Skip to content

feat(hub-ui): overridable primary color + customizable branding - #177

Merged
antfu merged 4 commits into
mainfrom
feat/hub-ui-branding
Aug 10, 2026
Merged

feat(hub-ui): overridable primary color + customizable branding#177
antfu merged 4 commits into
mainfrom
feat/hub-ui-branding

Conversation

@antfubot

@antfubot antfubot commented Aug 7, 2026

Copy link
Copy Markdown
Collaborator

Makes the reference dock's identity a first-class, overridable surface: a consumer (e.g. a Vite DevTools-style viewer) can reuse hub-ui and rebrand it — logo, product name, and color — without forking.

Stacked on #176 (base branch feat/hub-ui-antfu-design). Review after that merges, or review just this branch's diff.

Primary color as one variable

  • The entire primary ramp derives from a single --devframe-primary (src/client/primary-ramp.css), appended after the UnoCSS output so it wins over Wind4's :host defaults. Unset → exact devframe green (guaranteed-invalid fallback trick); set → the five stops derive via color-mix. Everything already routes through var(--colors-primary-*), so it all retints.
  • The dock glow now derives from the primary variable too.

Group accent, unified

  • A group's accentColor is applied by overriding --devframe-primary on the group's chrome container (.devframes-accent-scope re-runs the ramp so the override actually cascades), retinting the whole cluster through the primary token — replacing the bespoke inline accent colors in accent-color.ts. The group's plugin view is left untouched (no surprise recoloring of third-party UI).

Branding

  • New DevframeBranding: productName, logo/wordmark (string | { light, dark }), primaryColor, tagline, favicon, windowTitle — all optional with devframe defaults.
  • Transport: createUi({ branding }) publishes it as branding.json via a new generic DevframeHubUi.assets seam on @devframes/hub — the only hub change, and it carries no branding knowledge. The dock fetches it before first paint (no flash). A host page overrides any field at runtime via window.__DEVFRAME_BRANDING__, <script data-*>, or ?query params — merged per field (host page wins).
  • Surfaces: logo swaps at every BrandMark/BrandWordmark site (incl. the builtin:devframes sentinel); productName templatizes all user-visible copy; favicon/windowTitle apply to the standalone viewer and popped-out window only — the embedded bootstrap never touches the host page's head.

Internal devframes-* ids, custom-element tags, storage keys, and command ids are unchanged.

Design record

Shaped through a full decision interview: primary-as-variable, ramp via color-mix, group accent unified through the variable, branding delivered via createUi + host-page overrides, and a minimal generic assets seam as the single agreed hub change.

Verification

build:css, typecheck (workspace-wide), build (embedded + standalone), lint, knip, build-storybook, and the tsnapi API snapshots all pass. A Brand → Branded story demonstrates a custom name/logo/primary. No Chromium on this ARM64 host, so visual checks are via the Storybook/build pipeline rather than screenshots.

Created with the help of an agent.

Reuse the shared design system's Vue components in the dock shell instead
of bespoke local ones, swap the placeholder plug glyph for the devframe
logo, and drop the Vite-derived dock chrome.

- Buttons across the launcher, confirm modal, auth notice and json-render
  now use @antfu/design's ActionButton; keybinding chips use DisplayKbd.
- The shadow-root stylesheet build scans the design package's components
  so their semantic shortcut classes ship in the injected CSS.
- BrandMark/BrandWordmark render the devframe logo mark.
- Remove the dock brackets and re-theme the dock glow to the sage palette.

Created with the help of an agent.
Make the reference dock's identity a first-class, overridable surface so a
consumer (e.g. a Vite DevTools-style viewer) can reuse hub-ui and rebrand it —
logo, product name, and color — without forking.

Primary color
- The whole primary ramp derives from a single `--devframe-primary` variable
  (src/client/primary-ramp.css), appended after the UnoCSS output so it wins
  over Wind4's `:host` defaults. Unset keeps the exact devframe green (via a
  guaranteed-invalid fallback); set derives the five stops with `color-mix`.
- The dock glow follows the primary variable, so a rebrand retints it too.

Group accent
- A group's `accentColor` is applied by overriding `--devframe-primary` on the
  group's chrome container (`.devframes-accent-scope`), retinting the whole
  cluster through the primary token — replacing the bespoke inline accent
  colors. The group's plugin view is left untouched.

Branding
- New `DevframeBranding` (logo/wordmark with light/dark variants, productName,
  primaryColor, tagline, favicon, windowTitle); all optional with devframe
  defaults. `createUi({ branding })` publishes it as `branding.json` through a
  new generic `DevframeHubUi.assets` seam on `@devframes/hub` (the only hub
  change — branding-agnostic). The dock fetches it before first paint; a host
  page can override any field at runtime via `window.__DEVFRAME_BRANDING__`,
  `<script data-*>`, or `?query` params, merged per field.
- Logo swaps at every BrandMark/BrandWordmark site; productName templatizes all
  user-visible copy; favicon/title apply to the standalone viewer and popped-out
  window only (never the embedded host page's head).

Created with the help of an agent.
json-render components read their accent from `--jr-primary` (a standalone
blue default) via inline styles, so rendered plugin UI ignored the hub primary
and any branding override. Since ViewJsonRender renders inside the dock shadow
root, set `--jr-primary` from the brand primary in the ramp block — Tabs,
Switch, Progress, and Link now follow --devframe-primary / branding, tracking
the global primary (not per-group accent, matching the chrome-only accent
decision). The blue fallback remains for standalone json-render use.

Created with the help of an agent.
@antfu
antfu changed the base branch from feat/hub-ui-antfu-design to main August 10, 2026 00:55
# Conflicts:
#	packages/hub-ui/src/client/.generated/css.ts
#	packages/hub-ui/src/client/components/icons/BrandMark.vue
#	packages/hub-ui/src/client/components/icons/BrandWordmark.vue
#	packages/hub-ui/src/client/components/views-builtin/ViewBuiltinClientAuthNotice.vue
#	packages/hub-ui/src/client/style.css
@netlify

netlify Bot commented Aug 10, 2026

Copy link
Copy Markdown

Deploy Preview for devfra ready!

Name Link
🔨 Latest commit 569a7f0
🔍 Latest deploy log https://app.netlify.com/projects/devfra/deploys/6a7922ba60f64d00085c5a04
😎 Deploy Preview https://deploy-preview-177--devfra.netlify.app
📱 Preview on mobile
Toggle QR Code...

QR Code

Use your smartphone camera to open QR code link.
🤖 Make changes Run an agent on this branch

To edit notification comments on pull requests, go to your Netlify project configuration.

@antfu
antfu merged commit 7c18542 into main Aug 10, 2026
12 checks passed
@antfu
antfu deleted the feat/hub-ui-branding branch August 10, 2026 01:11
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants