From 13e57cfd0792311dec32efb6d1ed564b7a643a79 Mon Sep 17 00:00:00 2001 From: dvcolomban Date: Thu, 10 Sep 2026 20:06:00 +0200 Subject: [PATCH 1/6] feat(hub-ui): render explicit SVG mask icons --- docs/content/8.references/4.node-api.md | 4 +++- .../client/components/icons/IconifyIcon.vue | 11 ++++++++-- .../hub/src/client/dock-resources.test.ts | 10 ++++++++++ packages/hub/src/client/dock-resources.ts | 8 ++++++++ plugins/terminals/app/client/App.svelte | 20 ++++++++++++++++--- plugins/terminals/src/node/manager.ts | 9 ++------- plugins/terminals/test/terminals.test.ts | 6 ++++++ 7 files changed, 55 insertions(+), 13 deletions(-) diff --git a/docs/content/8.references/4.node-api.md b/docs/content/8.references/4.node-api.md index cdb6bf036..25b7f7af4 100644 --- a/docs/content/8.references/4.node-api.md +++ b/docs/content/8.references/4.node-api.md @@ -20,7 +20,7 @@ The fields of a `DevframeDefinition`: [Devframe Definition](/guide/devframe-defi | `importMetaUrl` | `string` | **Recommended.** Pass `import.meta.url`, the deps resolution base: default `resolveFrom` for [remote assets](/guide/client-assets) and declared [services](/guide/services#wire-services). | | `homepage` | `string` | **Required.** Homepage/docs URL. | | `description` | `string` | **Required.** One-line summary. | -| `icon` | `string \| { light, dark }` | Optional Iconify name or URL; light/dark pairs. | +| `icon` | `string \| { light, dark }` | Optional Iconify name, image URL, or `mask:`; light/dark pairs. | | `basePath` | `string` | Optional mount-path override. Default `/` standalone (`cli`/`build`), `/__/` hosted (`vite`/`embedded`). | | `duplicationStrategy` | `'warn' \| 'silent' \| 'throw' \| 'duplicate'` | Hub reaction when another devframe shares this `id`. Default `'warn'`. See [Duplication strategies](/references/hub-api#duplication-strategies); standalone adapters ignore it. | | `capabilities` | `{ dev?, build? }` | Per-runtime feature flags. `boolean` = whole runtime; object = individual features. | @@ -30,6 +30,8 @@ The fields of a `DevframeDefinition`: [Devframe Definition](/guide/devframe-defi | `setup` | `(ctx, info?) => void \| Promise` | **Required.** Server-side entry point, run in every runtime. Optional 2nd arg carries runtime metadata, notably parsed CLI `flags` under `createCac`. | | `cli` | `DevframeCliOptions` | CLI adapter defaults. See [CLI options](#cli-options). | +The reference hub UI and terminal SPA render `mask:` icons with the surrounding text color, preserving the image's shape and opacity. For a bundled SVG, use `` `mask:data:image/svg+xml,${encodeURIComponent(svg)}` ``. A mask produces one color; use an ordinary image URL for multicolor artwork. Relative mask URLs on dock entries resolve against the supplying hub's URL. Custom hub UI providers implement this string convention in their own icon renderer. + ## CLI options The `cli` field's `DevframeCliOptions`: [CLI options](/guide/devframe-definition#cli-options). diff --git a/packages/hub-ui/src/client/components/icons/IconifyIcon.vue b/packages/hub-ui/src/client/components/icons/IconifyIcon.vue index 7a210ccae..898a009c6 100644 --- a/packages/hub-ui/src/client/components/icons/IconifyIcon.vue +++ b/packages/hub-ui/src/client/components/icons/IconifyIcon.vue @@ -6,7 +6,8 @@ const props = defineProps<{ icon: string }>() -const isUrlIcon = computed(() => props.icon.includes('/') || props.icon.startsWith('data:') || props.icon.startsWith('builtin:')) +const maskUrl = computed(() => props.icon.startsWith('mask:') ? props.icon.slice(5) : undefined) +const isUrlIcon = computed(() => maskUrl.value !== undefined || props.icon.includes('/') || props.icon.startsWith('data:') || props.icon.startsWith('builtin:')) const iconifyParsed = computed(() => { if (isUrlIcon.value) return undefined @@ -38,7 +39,13 @@ watchEffect(async () => {