You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
The #496 color migration (sage green → logo blue) surfaced that hover and selected/active states are not governed by any enforced contract: docs/design-system.md defines a 5-state contract on paper but no test enforces it, so ~20 surfaces drifted to inline oklch / static --foreground-N mixes, and a hardcoded --color-state-selected mint block survived the migration untouched. The same scan also surfaced that tabs have no spec at all — 4 hand-written implementations, one of which bypasses the Base UI Tabs primitive entirely. This issue tracks both governance gaps. The color values themselves are in #496.
Verified against main at 226f31a5 on 2026-07-04 (hover/selected/tab drift is pre-existing; the blue token values land in #496).
Scope
Color values are handled in #496. This issue is about interaction-state governance (hover / selected / pressed) and tab component governance — enforcing the existing 5-state contract, retiring drift, and establishing a tab spec that does not exist yet. Not a visual redesign; the target direction was aligned while doing #496 — list/nav/panel selection = neutral wash + bold (no color, no checkmark), menus/dropdowns keep a checkmark. design-system.md + the settings nav and plan/skill tabs already follow this; the rest of the app does not.
CSS cascade/layer debt is tracked in #476; React architecture debt in #477.
P0 — hover/active state tokens are documented but unenforced; ~20 surfaces drifted
docs/design-system.md:56 defines a 5-state contract (default / hover · focus / active · pressed); :115-116,121 assign --hover (sidebar row / ghost button hover fill, "don't use as active") and --active (sidebar row active / button :active, "don't use as hover"). No contract test enforces this — design-system-governance-406-contract.test.ts only gates var(--accent) usage, not --hover / --active.
Only ~8 sites use --hover/--active. The rest drift across three notations:
maka-tokens.css:932,1721 (--hover), :934,1722 (--active) — the canonical pattern, underused
--foreground-N is color-mix static real color, not alpha overlay. composer.css:82-86 already documents the bug: --foreground-3 (≈#f7f7f7) is "indistinguishable from the gray plate (≈#ebebeb)" on glass — yet 16 sites still use --foreground-5 and 4 use --foreground-3 as hover backgrounds. frontend-css-governance.md §5 bans hardcoded colors, so the inline oklch hover values technically violate governance, but nothing enforces it.
Impact: hover visibility is inconsistent (some hovers invisible on glass), selection has 5 mechanisms, and any new surface will hand-roll again.
Direction: Add a contract test that enforces the 5-state contract — hover/active backgrounds for list/nav/button-ghost surfaces must resolve to --hover/--active (or a new --state-hover-bg/--state-selected-bg pair), with an allowlist for genuine exceptions (brand CTAs, destructive). Repoint the ~20 drift sites. Retire --foreground-N as hover/selected backgrounds.
P0 — selected/active state has 5 mechanisms and a platform split
--color-state-selected (theme-glass.css:92,107) is an orphan token — only the sidebar darwin override uses it; the comment claims it will be "reused for chip/tab/nav selected states later" but it never was.
Settings nav: nav-sidebar.css:197 uses 6.5% neutral wash + weight 500 (comment: "keep selected row neutral. A leading accent rail reads like a stray status marker in the Settings nav").
But the same-class surfaces use brand color instead: search results sidebar.css:464, command palette chat-header.css:850, artifact rows models.css:609, daily-review archive daily-review.css:151, memory preview tool-stream.css:158 all use --nav-active brand color for selected — inconsistent with the settings-nav "neutral" decision.
Tabs: see next P0.
Impact: "selected" reads 5 different ways; the colored-vs-neutral boundary is arbitrary per surface.
Direction: Adopt the aligned direction — list/nav/panel selection = neutral wash + bold (no color, no checkmark); menus/dropdowns = checkmark (model switcher, permission mode already do this). Remove --color-state-selected + the darwin override (collapse the platform split). Retire the colored-selected uses on list/panel items (search/palette/artifact/daily-review/memory) to neutral, or document an allowlist if any must stay colored.
P0 — tabs have no spec; 4 hand-written implementations
There is a shared primitive packages/ui/src/primitives/tabs.tsx (Base UI Tabs, default/underline variants + tailwind), but no surface follows it cleanly:
plan/skill tabs (module-pages/plan-reminders.css:424, module-pages/skills.css:225): use TabsList/TabsTrigger but hand-write neutral-underline CSS over it.
catalog tabs (settings/models.css:164, settings/provider-editor.css:37): use PrimitiveTabsList but display:none the Base UI sliding indicator (models.css:170-176 comment: "the pill background is the single source of the active state") and hand-write brand-color pill.
daily-review range tab (daily-review-panel.tsx:398): fully hand-rolled <nav><button className="maka-daily-review-range-tab">, does not use the Tabs primitive at all.
No shared maka-tab base class, no --tab-* token. design-system.md has no tab/segmented-control component section; frontend-css-governance.md doesn't mention tabs; the roadmap doesn't list a tab spec. Only notes/reference-atlas.md:300 mentions a workbench-tab | Tab control variant entry (upstream reference, not Maka's spec).
Impact: 4 visual languages for tabs; new tab surfaces hand-roll again; the primitive exists but is bypassed/overridden.
Direction: Decide one tab spec (variant system — e.g., underline vs pill as intentional documented variants, not per-surface hand-writing), expose it through the primitive + shared class/token, migrate the 4 surfaces, add a contract test that bans hand-written tab active/hover CSS outside the shared spec.
P1 — design-system.md color section is stale post-migration
docs/design-system.md:118 still references "accent 绿…2.46:1" and the old --action/--control green semantics. The #496 migration moved accent/action/control to logo blue (hue 250), but the doc wasn't updated.
Impact: the spec doc contradicts the shipped tokens; future work referencing the doc gets wrong color guidance.
Direction: update the color section to the blue tokens (accent/action/control/foreground values + WCAG ratios). Can ride #496 or this issue's first PR.
Hover/active state governance (P0) — consolidate on --hover/--active (or --state-hover-bg/--state-selected-bg), repoint ~20 drift sites, add the 5-state contract test, retire --color-state-selected + the darwin override, unify list/nav/panel selection to neutral + menus to checkmark.
Tab spec (P0) — design the variant system, migrate the 4 surfaces, add a tab contract test. Largest; do after state governance lands.
Background
The #496 color migration (sage green → logo blue) surfaced that hover and selected/active states are not governed by any enforced contract:
docs/design-system.mddefines a 5-state contract on paper but no test enforces it, so ~20 surfaces drifted to inlineoklch/ static--foreground-Nmixes, and a hardcoded--color-state-selectedmint block survived the migration untouched. The same scan also surfaced that tabs have no spec at all — 4 hand-written implementations, one of which bypasses the Base UI Tabs primitive entirely. This issue tracks both governance gaps. The color values themselves are in #496.Verified against
mainat226f31a5on 2026-07-04 (hover/selected/tab drift is pre-existing; the blue token values land in #496).Scope
Color values are handled in #496. This issue is about interaction-state governance (hover / selected / pressed) and tab component governance — enforcing the existing 5-state contract, retiring drift, and establishing a tab spec that does not exist yet. Not a visual redesign; the target direction was aligned while doing #496 — list/nav/panel selection = neutral wash + bold (no color, no checkmark), menus/dropdowns keep a checkmark.
design-system.md+ the settings nav and plan/skill tabs already follow this; the rest of the app does not.CSS cascade/layer debt is tracked in #476; React architecture debt in #477.
P0 — hover/active state tokens are documented but unenforced; ~20 surfaces drifted
docs/design-system.md:56defines a 5-state contract (default / hover · focus / active · pressed);:115-116,121assign--hover(sidebar row / ghost button hover fill, "don't use as active") and--active(sidebar row active / button:active, "don't use as hover"). No contract test enforces this —design-system-governance-406-contract.test.tsonly gatesvar(--accent)usage, not--hover/--active.Only ~8 sites use
--hover/--active. The rest drift across three notations:oklch(from var(--foreground) l c h / X)sidebar.css:738(0.06),nav-sidebar.css:203(0.065),sidebar.css:762(0.07),daily-review.css:463(0.045)--foreground-Nmix tokens (2/3/5/8/10)nav-sidebar.css:193(--foreground-5),tool-output.css:213(--foreground-3),models.css:160(--foreground-10),model-switcher.css:44(--foreground-8)--hover/--activetokensmaka-tokens.css:932,1721(--hover),:934,1722(--active) — the canonical pattern, underused--foreground-Niscolor-mixstatic real color, not alpha overlay.composer.css:82-86already documents the bug:--foreground-3(≈#f7f7f7) is "indistinguishable from the gray plate (≈#ebebeb)" on glass — yet 16 sites still use--foreground-5and 4 use--foreground-3as hover backgrounds.frontend-css-governance.md §5bans hardcoded colors, so the inlineoklchhover values technically violate governance, but nothing enforces it.Impact: hover visibility is inconsistent (some hovers invisible on glass), selection has 5 mechanisms, and any new surface will hand-roll again.
Direction: Add a contract test that enforces the 5-state contract — hover/active backgrounds for list/nav/button-ghost surfaces must resolve to
--hover/--active(or a new--state-hover-bg/--state-selected-bgpair), with an allowlist for genuine exceptions (brand CTAs, destructive). Repoint the ~20 drift sites. Retire--foreground-Nas hover/selected backgrounds.P0 — selected/active state has 5 mechanisms and a platform split
theme-glass.css:117(darwin) uses--color-state-selectedsolid color block; non-darwinsidebar.css:762uses 7% neutral wash. Platform split.--color-state-selected(theme-glass.css:92,107) is an orphan token — only the sidebar darwin override uses it; the comment claims it will be "reused for chip/tab/nav selected states later" but it never was.nav-sidebar.css:197uses 6.5% neutral wash + weight 500 (comment: "keep selected row neutral. A leading accent rail reads like a stray status marker in the Settings nav").sidebar.css:464, command palettechat-header.css:850, artifact rowsmodels.css:609, daily-review archivedaily-review.css:151, memory previewtool-stream.css:158all use--nav-activebrand color for selected — inconsistent with the settings-nav "neutral" decision.Impact: "selected" reads 5 different ways; the colored-vs-neutral boundary is arbitrary per surface.
Direction: Adopt the aligned direction — list/nav/panel selection = neutral wash + bold (no color, no checkmark); menus/dropdowns = checkmark (model switcher, permission mode already do this). Remove
--color-state-selected+ the darwin override (collapse the platform split). Retire the colored-selected uses on list/panel items (search/palette/artifact/daily-review/memory) to neutral, or document an allowlist if any must stay colored.P0 — tabs have no spec; 4 hand-written implementations
There is a shared primitive
packages/ui/src/primitives/tabs.tsx(Base UI Tabs,default/underlinevariants + tailwind), but no surface follows it cleanly:module-pages/plan-reminders.css:424,module-pages/skills.css:225): useTabsList/TabsTriggerbut hand-write neutral-underline CSS over it.settings/models.css:164,settings/provider-editor.css:37): usePrimitiveTabsListbutdisplay:nonethe Base UI sliding indicator (models.css:170-176comment: "the pill background is the single source of the active state") and hand-write brand-color pill.daily-review-panel.tsx:398): fully hand-rolled<nav><button className="maka-daily-review-range-tab">, does not use the Tabs primitive at all.No shared
maka-tabbase class, no--tab-*token.design-system.mdhas no tab/segmented-control component section;frontend-css-governance.mddoesn't mention tabs; the roadmap doesn't list a tab spec. Onlynotes/reference-atlas.md:300mentions aworkbench-tab | Tab control variantentry (upstream reference, not Maka's spec).Impact: 4 visual languages for tabs; new tab surfaces hand-roll again; the primitive exists but is bypassed/overridden.
Direction: Decide one tab spec (variant system — e.g., underline vs pill as intentional documented variants, not per-surface hand-writing), expose it through the primitive + shared class/token, migrate the 4 surfaces, add a contract test that bans hand-written tab active/hover CSS outside the shared spec.
P1 —
design-system.mdcolor section is stale post-migrationdocs/design-system.md:118still references "accent 绿…2.46:1" and the old--action/--controlgreen semantics. The #496 migration moved accent/action/control to logo blue (hue 250), but the doc wasn't updated.Impact: the spec doc contradicts the shipped tokens; future work referencing the doc gets wrong color guidance.
Direction: update the color section to the blue tokens (accent/action/control/foreground values + WCAG ratios). Can ride #496 or this issue's first PR.
P2 — press (
:active) scale is not converged:activepress feedback uses 5 scale values: 0.92 (chat-header.css:592toast-close), 0.97 (globalbase.css:94+ most), 0.98 (sidebar.css:749list-row,models.css:605artifact-row), 0.985 (nav-sidebar.css:630settings nav/back), 0.99 (daily-review.css:466,sidebar.css:945prompt-chip) plus translate variants.docs/design-refinement-roadmap-2026-07.md:61says ":active scale(0.97)已 shipped" as the standard.Impact: press feel is subtly inconsistent; no contract guards it.
Direction: converge to 0.97 with a documented allowlist for genuine exceptions; optional contract test.
Suggested PR order
design-system.mdcolor section to blue; can ride feat(design-system): migrate default color system from sage green to logo blue #496.--hover/--active(or--state-hover-bg/--state-selected-bg), repoint ~20 drift sites, add the 5-state contract test, retire--color-state-selected+ the darwin override, unify list/nav/panel selection to neutral + menus to checkmark.Out of scope