复用 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>
  );
}

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

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 中找到

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

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

可用图标类#

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

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

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

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

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

对于亮/暗主题,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 背景”模式创建的

  • 将图标的 svg 设置为 CSS 中的 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);
    

您最终得到的是一个带有“foo”图标作为背景图像的单个 DOM 节点。

在 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 的当前主题重新着色图标。