Skip to content

Align browser extension side panel with kilo-design - #4767

Merged
iscekic merged 11 commits into
mainfrom
ext-design-sync
Jul 25, 2026
Merged

Align browser extension side panel with kilo-design#4767
iscekic merged 11 commits into
mainfrom
ext-design-sync

Conversation

@iscekic

@iscekic iscekic commented Jul 25, 2026

Copy link
Copy Markdown
Contributor

Align browser extension side panel with kilo-design

Full visual + voice alignment of apps/extension with the canonical Kilo design system (DESIGN.md / tokens.json v0.2.0, dark-only per kilo-design ADR 0009). No behavior changes; existing E2E suites are the regression bar and stay green.

What changed

Token layer (new)

  • @theme static token set in style.css mirroring the contract: 6-step surface ladder, foreground roles, pre-alpha borders, brand (#F7F586), 8 status families × 4 steps, syntax, diff, radius remap (md 8px / lg 10px / xl 14px), Inter + Roboto Mono via fontsource (no remote font loads, MV3-safe).
  • type-* text-style utilities (type-titletype-code) copied verbatim from apps/web with extension font vars.
  • design-tokens.ts: tiny JS mirror for SVG consumers (donut strokes/track), kept in sync by the new drift guard.
  • Extension icon moved from old yellow #EDFF00 to brand #F7F586 (SVG + all five PNGs regenerated).

Component alignment

  • Surface ladder map: canvas/background, chrome bars/raised, floating/overlay, wells/inset; alpha-on-canvas fills retired.
  • Brand scarcity: Send and auth CTAs are the only primary-brand actions per surface; Stop/Compact now are filled-secondary (with the 1px same-slot border contract); selection is an interaction state, not brand; donut strokes map to usage status (green/yellow/red 500) with a gray idle stroke.
  • Message surfaces: user bubble on raised + border, agent on canvas, thinking/tool wells on inset, error chrome on diff-delete-surface + status-red nested text maps.
  • Unified neutral-controls rule (bordered-at-rest → filled secondary, borderless → ghost), global brand focus-ring recipe (ring-brand-primary-ring + ring-offset-surface-background), disabled recipe without opacity-*, contract button typography (type-label).
  • Typography: Inter/Roboto Mono everywhere; arbitrary text-[10/11px] eliminated (12px is the smallest role; type-eyebrow the only sanctioned 11px); mono for code/timestamps.
  • Upstream features that landed during the work (memory settings, pending-save card, collapsible code blocks, session cost) are aligned too.

Verification tooling (new)

  • Vitest drift guard: bans default Tailwind palette families, raw hex/rgb, arbitrary text sizes/tracking, ring-token opacity; asserts the icon brand contract and DESIGN_TOKENSstyle.css sync; includes a plant-and-catch self-check.
  • Computed-style E2E (design-tokens.test.ts, 7 cases): shell/footer paints, Send enabled/disabled/Stop, transcript recipes (bubble, mono, error/success wells, thinking, standalone error, agent canvas), donut warn stroke + track/button distinction, history Open eyebrow chip + old-paint scan. Firefox computed-style parity documented Chrome-only (font-stack serialization risk).

Verification

  • pnpm --filter kilo-extension verify — 337 unit tests pass (incl. drift guard)
  • pnpm --filter kilo-extension build / build:firefox — pass; bundled @font-face + 13 .woff2 assets verified in .output
  • pnpm --filter kilo-extension e2e:chrome70/70 pass
  • pnpm --filter kilo-extension e2e:firefox32/32 workflows pass
  • Chrome zip: 646.7 kB (fonts add ~430 kB unpacked; variable fonts keep it to two families)

Recorded deviations

  • @theme static (not plain, not inline): plain @theme tree-shakes unused variables; static emits the full token layer.
  • Transcript virtualizer estimateSize stays at the pre-existing 52: the measured collapsed band (42–46) destabilized the scroll-pin E2E on the CI browser (wheel-up poll timeouts at 44/46/48); the estimate only seeds unmeasured rows and measureElement reconciles real heights regardless. History estimateSize: 105 (measured, green everywhere).
  • Tab close stays size-6 (a size-8 close fills the whole h-8 pill).
  • Auth titles use type-heading (18px); OTP code display keeps tracking-[0.18em] (guard allow-listed).
  • Donut track uses surface.background (recessed groove on the filled-secondary overlay button — reviewer-found, repaired with a Case D lock).

Known observation (pre-existing, not from this PR)

When the "Add to memory" card is open above the composer, Save memory/Done/Retry (brand primary) co-exist with Send message (brand primary) — two primary fills on one surface, which sits against the contract's one-primary-per-surface rule. That role assignment came in with the upstream memory feature; this PR only tokenized it. Happy to file a follow-up if product wants the card's actions demoted to secondary.

iscekic added 8 commits July 25, 2026 10:58
Wire Inter/Roboto Mono variable fonts via fontsource, define the
kilo-design token set as a static @theme layer with type-* text-style
utilities, add a JS token mirror for SVG consumers, and refresh the
extension icon from old yellow (#EDFF00) to brand primary (#F7F586).
Apply the plan's brand matrix to the app shell: canvas/chrome surface
ladder, brand logo, filled-secondary icon buttons, auth card/OTP wells,
status-yellow warning banner, and the global brand focus-ring recipe.
Apply the message-surface recipes: user bubble on raised, agent on
canvas, thinking/tool wells on inset, error chrome on delete-surface
with status-red text maps, Send/Stop same-slot primary/secondary
switch, donut status strokes from the JS token mirror, and re-measured
virtualizer estimates (history 105, transcript 46).
…tokens

Apply the unified neutral-controls rule, dense input recipes, status
domains for mode icons and inline errors, card ladder roles, and retire
disabled:opacity in favor of the subtle-foreground disabled recipe.
Add a Vitest drift guard banning default palette families, raw hex/rgb,
arbitrary text sizes and tracking from sidepanel sources, asserting the
icon.svg brand contract and DESIGN_TOKENS/style.css sync. Add Playwright
computed-style cases A-E pinning shell, composer, transcript, donut, and
eyebrow token paints. Firefox computed-style parity documented as
Chrome-only.
Step the donut track down to surface.background so it reads as a
recessed groove on the filled-secondary overlay button, and compare
parsed RGB channels in the Case E old-paint scan so serialization form
cannot mask legacy paint.
…design tokens

Bring the upstream memory settings, pending-memory-save card, and
collapsible code block onto the token recipes: card ladder roles,
filled-secondary/primary/ghost control variants, inputs recipe, status
inline errors, token gradient fade, and the global focus ring.
The integrated safe-mode surface exposes search_memories/get_memory;
align the new computed-style fixtures with the upstream tool list.
@iscekic iscekic self-assigned this Jul 25, 2026
iscekic added 2 commits July 25, 2026 11:40
Map the PostHog opt-out card onto the card ladder role and the toggle
onto neutral surface/foreground states with the global focus ring,
retiring the brand fills and disabled opacity.
Measured collapsed heights (42-46) destabilized the scroll-pin E2E on
the CI browser (wheel-up poll timeouts). The estimate is only the
initial guess for unmeasured rows and measureElement reconciles actual
heights, so the pre-existing value stays with a recorded deviation.
@iscekic
iscekic enabled auto-merge (squash) July 25, 2026 11:43
@iscekic
iscekic merged commit ea03bf4 into main Jul 25, 2026
68 checks passed
@iscekic
iscekic deleted the ext-design-sync branch July 25, 2026 11:49
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