ui_components.rst 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346
  1. .. raw:: html
  2. <!--
  3. THIS FILE IS AUTOGENERATED, DO NOT EDIT
  4. Instead, make changes to docs sources in `packages/ui-components/docs`,
  5. then run "jlpm docs:init" to refresh the built docs
  6. -->
  7. .. _ui_components:
  8. Reusing JupyterLab UI
  9. =====================
  10. The `@jupyterlab/ui-components <../api/modules/ui_components.html>`__
  11. package provides UI elements that are widely used in JupyterLab core,
  12. and that can be reused in your own extensions.
  13. For example, all of the icons in JupyterLab core can be reused via
  14. ``LabIcon``. You can also use ``LabIcon`` to create your own custom
  15. icons that will be able to automatically change color to match the
  16. current JupyterLab theme.
  17. .. contents:: Explainer docs
  18. :local:
  19. :depth: 1
  20. ``LabIcon`` - set up and render icons
  21. -------------------------------------
  22. ``LabIcon`` is the icon class used by JupyterLab, and is part of the new
  23. icon system introduced in JupyterLab v2.0.
  24. How JupyterLab handles icons
  25. ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  26. The @jupyterlab/ui-components package provides icons to the rest of
  27. JupyterLab, in the form of a set of ``LabIcon`` instances (currently
  28. about 80). All of the icons in the core JupyterLab packages are rendered
  29. using one of these ``LabIcon`` instances.
  30. Using the icons in your own code
  31. ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  32. You can use any of JupyterLab icons in your own code via an ``import``
  33. statement. For example, to use ``jupyterIcon`` you would first do:
  34. .. code:: typescript
  35. import { jupyterIcon } from '@jupyterlab/ui-components';
  36. How to render an icon into a DOM node
  37. ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  38. Icons can be added as children to any ``div`` or ``span`` nodes using
  39. the ``icon.element(...)`` method (where ``icon`` is any instance of
  40. ``LabIcon``). For example, to render the Jupyter icon you could do:
  41. .. code:: typescript
  42. jupyterIcon.element({
  43. container: elem,
  44. height: '16px',
  45. width: '16px',
  46. marginLeft: '2px'
  47. });
  48. where ``elem`` is any ``HTMLElement`` with a ``div`` or ``span`` tag. As
  49. shown in the above example, the icon can be styled by passing CSS
  50. parameters into ``.element(...)``. Any valid CSS parameter can be used
  51. (one catch: snake case params do have to be converted to camel case:
  52. instead of ``foo-bar: '8px'``, you’d need to use ``fooBar: '8px'``.
  53. How to render an icon as a React component
  54. ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  55. Icons can also be rendered using React. The ``icon.react`` parameter
  56. holds a standard React component that will display the icon on render.
  57. Like any React component, ``icon.react`` can be used in various ways.
  58. For example, here is how you would add the Jupyter icon to the render
  59. tree of another React component:
  60. .. code::
  61. public render() {
  62. return (
  63. <div className="outer">
  64. <div className="inner">
  65. <jupyterIcon.react tag="span" right="7px" top="5px" />
  66. "and here's a text node"
  67. </div>
  68. </div>
  69. );
  70. }
  71. Alternatively, you can just render the icon directly into any existing
  72. DOM node ``elem`` by using the ``ReactDOM`` module:
  73. .. code:: typescript
  74. ReactDOM.render(jupyterIcon.react, elem);
  75. If do you use ``ReactDOM`` to render, and if the ``elem`` node is ever
  76. removed from the DOM, you’ll first need to clean it up:
  77. .. code:: typescript
  78. ReactDOM.unmountComponentAtNode(elem);
  79. This cleanup step is not a special property of ``LabIcon``, but is
  80. instead needed for any React component that is rendered directly at the
  81. top level by ``ReactDOM``: failure to call ``unmountComponentAtNode``
  82. can result in a `memory
  83. leak <https://stackoverflow.com/a/48198011/425458>`__.
  84. How to create your own custom ``LabIcon``
  85. ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  86. You can create your own custom icon by constructing a new instance of
  87. ``LabIcon``:
  88. .. code:: typescript
  89. export const fooIcon = new LabIcon({
  90. name: 'barpkg:foo',
  91. svgstr: '<svg>...</svg>'
  92. });
  93. where ``name`` should be of the form “your-pkg:icon-name”, and
  94. ``svgstr`` is the raw contents of your icon’s svg file.
  95. How to create a new ``LabIcon`` from an external svg file
  96. ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  97. Although you can copy-and-paste an svg directly into the ``LabIcon``
  98. constructor, the best practice is to keep the svg for each of your icons
  99. in its own separate svg file. You will need to have an ``svg.d.ts`` file
  100. at the root of your project’s ``src`` directory:
  101. .. code:: typescript
  102. // svg.d.ts
  103. declare module '*.svg' {
  104. const value: string;
  105. export default value;
  106. }
  107. You can then ``import`` the contents of an svg file:
  108. .. code:: typescript
  109. import fooSvgstr from 'path-to-your/foo.svg';
  110. export const fooIcon = new LabIcon({
  111. name: 'barpkg:foo',
  112. svgstr: fooSvgstr
  113. });
  114. Sync icon color to JupyterLab theme
  115. ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  116. .. raw:: html
  117. <em>Example svgs with class annotation can be found in <a href="https://github.com/jupyterlab/jupyterlab/tree/f0153e0258b32674c9aec106383ddf7b618cebab/packages/ui-components/style/icons">ui-components/style/icons</a></em>
  118. |
  119. | You can ensure that the colors of your custom ``LabIcon`` sync up to the colors of the current JupyterLab theme by adding appropriate ``class`` annotations to each colored element of your icon's svg.
  120. |
  121. | In other words, each element of your svg that a ``fill="..."`` or a ``stroke="..."`` property should also have a ``class="jp-icon<whatever>"`` property.
  122. Available icon classes
  123. """"""""""""""""""""""
  124. .. raw:: html
  125. <em>Icon-related CSS classes are defined in <a href="https://github.com/jupyterlab/jupyterlab/blob/f0153e0258b32674c9aec106383ddf7b618cebab/packages/ui-components/style/icons.css">ui-components/style/icons.css</a></em>
  126. |
  127. | All colors shown are for the standard light/dark theme, mouse over for hex values.
  128. ``jp-iconX``: contrast to theme background
  129. ''''''''''''''''''''''''''''''''''''''''''
  130. .. raw:: html
  131. <ul>
  132. <li>jp-icon0: <svg width="16" viewBox="0 0 1 1"><rect width="1" height="1" fill="#111"/><title>#111</title></svg> / <svg width="16" viewBox="0 0 1 1"><rect width="1" height="1" fill="#fff"/><title>#fff</title></svg></li>
  133. <li>jp-icon1: <svg width="16" viewBox="0 0 1 1"><rect width="1" height="1" fill="#212121"/><title>#212121</title></svg> / <svg width="16" viewBox="0 0 1 1"><rect width="1" height="1" fill="#fff"/><title>#fff</title></svg></li>
  134. <li>jp-icon2: <svg width="16" viewBox="0 0 1 1"><rect width="1" height="1" fill="#424242"/><title>#424242</title></svg> / <svg width="16" viewBox="0 0 1 1"><rect width="1" height="1" fill="#eee"/><title>#eee</title></svg></li>
  135. <li>jp-icon3: <svg width="16" viewBox="0 0 1 1"><rect width="1" height="1" fill="#616161"/><title>#616161</title></svg> / <svg width="16" viewBox="0 0 1 1"><rect width="1" height="1" fill="#bdbdbd"/><title>#bdbdbd</title></svg></li>
  136. <li>jp-icon4: <svg width="16" viewBox="0 0 1 1"><rect width="1" height="1" fill="#757575"/><title>#757575</title></svg> / <svg width="16" viewBox="0 0 1 1"><rect width="1" height="1" fill="#757575"/><title>#757575</title></svg></li>
  137. </ul>
  138. Most one-color icons in JupyterLab (including the sidebar and toolbar
  139. icons) are colored using the ``jp-icon3`` class.
  140. For light/dark themes, ``jp-icon0`` corresponds to the darkest/lightest
  141. background color, while ``jp-icon1`` is somewhat lighter/darker, and so
  142. forth.
  143. ``jp-icon-accentX``: match to theme background
  144. ''''''''''''''''''''''''''''''''''''''''''''''
  145. .. raw:: html
  146. <ul>
  147. <li>jp-icon-accent0: <svg width="16" viewBox="0 0 1 1"><rect width="1" height="1" fill="#fff"/><title>#fff</title></svg> / <svg width="16" viewBox="0 0 1 1"><rect width="1" height="1" fill="#111"/><title>#111</title></svg></li>
  148. <li>jp-icon-accent1: <svg width="16" viewBox="0 0 1 1"><rect width="1" height="1" fill="#fff"/><title>#fff</title></svg> / <svg width="16" viewBox="0 0 1 1"><rect width="1" height="1" fill="#212121"/><title>#212121</title></svg></li>
  149. <li>jp-icon-accent2: <svg width="16" viewBox="0 0 1 1"><rect width="1" height="1" fill="#eee"/><title>#eee</title></svg> / <svg width="16" viewBox="0 0 1 1"><rect width="1" height="1" fill="#424242"/><title>#424242</title></svg></li>
  150. <li>jp-icon-accent3: <svg width="16" viewBox="0 0 1 1"><rect width="1" height="1" fill="#bdbdbd"/><title>#bdbdbd</title></svg> / <svg width="16" viewBox="0 0 1 1"><rect width="1" height="1" fill="#616161"/><title>#616161</title></svg></li>
  151. <li>jp-icon-accent4: <svg width="16" viewBox="0 0 1 1"><rect width="1" height="1" fill="#757575"/><title>#757575</title></svg> / <svg width="16" viewBox="0 0 1 1"><rect width="1" height="1" fill="#757575"/><title>#757575</title></svg></li>
  152. </ul>
  153. For light/dark themes, ``jp-icon-accent0`` corresponds to the
  154. lightest/darkest background color, while ``jp-icon-accent1`` is somewhat
  155. darker/lighter, and so forth.
  156. Adding classes to a one-color icon
  157. """"""""""""""""""""""""""""""""""
  158. For most simple, one-color icons, it is desirable for the icon's color
  159. to strongly contrast with that of the application's background. You can
  160. achieve this using one of the ``jp-iconX`` classes.
  161. **Example: check icon**
  162. *svg source:*
  163. .. code:: html
  164. <svg xmlns="http://www.w3.org/2000/svg" width="100" viewBox="0 0 24 24">
  165. <path class="jp-icon3" fill="#616161" d="M9 16.17L4.83 12l-1.42 1.41L9 19 21 7l-1.41-1.41z"/>
  166. </svg>
  167. *rendered icon:*
  168. .. raw:: html
  169. <svg xmlns="http://www.w3.org/2000/svg" width="100" viewBox="0 0 24 24">
  170. <path class="jp-icon3" fill="#616161" d="M9 16.17L4.83 12l-1.42 1.41L9 19 21 7l-1.41-1.41z"/>
  171. </svg>
  172. Adding classes to a multi-colored icon
  173. """"""""""""""""""""""""""""""""""""""
  174. For more complex icons, each element that needs to match the background
  175. should be annotated with a ``jp-icon-accentX`` class, while each element
  176. that needs to contrast with the background should be annotated with a
  177. ``jp-iconX`` class.
  178. **Example: close-circle icon**
  179. *svg source:*
  180. .. code:: html
  181. <svg xmlns="http://www.w3.org/2000/svg" width="100" viewBox="0 0 24 24">
  182. <circle class="jp-icon3" fill="#616161" cx="12" cy="12" r="11"/>
  183. <rect class="jp-icon-accent0" fill="#fff" height="18" width="2" x="11" y="3" transform="rotate(315, 12, 12)"/>
  184. <rect class="jp-icon-accent0" fill="#fff" height="18" width="2" x="11" y="3" transform="rotate(45, 12, 12)"/>
  185. </svg>
  186. *rendered icon:*
  187. .. raw:: html
  188. <svg xmlns="http://www.w3.org/2000/svg" width="100" viewBox="0 0 24 24">
  189. <circle class="jp-icon3" fill="#616161" cx="12" cy="12" r="11"/>
  190. <rect class="jp-icon-accent0" fill="#fff" height="18" width="2" x="11" y="3" transform="rotate(315, 12, 12)"/>
  191. <rect class="jp-icon-accent0" fill="#fff" height="18" width="2" x="11" y="3" transform="rotate(45, 12, 12)"/>
  192. </svg>
  193. Background
  194. ^^^^^^^^^^
  195. Icon handling in Jupyterlab
  196. """""""""""""""""""""""""""
  197. Pre JupyterLab 2.0, most icons were created using the icons-as-css-background
  198. pattern:
  199. - Set up the icon’s svg as a ``background-image`` in CSS:
  200. .. code:: css
  201. /* CSS */
  202. .jp-FooIcon {
  203. background-image: url('path-to-your/foo.svg');
  204. }
  205. - Add the icon to the DOM by constructing an otherwise empty DOM node
  206. with the appropriate class:
  207. .. code:: typescript
  208. // typescript
  209. const e = document.createElement('div');
  210. e.className = 'jp-FooIcon';
  211. document.body.append(e);
  212. What you end up with is a single DOM node that has the “foo” icon as a
  213. background image.
  214. Post JupyterLab 2.0, nearly all icons in core are now created using
  215. `LabIcon <https://github.com/jupyterlab/jupyterlab/blob/f0153e0258b32674c9aec106383ddf7b618cebab/packages/ui-components/src/icon/labicon.tsx>`__
  216. and the icons-as-inline-svg pattern:
  217. - Construct a new instance of LabIcon from the icon’s name and svg:
  218. .. code:: typescript
  219. // typescript
  220. // svgstr is the raw contents of an icon's svg file
  221. export const fooIcon = new LabIcon({
  222. name: 'barpkg:foo',
  223. svgstr: '<svg>...</svg>'
  224. });
  225. - Add the icon to the DOM using the appropriate property of your
  226. LabIcon instance (either LabIcon.element() to directly create a DOM
  227. node, or LabIcon.react to get the icon as a react component):
  228. .. code:: typescript
  229. // typescript
  230. const e = fooIcon.element();
  231. document.body.append(e);
  232. What you end up with is a DOM node (by default a ‘div’) that has an
  233. inline svg node as a child.
  234. ``background-image`` vs inline svg
  235. """"""""""""""""""""""""""""""""""
  236. The big limitation of the old icon-as-css-background pattern is that svg
  237. images rendered as ``background-image`` are invisible to CSS. On the
  238. other hand, an icon rendered as an inline svg node is fully exposed to
  239. the CSS. This allows us to dynamically change icon styling as needed
  240. simply by modifying our CSS. Most importantly, this allows us to recolor
  241. icons according to Jupyterlab’s current theme.