重用 JupyterLab UI#

@jupyterlab/ui-components 包提供了 JupyterLab 核心广泛使用的 UI 元素,这些元素可以在您自己的扩展中重复使用。

例如,JupyterLab 核心中的所有图标都可以通过 LabIcon 重用。您还可以使用 LabIcon 创建您自己的自定义图标,这些图标将能够自动更改颜色以匹配当前的 JupyterLab 主题。

LabIcon - 设置和渲染图标#

LabIcon 是 JupyterLab 使用的图标类,是 JupyterLab v2.0 中引入的新图标系统的一部分。

JupyterLab 如何处理图标#

该 @jupyterlab/ui-components 包以一组 LabIcon 实例(目前约 80 个)的形式向 JupyterLab 的其余部分提供图标。核心 JupyterLab 包中的所有图标都使用这些 LabIcon 实例之一进行渲染。

在您自己的代码中使用图标#

您可以通过 import 语句在您自己的代码中使用任何 JupyterLab 图标。例如,要使用 jupyterIcon,您首先需要执行以下操作

import { jupyterIcon } from '@jupyterlab/ui-components';

如何将图标渲染到 DOM 节点#

可以使用 icon.element(...) 方法(其中 iconLabIcon 的任何实例)将图标添加为任何 divspan 节点的子节点。例如,要渲染 Jupyter 图标,您可以执行以下操作

jupyterIcon.element({
  container: elem,
  height: '16px',
  width: '16px',
  marginLeft: '2px'
});

其中 elem 是任何带有 divspan 标签的 HTMLElement。如上例所示,可以通过将 CSS 参数传递到 .element(...) 来设置图标的样式。可以使用任何有效的 CSS 参数(一个例外:蛇形大小写参数必须转换为驼峰式大小写:而不是 foo-bar: '8px',您需要使用 fooBar: '8px')。

如何将图标渲染为 React 组件#

图标也可以使用 React 进行渲染。该 icon.react 参数包含一个标准的 React 组件,该组件将在渲染时显示图标。与任何 React 组件一样,icon.react 可以以多种方式使用。

例如,以下是如何将 Jupyter 图标添加到另一个 React 组件的渲染树中

public render() {
  return (
    <div className="outer">
      <div className="inner">
        <jupyterIcon.react tag="span" right="7px" top="5px" />
        "and here's a text node"
      </div>
    </div>
  );
}

或者,您可以直接将图标渲染到任何现有的 DOM 节点 elem 中,方法是使用 ReactDOM 模块

ReactDOM.render(jupyterIcon.react, elem);

如果您使用 ReactDOM 进行渲染,并且如果 elem 节点曾经从 DOM 中移除,您首先需要清理它

ReactDOM.unmountComponentAtNode(elem);

此清理步骤不是 LabIcon 的特殊属性,而是任何直接在顶层由 ReactDOM 渲染的 React 组件都需要:未能调用 unmountComponentAtNode 会导致内存泄漏。

如何创建您自己的自定义 LabIcon#

您可以通过构造一个新的 LabIcon 实例来创建您自己的自定义图标

export const fooIcon = new LabIcon({
  name: 'barpkg:foo',
  svgstr: '<svg>...</svg>'
});

其中 name 应为“your-pkg:icon-name”形式,而 svgstr 是您图标的 svg 文件的原始内容。

如何从外部 svg 文件创建新的 LabIcon#

虽然您可以将 svg 直接复制粘贴到 LabIcon 构造函数中,但最佳实践是将每个图标的 svg 保存在其自己的单独 svg 文件中。您需要在项目的 src 文件夹的根目录下有一个 svg.d.ts 文件

// svg.d.ts

declare module '*.svg' {
  const value: string;
  export default value;
}

然后您可以 import svg 文件的内容

import fooSvgstr from 'path-to-your/foo.svg';

export const fooIcon = new LabIcon({
  name: 'barpkg:foo',
  svgstr: fooSvgstr
});

将图标颜色同步到 JupyterLab 主题#

带有类注释的示例 svg 可以在这里找到:ui-components/style/icons

您可以通过向您自定义 LabIcon 的图标 svg 的每个彩色元素添加适当的 class 注释来确保自定义 LabIcon 的颜色与当前 JupyterLab 主题的颜色同步。

换句话说,您的 svg 的每个具有 fill="..."stroke="..." 属性的元素也应该具有 class="jp-icon<whatever>" 属性。

