diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 11292ccc..2a1da782 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -48,7 +48,9 @@ jobs: yarn- - name: Install dependencies - run: python -m pip install -U jupyterlab~=4.0 + # Use JLab 4.0.x branch because otherwise this will not bring + # the current toolkit version but the core version one. + run: python -m pip install -U jupyterlab~=4.0.0 - name: Build the extension run: | set -eux @@ -94,6 +96,6 @@ jobs: sudo rm -rf $(which node) sudo rm -rf $(which node) pip install myextension.tar.gz - pip install jupyterlab + pip install "jupyterlab~=4.0.0" jupyter labextension list 2>&1 | grep -ie "jupyter-ui-demo.*enabled" python -m jupyterlab.browser_check --no-browser-test diff --git a/binder/environment.yml b/binder/environment.yml index b363f5ee..04ed56a7 100644 --- a/binder/environment.yml +++ b/binder/environment.yml @@ -12,8 +12,8 @@ channels: dependencies: # runtime dependencies - python >=3.10,<3.11.0a0 - - jupyterlab >=4.0.0,<5 + - jupyterlab >=4.0.0,<4.1.0 # labextension build dependencies - - nodejs >=18,<19 + - nodejs >=20,<21 - pip - wheel diff --git a/packages/components/src/breadcrumb-item/breadcrumb-item.styles.ts b/packages/components/src/breadcrumb-item/breadcrumb-item.styles.ts index 542c8cc9..5e5656ab 100644 --- a/packages/components/src/breadcrumb-item/breadcrumb-item.styles.ts +++ b/packages/components/src/breadcrumb-item/breadcrumb-item.styles.ts @@ -119,7 +119,8 @@ export const breadcrumbItemStyles: FoundationElementTemplate< display: flex; } - ::slotted(svg) { + ::slotted(svg), + ::slotted(jp-icon) { /* TODO: adaptive typography https://github.com/microsoft/fast/issues/2432 */ width: 16px; height: 16px; diff --git a/packages/components/src/breadcrumb-item/breadcrumb-item.test.ts-snapshots/breadcrumb-item-with-end-icon-chromium-linux.png b/packages/components/src/breadcrumb-item/breadcrumb-item.test.ts-snapshots/breadcrumb-item-with-end-icon-chromium-linux.png index 99f80fb1..1ed06b6c 100644 Binary files a/packages/components/src/breadcrumb-item/breadcrumb-item.test.ts-snapshots/breadcrumb-item-with-end-icon-chromium-linux.png and b/packages/components/src/breadcrumb-item/breadcrumb-item.test.ts-snapshots/breadcrumb-item-with-end-icon-chromium-linux.png differ diff --git a/packages/components/src/breadcrumb-item/breadcrumb-item.test.ts-snapshots/breadcrumb-item-with-end-icon-firefox-linux.png b/packages/components/src/breadcrumb-item/breadcrumb-item.test.ts-snapshots/breadcrumb-item-with-end-icon-firefox-linux.png index 20648e8a..66501241 100644 Binary files a/packages/components/src/breadcrumb-item/breadcrumb-item.test.ts-snapshots/breadcrumb-item-with-end-icon-firefox-linux.png and b/packages/components/src/breadcrumb-item/breadcrumb-item.test.ts-snapshots/breadcrumb-item-with-end-icon-firefox-linux.png differ diff --git a/packages/components/src/breadcrumb-item/breadcrumb-item.test.ts-snapshots/breadcrumb-item-with-end-icon-webkit-linux.png b/packages/components/src/breadcrumb-item/breadcrumb-item.test.ts-snapshots/breadcrumb-item-with-end-icon-webkit-linux.png index 9a96280c..879096cc 100644 Binary files a/packages/components/src/breadcrumb-item/breadcrumb-item.test.ts-snapshots/breadcrumb-item-with-end-icon-webkit-linux.png and b/packages/components/src/breadcrumb-item/breadcrumb-item.test.ts-snapshots/breadcrumb-item-with-end-icon-webkit-linux.png differ diff --git a/packages/components/src/breadcrumb-item/breadcrumb-item.test.ts-snapshots/breadcrumb-item-with-start-icon-chromium-linux.png b/packages/components/src/breadcrumb-item/breadcrumb-item.test.ts-snapshots/breadcrumb-item-with-start-icon-chromium-linux.png index b890cc6a..1a2e3b2f 100644 Binary files a/packages/components/src/breadcrumb-item/breadcrumb-item.test.ts-snapshots/breadcrumb-item-with-start-icon-chromium-linux.png and b/packages/components/src/breadcrumb-item/breadcrumb-item.test.ts-snapshots/breadcrumb-item-with-start-icon-chromium-linux.png differ diff --git a/packages/components/src/breadcrumb-item/breadcrumb-item.test.ts-snapshots/breadcrumb-item-with-start-icon-firefox-linux.png b/packages/components/src/breadcrumb-item/breadcrumb-item.test.ts-snapshots/breadcrumb-item-with-start-icon-firefox-linux.png index 5c556ac2..c2d63a96 100644 Binary files a/packages/components/src/breadcrumb-item/breadcrumb-item.test.ts-snapshots/breadcrumb-item-with-start-icon-firefox-linux.png and b/packages/components/src/breadcrumb-item/breadcrumb-item.test.ts-snapshots/breadcrumb-item-with-start-icon-firefox-linux.png differ diff --git a/packages/components/src/breadcrumb-item/breadcrumb-item.test.ts-snapshots/breadcrumb-item-with-start-icon-webkit-linux.png b/packages/components/src/breadcrumb-item/breadcrumb-item.test.ts-snapshots/breadcrumb-item-with-start-icon-webkit-linux.png index db9bb127..714c912b 100644 Binary files a/packages/components/src/breadcrumb-item/breadcrumb-item.test.ts-snapshots/breadcrumb-item-with-start-icon-webkit-linux.png and b/packages/components/src/breadcrumb-item/breadcrumb-item.test.ts-snapshots/breadcrumb-item-with-start-icon-webkit-linux.png differ diff --git a/packages/components/src/breadcrumb/breadcrumb.test.ts-snapshots/breadcrumb-with-end-icon-chromium-linux.png b/packages/components/src/breadcrumb/breadcrumb.test.ts-snapshots/breadcrumb-with-end-icon-chromium-linux.png index 38db1463..9cfae4c7 100644 Binary files a/packages/components/src/breadcrumb/breadcrumb.test.ts-snapshots/breadcrumb-with-end-icon-chromium-linux.png and b/packages/components/src/breadcrumb/breadcrumb.test.ts-snapshots/breadcrumb-with-end-icon-chromium-linux.png differ diff --git a/packages/components/src/breadcrumb/breadcrumb.test.ts-snapshots/breadcrumb-with-end-icon-firefox-linux.png b/packages/components/src/breadcrumb/breadcrumb.test.ts-snapshots/breadcrumb-with-end-icon-firefox-linux.png index 12b842b5..c00e8e20 100644 Binary files a/packages/components/src/breadcrumb/breadcrumb.test.ts-snapshots/breadcrumb-with-end-icon-firefox-linux.png and b/packages/components/src/breadcrumb/breadcrumb.test.ts-snapshots/breadcrumb-with-end-icon-firefox-linux.png differ diff --git a/packages/components/src/breadcrumb/breadcrumb.test.ts-snapshots/breadcrumb-with-end-icon-webkit-linux.png b/packages/components/src/breadcrumb/breadcrumb.test.ts-snapshots/breadcrumb-with-end-icon-webkit-linux.png index 8a405e78..d78e9b31 100644 Binary files a/packages/components/src/breadcrumb/breadcrumb.test.ts-snapshots/breadcrumb-with-end-icon-webkit-linux.png and b/packages/components/src/breadcrumb/breadcrumb.test.ts-snapshots/breadcrumb-with-end-icon-webkit-linux.png differ diff --git a/packages/components/src/breadcrumb/breadcrumb.test.ts-snapshots/breadcrumb-with-start-icon-chromium-linux.png b/packages/components/src/breadcrumb/breadcrumb.test.ts-snapshots/breadcrumb-with-start-icon-chromium-linux.png index f54bd245..2aa72339 100644 Binary files a/packages/components/src/breadcrumb/breadcrumb.test.ts-snapshots/breadcrumb-with-start-icon-chromium-linux.png and b/packages/components/src/breadcrumb/breadcrumb.test.ts-snapshots/breadcrumb-with-start-icon-chromium-linux.png differ diff --git a/packages/components/src/breadcrumb/breadcrumb.test.ts-snapshots/breadcrumb-with-start-icon-firefox-linux.png b/packages/components/src/breadcrumb/breadcrumb.test.ts-snapshots/breadcrumb-with-start-icon-firefox-linux.png index 60a5d1d3..3e939ebc 100644 Binary files a/packages/components/src/breadcrumb/breadcrumb.test.ts-snapshots/breadcrumb-with-start-icon-firefox-linux.png and b/packages/components/src/breadcrumb/breadcrumb.test.ts-snapshots/breadcrumb-with-start-icon-firefox-linux.png differ diff --git a/packages/components/src/breadcrumb/breadcrumb.test.ts-snapshots/breadcrumb-with-start-icon-webkit-linux.png b/packages/components/src/breadcrumb/breadcrumb.test.ts-snapshots/breadcrumb-with-start-icon-webkit-linux.png index 1ade7cc4..cbc50a9c 100644 Binary files a/packages/components/src/breadcrumb/breadcrumb.test.ts-snapshots/breadcrumb-with-start-icon-webkit-linux.png and b/packages/components/src/breadcrumb/breadcrumb.test.ts-snapshots/breadcrumb-with-start-icon-webkit-linux.png differ diff --git a/packages/components/src/button/button.test.ts-snapshots/button-icon-only-chromium-linux.png b/packages/components/src/button/button.test.ts-snapshots/button-icon-only-chromium-linux.png index aaee66aa..7f707a0d 100644 Binary files a/packages/components/src/button/button.test.ts-snapshots/button-icon-only-chromium-linux.png and b/packages/components/src/button/button.test.ts-snapshots/button-icon-only-chromium-linux.png differ diff --git a/packages/components/src/button/button.test.ts-snapshots/button-icon-only-firefox-linux.png b/packages/components/src/button/button.test.ts-snapshots/button-icon-only-firefox-linux.png index c01871f2..97af638a 100644 Binary files a/packages/components/src/button/button.test.ts-snapshots/button-icon-only-firefox-linux.png and b/packages/components/src/button/button.test.ts-snapshots/button-icon-only-firefox-linux.png differ diff --git a/packages/components/src/button/button.test.ts-snapshots/button-icon-only-webkit-linux.png b/packages/components/src/button/button.test.ts-snapshots/button-icon-only-webkit-linux.png index c8636f54..46261fba 100644 Binary files a/packages/components/src/button/button.test.ts-snapshots/button-icon-only-webkit-linux.png and b/packages/components/src/button/button.test.ts-snapshots/button-icon-only-webkit-linux.png differ diff --git a/packages/components/src/button/button.test.ts-snapshots/button-with-start-icon-chromium-linux.png b/packages/components/src/button/button.test.ts-snapshots/button-with-start-icon-chromium-linux.png index 04ef7ae9..eac33314 100644 Binary files a/packages/components/src/button/button.test.ts-snapshots/button-with-start-icon-chromium-linux.png and b/packages/components/src/button/button.test.ts-snapshots/button-with-start-icon-chromium-linux.png differ diff --git a/packages/components/src/button/button.test.ts-snapshots/button-with-start-icon-firefox-linux.png b/packages/components/src/button/button.test.ts-snapshots/button-with-start-icon-firefox-linux.png index 479d3b06..431197f5 100644 Binary files a/packages/components/src/button/button.test.ts-snapshots/button-with-start-icon-firefox-linux.png and b/packages/components/src/button/button.test.ts-snapshots/button-with-start-icon-firefox-linux.png differ diff --git a/packages/components/src/button/button.test.ts-snapshots/button-with-start-icon-webkit-linux.png b/packages/components/src/button/button.test.ts-snapshots/button-with-start-icon-webkit-linux.png index 38371dd7..1d236bba 100644 Binary files a/packages/components/src/button/button.test.ts-snapshots/button-with-start-icon-webkit-linux.png and b/packages/components/src/button/button.test.ts-snapshots/button-with-start-icon-webkit-linux.png differ diff --git a/packages/components/src/button/index.ts b/packages/components/src/button/index.ts index c65e1cf1..96d7079b 100644 --- a/packages/components/src/button/index.ts +++ b/packages/components/src/button/index.ts @@ -5,6 +5,7 @@ import { attr } from '@microsoft/fast-element'; import { Button, buttonTemplate as template } from '@microsoft/fast-foundation'; import { buttonStyles as styles } from './button.styles.js'; +import { Icon } from '../icon/index.js'; /** * Scale locally an element. @@ -73,9 +74,8 @@ class JupyterButton extends Button { ); if ( slottedElements.length === 1 && - (slottedElements[0] instanceof SVGElement || - slottedElements[0].classList.contains('fa') || - slottedElements[0].classList.contains('fas')) + (slottedElements[0] instanceof Icon || + slottedElements[0] instanceof SVGElement) ) { this.control.classList.add('icon-only'); } else { diff --git a/packages/components/src/combobox/combobox.test.ts-snapshots/combobox-custom-indicator-chromium-linux.png b/packages/components/src/combobox/combobox.test.ts-snapshots/combobox-custom-indicator-chromium-linux.png index eeb69a02..70028375 100644 Binary files a/packages/components/src/combobox/combobox.test.ts-snapshots/combobox-custom-indicator-chromium-linux.png and b/packages/components/src/combobox/combobox.test.ts-snapshots/combobox-custom-indicator-chromium-linux.png differ diff --git a/packages/components/src/combobox/combobox.test.ts-snapshots/combobox-custom-indicator-firefox-linux.png b/packages/components/src/combobox/combobox.test.ts-snapshots/combobox-custom-indicator-firefox-linux.png index 2e244a6e..19fa1778 100644 Binary files a/packages/components/src/combobox/combobox.test.ts-snapshots/combobox-custom-indicator-firefox-linux.png and b/packages/components/src/combobox/combobox.test.ts-snapshots/combobox-custom-indicator-firefox-linux.png differ diff --git a/packages/components/src/custom-elements.ts b/packages/components/src/custom-elements.ts index cc79ff10..f4235e3a 100644 --- a/packages/components/src/custom-elements.ts +++ b/packages/components/src/custom-elements.ts @@ -24,6 +24,7 @@ import type { DesignSystemProvider } from './design-system-provider/index.js'; import type { Dialog } from './dialog/index.js'; import type { Disclosure } from './disclosure/index.js'; import type { Divider } from './divider/index.js'; +import type { Icon } from './icon/index.js'; import type { Listbox } from './listbox/index.js'; import type { Menu } from './menu/index.js'; import type { MenuItem } from './menu-item/index.js'; diff --git a/packages/components/src/date-field/date-field.test.ts-snapshots/date-field-with-start-icon-chromium-linux.png b/packages/components/src/date-field/date-field.test.ts-snapshots/date-field-with-start-icon-chromium-linux.png index 28e1e20a..90a9407b 100644 Binary files a/packages/components/src/date-field/date-field.test.ts-snapshots/date-field-with-start-icon-chromium-linux.png and b/packages/components/src/date-field/date-field.test.ts-snapshots/date-field-with-start-icon-chromium-linux.png differ diff --git a/packages/components/src/date-field/date-field.test.ts-snapshots/date-field-with-start-icon-firefox-linux.png b/packages/components/src/date-field/date-field.test.ts-snapshots/date-field-with-start-icon-firefox-linux.png index b05c1791..58cd672d 100644 Binary files a/packages/components/src/date-field/date-field.test.ts-snapshots/date-field-with-start-icon-firefox-linux.png and b/packages/components/src/date-field/date-field.test.ts-snapshots/date-field-with-start-icon-firefox-linux.png differ diff --git a/packages/components/src/date-field/date-field.test.ts-snapshots/date-field-with-start-icon-webkit-linux.png b/packages/components/src/date-field/date-field.test.ts-snapshots/date-field-with-start-icon-webkit-linux.png index ebf47073..adee09b3 100644 Binary files a/packages/components/src/date-field/date-field.test.ts-snapshots/date-field-with-start-icon-webkit-linux.png and b/packages/components/src/date-field/date-field.test.ts-snapshots/date-field-with-start-icon-webkit-linux.png differ diff --git a/packages/components/src/icon/icon.stories.ts b/packages/components/src/icon/icon.stories.ts index e7e7eb94..89cbffc5 100644 --- a/packages/components/src/icon/icon.stories.ts +++ b/packages/components/src/icon/icon.stories.ts @@ -4,9 +4,11 @@ import { Icon } from './index'; // Register the icon with proper SVG formatting Icon.register({ name: 'search', - svgStr: ` - - + svgStr: ` + ` }); @@ -25,8 +27,12 @@ const Template: StoryFn = (args, context): string => { setTimeout(() => { Icon.register({ name: 'search', - svgStr: ` - ` + svgStr: ` + + ` }); }, args.delay); } diff --git a/packages/components/src/icon/icon.styles.ts b/packages/components/src/icon/icon.styles.ts new file mode 100644 index 00000000..87c97ecc --- /dev/null +++ b/packages/components/src/icon/icon.styles.ts @@ -0,0 +1,23 @@ +// Copyright (c) Jupyter Development Team. +// Distributed under the terms of the Modified BSD License. + +import { css, ElementStyles } from '@microsoft/fast-element'; +import { display } from '@microsoft/fast-foundation'; +import { heightNumber } from '../styles/index.js'; + +/** + * Styles for Badge + * @public + */ +export const iconStyles: ElementStyles = css` + ${display('inline-block')} :host { + inline-size: ${heightNumber}; + block-size: ${heightNumber}; + } + + :host svg { + display: block; + width: 100%; + height: 100%; + } +`; diff --git a/packages/components/src/icon/icon.test.ts-snapshots/icon-change-icon-chromium-linux.png b/packages/components/src/icon/icon.test.ts-snapshots/icon-change-icon-chromium-linux.png index 8ed077c4..451b55ca 100644 Binary files a/packages/components/src/icon/icon.test.ts-snapshots/icon-change-icon-chromium-linux.png and b/packages/components/src/icon/icon.test.ts-snapshots/icon-change-icon-chromium-linux.png differ diff --git a/packages/components/src/icon/icon.test.ts-snapshots/icon-change-icon-firefox-linux.png b/packages/components/src/icon/icon.test.ts-snapshots/icon-change-icon-firefox-linux.png index 05bfb87c..d079e8a1 100644 Binary files a/packages/components/src/icon/icon.test.ts-snapshots/icon-change-icon-firefox-linux.png and b/packages/components/src/icon/icon.test.ts-snapshots/icon-change-icon-firefox-linux.png differ diff --git a/packages/components/src/icon/icon.test.ts-snapshots/icon-change-icon-webkit-linux.png b/packages/components/src/icon/icon.test.ts-snapshots/icon-change-icon-webkit-linux.png index 3298f099..e8d51eb5 100644 Binary files a/packages/components/src/icon/icon.test.ts-snapshots/icon-change-icon-webkit-linux.png and b/packages/components/src/icon/icon.test.ts-snapshots/icon-change-icon-webkit-linux.png differ diff --git a/packages/components/src/icon/icon.test.ts-snapshots/icon-default-chromium-linux.png b/packages/components/src/icon/icon.test.ts-snapshots/icon-default-chromium-linux.png index 662d255c..bfb380d3 100644 Binary files a/packages/components/src/icon/icon.test.ts-snapshots/icon-default-chromium-linux.png and b/packages/components/src/icon/icon.test.ts-snapshots/icon-default-chromium-linux.png differ diff --git a/packages/components/src/icon/icon.test.ts-snapshots/icon-default-firefox-linux.png b/packages/components/src/icon/icon.test.ts-snapshots/icon-default-firefox-linux.png index 49f57c6d..e2a8aee8 100644 Binary files a/packages/components/src/icon/icon.test.ts-snapshots/icon-default-firefox-linux.png and b/packages/components/src/icon/icon.test.ts-snapshots/icon-default-firefox-linux.png differ diff --git a/packages/components/src/icon/icon.test.ts-snapshots/icon-default-webkit-linux.png b/packages/components/src/icon/icon.test.ts-snapshots/icon-default-webkit-linux.png index e464b656..37661fb3 100644 Binary files a/packages/components/src/icon/icon.test.ts-snapshots/icon-default-webkit-linux.png and b/packages/components/src/icon/icon.test.ts-snapshots/icon-default-webkit-linux.png differ diff --git a/packages/components/src/icon/index.ts b/packages/components/src/icon/index.ts index 41f75dbe..c8e0c487 100644 --- a/packages/components/src/icon/index.ts +++ b/packages/components/src/icon/index.ts @@ -1,11 +1,19 @@ -import { - FASTElement, - customElement, - attr, - html -} from '@microsoft/fast-element'; +import { DOM, FASTElement, customElement, attr } from '@microsoft/fast-element'; +import { iconStyles as styles } from './icon.styles'; -const template = html`
`; +/** + * Icon definition + */ +export interface IconDefinition { + /** + * Icon unique name + */ + name: string; + /** + * Icon SVG as string + */ + svgStr: string; +} /** * Icon component @@ -19,24 +27,24 @@ const template = html`
`; */ @customElement({ name: 'jp-icon', - template + styles }) export class Icon extends FASTElement { - /** - * Name of the icon to display. - */ - @attr name: string; - private static iconsMap = new Map(); private static _defaultIcon = - ''; + DOM.createHTML(` + + `); /** * Register a new icon. * - * @param options { name: Icon unique name, svgStr: Icon SVG as string } + * @param options Icon definition */ - static register(options: { name: string; svgStr: string }): void { + static register(options: IconDefinition): void { if (Icon.iconsMap.has(options.name)) { console.warn( `Redefining previously loaded icon svgStr. name: ${ @@ -46,11 +54,11 @@ export class Icon extends FASTElement { }` ); } - Icon.iconsMap.set(options.name, options.svgStr); + Icon.iconsMap.set(options.name, DOM.createHTML(options.svgStr)); // Rerender all existing icons with the same name document - .querySelectorAll(`jp-icon[name="${options.name}"]`) + ?.querySelectorAll(`jp-icon[name="${options.name}"]`) .forEach((node: HTMLElement) => { node.setAttribute('name', ''); node.setAttribute('name', options.name); @@ -58,7 +66,7 @@ export class Icon extends FASTElement { } /** - * Set a new default icon. + * Set the default icon. * * @param svgStr The SVG string to be used as the default icon. */ @@ -76,10 +84,33 @@ export class Icon extends FASTElement { return Icon._defaultIcon; } + /** + * Name of the icon to display. + */ + @attr name: string; + nameChanged() { + if (this.shadowRoot) { + this.shadowRoot.innerHTML = this.getSvg(); + } + } + + /** + * The connected callback for this FASTElement. + * @remarks + * This method is invoked by the platform whenever this FASTElement + * becomes connected to the document. + */ + connectedCallback(): void { + super.connectedCallback(); + this.nameChanged(); + } + /** * Get the icon SVG */ - getSvg(): string { + protected getSvg(): string { return Icon.iconsMap.get(this.name) ?? Icon.defaultIcon(); } } + +export { styles as iconStyles }; diff --git a/packages/components/src/index.ts b/packages/components/src/index.ts index 7456f380..a5d01cd2 100644 --- a/packages/components/src/index.ts +++ b/packages/components/src/index.ts @@ -36,6 +36,7 @@ export * from './design-tokens.js'; export * from './dialog/index.js'; export * from './disclosure/index.js'; export * from './divider/index.js'; +export * from './icon/index.js'; export * from './listbox/index.js'; export * from './menu/index.js'; export * from './menu-item/index.js'; diff --git a/packages/components/src/menu-item/menu-item.styles.ts b/packages/components/src/menu-item/menu-item.styles.ts index c4668950..08fb1db9 100644 --- a/packages/components/src/menu-item/menu-item.styles.ts +++ b/packages/components/src/menu-item/menu-item.styles.ts @@ -144,7 +144,8 @@ export const menuItemStyles: FoundationElementTemplate< :host([disabled]:hover) .start, :host([disabled]:hover) .end, - :host([disabled]:hover)::slotted(svg) { + :host([disabled]:hover)::slotted(svg), + :host([disabled]:hover)::slotted(jp-icon) { fill: ${neutralForegroundRest}; } @@ -168,7 +169,8 @@ export const menuItemStyles: FoundationElementTemplate< justify-content: center; } - ::slotted(svg) { + ::slotted(svg), + ::slotted(jp-icon) { /* TODO: adaptive typography https://github.com/microsoft/fast/issues/2432 */ width: 16px; height: 16px; @@ -183,9 +185,11 @@ export const menuItemStyles: FoundationElementTemplate< :host(:hover) .start, :host(:hover) .end, :host(:hover)::slotted(svg), + :host(:hover)::slotted(jp-icon), :host(:active) .start, :host(:active) .end, - :host(:active)::slotted(svg) { + :host(:active)::slotted(svg), + :host(:active)::slotted(jp-icon) { fill: ${neutralForegroundRest}; } @@ -331,9 +335,11 @@ export const menuItemStyles: FoundationElementTemplate< :host(:hover) .start, :host(:hover) .end, :host(:hover)::slotted(svg), + :host(:hover)::slotted(jp-icon), :host(:active) .start, :host(:active) .end, - :host(:active)::slotted(svg) { + :host(:active)::slotted(svg), + :host(:active)::slotted(jp-icon) { fill: ${SystemColors.HighlightText}; } @@ -356,7 +362,8 @@ export const menuItemStyles: FoundationElementTemplate< :host([disabled]:hover), :host([disabled]:hover) .start, :host([disabled]:hover) .end, - :host([disabled]:hover)::slotted(svg) { + :host([disabled]:hover)::slotted(svg), + :host([disabled]:hover)::slotted(jp-icon) { background: ${SystemColors.Canvas}; color: ${SystemColors.GrayText}; fill: currentcolor; diff --git a/packages/components/src/menu/menu.test.ts-snapshots/menu-default-chromium-linux.png b/packages/components/src/menu/menu.test.ts-snapshots/menu-default-chromium-linux.png index 355ae6d8..63b1b821 100644 Binary files a/packages/components/src/menu/menu.test.ts-snapshots/menu-default-chromium-linux.png and b/packages/components/src/menu/menu.test.ts-snapshots/menu-default-chromium-linux.png differ diff --git a/packages/components/src/menu/menu.test.ts-snapshots/menu-default-firefox-linux.png b/packages/components/src/menu/menu.test.ts-snapshots/menu-default-firefox-linux.png index d25b2f09..4fe5df2a 100644 Binary files a/packages/components/src/menu/menu.test.ts-snapshots/menu-default-firefox-linux.png and b/packages/components/src/menu/menu.test.ts-snapshots/menu-default-firefox-linux.png differ diff --git a/packages/components/src/menu/menu.test.ts-snapshots/menu-default-webkit-linux.png b/packages/components/src/menu/menu.test.ts-snapshots/menu-default-webkit-linux.png index a54441fb..a8ae679a 100644 Binary files a/packages/components/src/menu/menu.test.ts-snapshots/menu-default-webkit-linux.png and b/packages/components/src/menu/menu.test.ts-snapshots/menu-default-webkit-linux.png differ diff --git a/packages/components/src/number-field/number-field.test.ts-snapshots/number-field-with-start-icon-chromium-linux.png b/packages/components/src/number-field/number-field.test.ts-snapshots/number-field-with-start-icon-chromium-linux.png index 3ee0e8f4..38a91a33 100644 Binary files a/packages/components/src/number-field/number-field.test.ts-snapshots/number-field-with-start-icon-chromium-linux.png and b/packages/components/src/number-field/number-field.test.ts-snapshots/number-field-with-start-icon-chromium-linux.png differ diff --git a/packages/components/src/number-field/number-field.test.ts-snapshots/number-field-with-start-icon-firefox-linux.png b/packages/components/src/number-field/number-field.test.ts-snapshots/number-field-with-start-icon-firefox-linux.png index ef187137..7e04df78 100644 Binary files a/packages/components/src/number-field/number-field.test.ts-snapshots/number-field-with-start-icon-firefox-linux.png and b/packages/components/src/number-field/number-field.test.ts-snapshots/number-field-with-start-icon-firefox-linux.png differ diff --git a/packages/components/src/number-field/number-field.test.ts-snapshots/number-field-with-start-icon-webkit-linux.png b/packages/components/src/number-field/number-field.test.ts-snapshots/number-field-with-start-icon-webkit-linux.png index 328c9eb9..11c6d1d2 100644 Binary files a/packages/components/src/number-field/number-field.test.ts-snapshots/number-field-with-start-icon-webkit-linux.png and b/packages/components/src/number-field/number-field.test.ts-snapshots/number-field-with-start-icon-webkit-linux.png differ diff --git a/packages/components/src/option/option.styles.ts b/packages/components/src/option/option.styles.ts index e4269ef5..1fa03603 100644 --- a/packages/components/src/option/option.styles.ts +++ b/packages/components/src/option/option.styles.ts @@ -110,11 +110,13 @@ export const optionStyles: FoundationElementTemplate< .start, .end, - ::slotted(svg) { + ::slotted(svg), + ::slotted(jp-icon) { display: flex; } - ::slotted(svg) { + ::slotted(svg), + ::slotted(jp-icon) { /* TODO: adaptive typography https://github.com/microsoft/fast/issues/2432 */ height: calc(${designUnit} * 4px); width: calc(${designUnit} * 4px); diff --git a/packages/components/src/search/search.styles.ts b/packages/components/src/search/search.styles.ts index d427669a..e8e8aef8 100644 --- a/packages/components/src/search/search.styles.ts +++ b/packages/components/src/search/search.styles.ts @@ -115,7 +115,8 @@ export const searchStyles: FoundationElementTemplate< height: calc(100% - 2px); } - ::slotted(svg) { + ::slotted(svg), + ::slotted(jp-icon) { /* TODO: adaptive typography https://github.com/microsoft/fast/issues/2432 */ width: 16px; height: 16px; diff --git a/packages/components/src/select/select.styles.ts b/packages/components/src/select/select.styles.ts index fb8258ec..0880fcf8 100644 --- a/packages/components/src/select/select.styles.ts +++ b/packages/components/src/select/select.styles.ts @@ -281,7 +281,8 @@ export const selectStyles: FoundationElementTemplate< .end, .indicator, .select-indicator, - ::slotted(svg) { + ::slotted(svg), + ::slotted(jp-icon) { /* TODO: adaptive typography https://github.com/microsoft/fast/issues/2432 */ fill: currentcolor; height: 1em; @@ -355,7 +356,8 @@ export const selectStyles: FoundationElementTemplate< .end, .indicator, .select-indicator, - ::slotted(svg) { + ::slotted(svg), + ::slotted(jp-icon) { color: ${SystemColors.ButtonText}; fill: currentcolor; } diff --git a/packages/components/src/select/select.test.ts-snapshots/select-with-custom-indicator-chromium-linux.png b/packages/components/src/select/select.test.ts-snapshots/select-with-custom-indicator-chromium-linux.png index f1033af2..cca4a142 100644 Binary files a/packages/components/src/select/select.test.ts-snapshots/select-with-custom-indicator-chromium-linux.png and b/packages/components/src/select/select.test.ts-snapshots/select-with-custom-indicator-chromium-linux.png differ diff --git a/packages/components/src/select/select.test.ts-snapshots/select-with-custom-indicator-firefox-linux.png b/packages/components/src/select/select.test.ts-snapshots/select-with-custom-indicator-firefox-linux.png index 16a70904..fc2e2e29 100644 Binary files a/packages/components/src/select/select.test.ts-snapshots/select-with-custom-indicator-firefox-linux.png and b/packages/components/src/select/select.test.ts-snapshots/select-with-custom-indicator-firefox-linux.png differ diff --git a/packages/components/src/skeleton/skeleton.styles.ts b/packages/components/src/skeleton/skeleton.styles.ts index 7a6d4b92..7e2d4845 100644 --- a/packages/components/src/skeleton/skeleton.styles.ts +++ b/packages/components/src/skeleton/skeleton.styles.ts @@ -76,7 +76,8 @@ export const skeletonStyles: FoundationElementTemplate = ( z-index: 1; } - ::slotted(svg) { + ::slotted(svg), + ::slotted(jp-icon) { z-index: 2; } diff --git a/packages/components/src/styles/patterns/button.ts b/packages/components/src/styles/patterns/button.ts index 7fddb33f..22628e92 100644 --- a/packages/components/src/styles/patterns/button.ts +++ b/packages/components/src/styles/patterns/button.ts @@ -148,7 +148,8 @@ export const BaseButtonStyles = css` line-height: 0; } - ::slotted(svg) { + ::slotted(svg), + ::slotted(jp-icon) { ${ /* Glyph size and margin-left is temporary - replace when adaptive typography is figured out */ '' diff --git a/packages/components/src/styles/patterns/field.ts b/packages/components/src/styles/patterns/field.ts index e9533ada..7c2d76f9 100644 --- a/packages/components/src/styles/patterns/field.ts +++ b/packages/components/src/styles/patterns/field.ts @@ -108,7 +108,8 @@ export const BaseFieldStyles = css` fill: currentcolor; } - ::slotted(svg) { + ::slotted(svg), + ::slotted(jp-icon) { /* TODO: adaptive typography https://github.com/microsoft/fast/issues/2432 */ width: 16px; height: 16px; diff --git a/packages/components/src/toolbar/toolbar.styles.ts b/packages/components/src/toolbar/toolbar.styles.ts index 1d88494f..d3f8f5e8 100644 --- a/packages/components/src/toolbar/toolbar.styles.ts +++ b/packages/components/src/toolbar/toolbar.styles.ts @@ -72,7 +72,8 @@ export const toolbarStyles: FoundationElementTemplate< margin-inline: 0; } - ::slotted(svg) { + ::slotted(svg), + ::slotted(jp-icon) { /* TODO: adaptive typography https://github.com/microsoft/fast/issues/2432 */ width: 16px; height: 16px; diff --git a/packages/components/src/tree-item/tree-item.styles.ts b/packages/components/src/tree-item/tree-item.styles.ts index f2f05d78..63f0a1c8 100644 --- a/packages/components/src/tree-item/tree-item.styles.ts +++ b/packages/components/src/tree-item/tree-item.styles.ts @@ -235,7 +235,8 @@ export const treeItemStyles: FoundationElementTemplate< fill: currentcolor; } - ::slotted(svg) { + ::slotted(svg), + ::slotted(jp-icon) { /* TODO: adaptive typography https://github.com/microsoft/fast/issues/2432 */ width: 16px; height: 16px; diff --git a/packages/components/src/tree-item/tree-item.test.ts-snapshots/tree-item-with-after-content-chromium-linux.png b/packages/components/src/tree-item/tree-item.test.ts-snapshots/tree-item-with-after-content-chromium-linux.png index 648bfd98..3ff68859 100644 Binary files a/packages/components/src/tree-item/tree-item.test.ts-snapshots/tree-item-with-after-content-chromium-linux.png and b/packages/components/src/tree-item/tree-item.test.ts-snapshots/tree-item-with-after-content-chromium-linux.png differ diff --git a/packages/components/src/tree-item/tree-item.test.ts-snapshots/tree-item-with-after-content-firefox-linux.png b/packages/components/src/tree-item/tree-item.test.ts-snapshots/tree-item-with-after-content-firefox-linux.png index 9b7aa8a3..1f5767fc 100644 Binary files a/packages/components/src/tree-item/tree-item.test.ts-snapshots/tree-item-with-after-content-firefox-linux.png and b/packages/components/src/tree-item/tree-item.test.ts-snapshots/tree-item-with-after-content-firefox-linux.png differ diff --git a/packages/components/src/tree-item/tree-item.test.ts-snapshots/tree-item-with-after-content-webkit-linux.png b/packages/components/src/tree-item/tree-item.test.ts-snapshots/tree-item-with-after-content-webkit-linux.png index 1e668e73..60a01417 100644 Binary files a/packages/components/src/tree-item/tree-item.test.ts-snapshots/tree-item-with-after-content-webkit-linux.png and b/packages/components/src/tree-item/tree-item.test.ts-snapshots/tree-item-with-after-content-webkit-linux.png differ diff --git a/packages/components/src/tree-item/tree-item.test.ts-snapshots/tree-item-with-before-content-chromium-linux.png b/packages/components/src/tree-item/tree-item.test.ts-snapshots/tree-item-with-before-content-chromium-linux.png index 66fbf31c..64b2b0c1 100644 Binary files a/packages/components/src/tree-item/tree-item.test.ts-snapshots/tree-item-with-before-content-chromium-linux.png and b/packages/components/src/tree-item/tree-item.test.ts-snapshots/tree-item-with-before-content-chromium-linux.png differ diff --git a/packages/components/src/tree-item/tree-item.test.ts-snapshots/tree-item-with-before-content-firefox-linux.png b/packages/components/src/tree-item/tree-item.test.ts-snapshots/tree-item-with-before-content-firefox-linux.png index 85fa961f..9f45c0c4 100644 Binary files a/packages/components/src/tree-item/tree-item.test.ts-snapshots/tree-item-with-before-content-firefox-linux.png and b/packages/components/src/tree-item/tree-item.test.ts-snapshots/tree-item-with-before-content-firefox-linux.png differ diff --git a/packages/components/src/tree-item/tree-item.test.ts-snapshots/tree-item-with-before-content-webkit-linux.png b/packages/components/src/tree-item/tree-item.test.ts-snapshots/tree-item-with-before-content-webkit-linux.png index 3bfea48d..26a9ae17 100644 Binary files a/packages/components/src/tree-item/tree-item.test.ts-snapshots/tree-item-with-before-content-webkit-linux.png and b/packages/components/src/tree-item/tree-item.test.ts-snapshots/tree-item-with-before-content-webkit-linux.png differ diff --git a/packages/components/src/utilities/storybook/index.ts b/packages/components/src/utilities/storybook/index.ts index 2356bf28..928bb883 100644 --- a/packages/components/src/utilities/storybook/index.ts +++ b/packages/components/src/utilities/storybook/index.ts @@ -1,7 +1,7 @@ // Copyright (c) Jupyter Development Team. // Distributed under the terms of the Modified BSD License. -import { icon, library } from '@fortawesome/fontawesome-svg-core'; +import { config, icon, library } from '@fortawesome/fontawesome-svg-core'; import * as icons from '@fortawesome/free-solid-svg-icons'; import { parseColor } from '@microsoft/fast-colors'; import { SwatchRGB } from '../../color/swatch.js'; @@ -10,6 +10,9 @@ import { isDark } from '../../color/utilities/is-dark.js'; import { StoryContext } from '@storybook/html'; import { DesignSystemProvider } from '../../design-system-provider/index.js'; import type { Button } from '../../button/index.js'; +import { Icon } from '../../icon/index.js'; + +config.autoAddCss = false; /** * Generate the SVG for a fontawesome icon @@ -25,12 +28,10 @@ export function getFaIcon(iconName: string, slotName: string | null): string { .reduce((agg, part) => agg + part, 'fa'); library.add((icons as any)[objectName]); const theIcon = icon({ prefix: 'fas', iconName: iconName as icons.IconName }); - - const copy = theIcon!.node.item(0)!.cloneNode(true) as HTMLElement; - if (slotName) { - copy.setAttribute('slot', slotName); - } - return copy.outerHTML; + Icon.register({ name: iconName, svgStr: theIcon.html[0] }); + return ``; } /** diff --git a/packages/lab-example/src/index.tsx b/packages/lab-example/src/index.tsx index 5787013a..2f8836ed 100644 --- a/packages/lab-example/src/index.tsx +++ b/packages/lab-example/src/index.tsx @@ -17,6 +17,7 @@ import { DateField, Disclosure, Divider, + Icon, Listbox, Menu, MenuItem, @@ -46,6 +47,7 @@ import { addJupyterLabThemeChangeListener, allComponents, DataGrid as WebDataGrid, + Icon as WebIcon, provideJupyterDesignSystem } from '@jupyter/web-components'; import { @@ -65,6 +67,23 @@ import { provideJupyterDesignSystem().register(allComponents); addJupyterLabThemeChangeListener(); +WebIcon.register({ + name: 'search', + svgStr: ` + + + ` +}); +Icon.register({ + name: 'home', + svgStr: ` + + ` +}); + const TABLE_DATA = [ { Header1: 'Data 1 1', @@ -193,7 +212,7 @@ const plugin: JupyterFrontEndPlugin = { app.restored.then(() => { app.shell.add(widget, 'main'); - app.shell.add(reactWidget, 'main', { mode: 'split-right' }); + app.shell.add(reactWidget, 'main', { mode: 'split-bottom' }); app.shell.activateById(widget.id); const dataGrid: WebDataGrid | null = @@ -356,7 +375,10 @@ function Artwork(props: { dataRef: React.Ref }): JSX.Element { JS 22 - Item 1 + + + Item 1 + Item 2 Item 3 @@ -572,7 +594,10 @@ function createNode(): HTMLElement { 18 JS - Item 1 + + Item 1 + + Item 2 Item 3 diff --git a/packages/react-components/lib/Icon.d.ts b/packages/react-components/lib/Icon.d.ts new file mode 100644 index 00000000..c7be949d --- /dev/null +++ b/packages/react-components/lib/Icon.d.ts @@ -0,0 +1,35 @@ +import { + Icon as IconElement, + type IconDefinition +} from '@jupyter/web-components'; + +export type { IconElement, IconDefinition }; + +export interface IconProps extends React.HTMLAttributes { + /** + * Allows getting a ref to the component instance. + */ + ref?: React.Ref; + + /** Name of the icon to display. */ + name?: IconElement['name']; +} + +/** + * Icon class + * --- + */ +export const Icon: React.ForwardRefExoticComponent & { + /** + * Register a new icon. + * + * @param options Icon definition + */ + register(options: IconDefinition): void; + /** + * Set the default icon. + * + * @param svgStr The SVG string to be used as the default icon. + */ + setDefaultIcon(svgStr: string): void; +}; diff --git a/packages/react-components/lib/Icon.js b/packages/react-components/lib/Icon.js new file mode 100644 index 00000000..97b25a26 --- /dev/null +++ b/packages/react-components/lib/Icon.js @@ -0,0 +1,49 @@ +import { Icon as IconElement } from '@jupyter/web-components'; +import React, { forwardRef, useImperativeHandle, useRef } from 'react'; +import { useProperties } from './react-utils.js'; + +/** + * Icon component + * + * Icon must first be registered: `Icon.register({ name, svgStr });` + * + * Then you can use it with `` . + * + * To style your icon, you should set `fill` and/or `stroke` attributes to `currentColor`. + * Then the icon will be colored with the active text color. + */ +export const Icon = forwardRef((props, forwardedRef) => { + const ref = useRef(null); + const { className, name, ...filteredProps } = props; + + /** Properties - run whenever a property has changed */ + useProperties(ref, 'name', props.name); + + /** Methods - uses `useImperativeHandle` hook to pass ref to component */ + useImperativeHandle(forwardedRef, () => ref.current, [ref.current]); + + return React.createElement('jp-icon', { + ref, + ...filteredProps, + class: props.className, + style: { ...props.style } + }); +}); + +/** + * Register a new icon. + * + * @param {IconDefinition} options Icon definition + */ +Icon.register = options => { + IconElement.register(options); +}; + +/** + * Set the default icon. + * + * @param svgStr The SVG string to be used as the default icon. + */ +Icon.setDefaultIcon = svgStr => { + IconElement.setDefaultIcon(svgStr); +}; diff --git a/packages/react-components/lib/index.d.ts b/packages/react-components/lib/index.d.ts index 61335dba..3986efdb 100644 --- a/packages/react-components/lib/index.d.ts +++ b/packages/react-components/lib/index.d.ts @@ -17,6 +17,7 @@ export * from './DataGrid.js'; export * from './Dialog.js'; export * from './Disclosure.js'; export * from './Divider.js'; +export * from './Icon.js'; export * from './Listbox.js'; export * from './MenuItem.js'; export * from './Menu.js'; diff --git a/packages/react-components/lib/index.js b/packages/react-components/lib/index.js index 61335dba..3986efdb 100644 --- a/packages/react-components/lib/index.js +++ b/packages/react-components/lib/index.js @@ -17,6 +17,7 @@ export * from './DataGrid.js'; export * from './Dialog.js'; export * from './Disclosure.js'; export * from './Divider.js'; +export * from './Icon.js'; export * from './Listbox.js'; export * from './MenuItem.js'; export * from './Menu.js'; diff --git a/pyproject.toml b/pyproject.toml index 9fd346aa..476cf8bb 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -1,5 +1,5 @@ [build-system] -requires = ["hatchling>=1.5.0", "jupyterlab>=4.0.0,<5", "hatch-nodejs-version"] +requires = ["hatchling>=1.5.0", "jupyterlab>=4.0.0,<4.1.0", "hatch-nodejs-version"] build-backend = "hatchling.build" [project] @@ -28,7 +28,7 @@ dynamic = ["version", "description", "authors", "urls", "keywords"] [project.optional-dependencies] dev = [ "hatch>=1.5.0", - "jupyterlab" + "jupyterlab~=4.0.0" ] [tool.hatch.version] @@ -72,7 +72,7 @@ version_cmd = "python scripts/bump_version.py --force" [tool.jupyter-releaser.hooks] before-build-npm = [ - "python -m pip install 'jupyterlab>=4.0.0,<5'", + "python -m pip install 'jupyterlab>=4.0.0,<4.1.0'", "jlpm", "jlpm build:prod" ]