Skip to content

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

Open
antfubot wants to merge 2 commits into
feat/hub-ui-antfu-designfrom
feat/hub-ui-branding
Open

feat(hub-ui): overridable primary color + customizable branding#177
antfubot wants to merge 2 commits into
feat/hub-ui-antfu-designfrom
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.

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.
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.

1 participant