可用的图标类#

与图标相关的 CSS 类在 ui-components/style/icons.css 中定义

显示的所有颜色均为标准浅色/深色主题,鼠标悬停以查看十六进制值。
jp-iconX:与主题背景对比#
  • jp-icon0 #111 / #fff
  • jp-icon1 #212121 / #fff
  • jp-icon2 #424242 / #eee
  • jp-icon3 #616161 / #bdbdbd
  • jp-icon4 #757575 / #757575

JupyterLab 中大多数单色图标(包括侧边栏和工具栏图标)都使用 jp-icon3 类进行着色。

对于浅色/深色主题,jp-icon0 对应于最暗/最亮的背景颜色,而 jp-icon1 稍微更亮/更暗,依此类推。

jp-icon-accentX:与主题背景匹配#
  • jp-icon-accent0 #fff / #111
  • jp-icon-accent1 #fff / #212121
  • jp-icon-accent2 #eee / #424242
  • jp-icon-accent3 #bdbdbd / #616161
  • jp-icon-accent4 #757575 / #757575

对于浅色/深色主题,jp-icon-accent0 对应于最亮/最暗的背景颜色,而 jp-icon-accent1 稍微更暗/更亮,依此类推。

向单色图标添加类#

对于大多数简单的单色图标,希望图标的颜色与应用程序背景形成强烈对比。可以使用以下其中一个 jp-iconX 类来实现这一点。

示例:复选标记图标

svg 源代码

<svg xmlns="http://www.w3.org/2000/svg" width="100" viewBox="0 0 24 24">
  <path class="jp-icon3" fill="#616161" d="M9 16.17L4.83 12l-1.42 1.41L9 19 21 7l-1.41-1.41z"/>
</svg>

渲染后的图标

向多色图标添加类#

对于更复杂的图标,每个需要与背景匹配的元素都应使用 jp-icon-accentX 类进行注释,而每个需要与背景形成对比的元素都应使用 jp-iconX 类进行注释。

示例:关闭圆圈图标

svg 源代码

<svg xmlns="http://www.w3.org/2000/svg" width="100" viewBox="0 0 24 24">
  <circle class="jp-icon3" fill="#616161" cx="12" cy="12" r="11"/>
  <rect class="jp-icon-accent0" fill="#fff" height="18" width="2" x="11" y="3" transform="rotate(315, 12, 12)"/>
  <rect class="jp-icon-accent0" fill="#fff" height="18" width="2" x="11" y="3" transform="rotate(45, 12, 12)"/>
</svg>

渲染后的图标

背景#

JupyterLab 中的图标处理#

在 JupyterLab 2.0 之前,大多数图标都是使用图标作为 CSS 背景的模式创建的

  • 在 CSS 中将图标的 svg 设置为 background-image

    /* CSS */
    
    .jp-FooIcon {
      background-image: url('path-to-your/foo.svg');
    }
    
  • 通过构建一个具有适当类的空 DOM 节点来将图标添加到 DOM 中

    // typescript
    
    const e = document.createElement('div');
    e.className = 'jp-FooIcon';
    document.body.append(e);
    

最终得到的是一个 DOM 节点,它将“foo”图标作为背景图像。

JupyterLab 2.0 之后,核心中的几乎所有图标现在都是使用 LabIcon 和图标作为内联 svg 的模式创建的

  • 从图标的名称和 svg 构建一个新的 LabIcon 实例

    // typescript
    
    // svgstr is the raw contents of an icon's svg file
    export const fooIcon = new LabIcon({
      name: 'barpkg:foo',
      svgstr: '<svg>...</svg>'
    });
    
  • 使用 LabIcon 实例的适当属性将图标添加到 DOM 中(使用 LabIcon.element() 直接创建 DOM 节点,或使用 LabIcon.react 获取图标作为 React 组件)

    // typescript
    
    const e = fooIcon.element();
    document.body.append(e);
    

最终得到的是一个 DOM 节点(默认情况下为“div”),它有一个内联 svg 节点作为子节点。

background-image 与内联 svg#

旧的图标作为 CSS 背景模式的最大限制是,作为 background-image 渲染的 svg 图像对 CSS 不可見。另一方面,作为内联 svg 节点渲染的图标完全暴露给 CSS。这使我们能够通过简单地修改 CSS 来动态更改图标样式,根据需要。最重要的是,这使我们能够根据 JupyterLab 的当前主题重新着色图标。