Skip to content

refactor(design): add DESIGN.md, a semantic token layer and converged primitives - #45

Merged
mrsibe merged 3 commits into
mainfrom
design/tokens-and-primitives
Sep 24, 2026
Merged

mrsibe merged 3 commits into
mainfrom
design/tokens-and-primitives

Conversation

@mrsibe

@mrsibe mrsibe commented Sep 24, 2026

Copy link
Copy Markdown
Owner

What does this PR do?

Adds DESIGN.md as the repository's single design source of truth, turns the
existing Tailwind variables into a semantic token layer (surface / text /
elevation), and moves the 22 base primitives in components/ui onto it.

No product behaviour changes, no new pages, no new dependencies. This is part 1
of 2; the shell and page refactor is stacked on top of it.

Why?

The token layer already existed, but the system did not. Three concrete
problems measured on main:

  • No surface hierarchy. Only background / card / popover existed, while
    the UI is a multi-panel desktop app. Worse, the two levels pointed in opposite
    directions between themes: in light card(1.0) > background(0.985), in dark
    card(0.263) < background(0.2925), and dark card and sidebar were the same
    value. Panel layering was therefore expressed with shadows.
  • No radius or elevation rhythm. rounded-md 26 / rounded-lg 25 (near
    equal), plus sm/xl/2xl; shadow-sm 12 / shadow-md 13 / shadow-lg 12
    mixed with no rule.
  • No written contract. Any agent asked to "add a knowledge-base page" could
    only fall back on adjectives.

Fixes #43 (part 1).

What changed?

DESIGN.md (new) — principles, surface ladder, border/elevation rules, the
three radius values, spacing and density tables, the T1/T2/T3 text hierarchy,
accent discipline, the four interaction states, dark-mode requirements, a
do/don't list, component recipes, and the order of decisions for a new page.
Every rule names a token or a Tailwind class; there are no adjectives.

theme.css — new primitives:

  • surface-sunken < surface-base < surface-raised < surface-overlay,
    monotonic in both colour schemes.
  • surface-hover / surface-selected as translucent state fills, so a row
    highlights correctly on any surface instead of needing per-panel values.
  • subtle-foreground as the third text level; muted-foreground adjusted for
    contrast (light 0.7055 → 0.58, dark 0.4983 → 0.68; dark was ~2.1:1 before).
  • shadow-elevation (floating layers) and shadow-control (knobs/handles)
    replace the six-step shadow scale.
  • --background / --card / --popover / --sidebar / --accent are kept as
    aliases of the ladder, so un-migrated components inherit the consistency
    without a mass rename. The legacy shadow names all resolve to
    shadow-elevation, so a missed shadow-md degrades to the same elevation
    instead of a third style.

Base primitives — Button, Input, Textarea, Card, Badge, Tabs, Dialog,
AlertDialog, Sheet, Select, Tooltip, ContextMenu, Sonner, Checkbox, Switch,
Slider, Progress, Empty, PanelHeader:

  • every radius collapses onto rounded-md (control) / rounded-lg (container)
    / rounded-full (pill);
  • floating layers become bg-surface-overlay + hairline border +
    shadow-elevation; panels, cards, buttons and inputs lose their shadows;
  • density per the table: 36px buttons, 32px icon buttons, 36px inputs, 44px
    panel headers, 16px dialog/card titles, tighter card padding;
  • hover/selected/focus/disabled use one literal expression per DESIGN.md.

Two latent bugs fixed on the way: Empty's container had border-dashed with no
border width (the intended outline never rendered), and ScrollArea's viewport
used rounded-[inherit], a fourth radius value that the root's overflow-hidden
already covered.

Related issue

Fixes #43

How was this tested?

  • npm run lint — 0 errors; warning count unchanged at 118.
  • npm run typecheck — passes (node + web + test configs).
  • npm run build (electron-vite) — passes.
  • Verified against the emitted CSS that the new utilities are generated and
    reference the primitive variables, and that the .dark overrides win:
    .bg-surface-raised { background-color: var(--surface-raised) },
    .shadow-elevation { --tw-shadow: var(--shadow-elevation) }.

Not verified: the visual result. My environment has no display (no Xvfb), so
I could not launch Electron or capture screenshots — see below.

Screenshots / recordings

I could not capture these: no display is available in the environment this was
built in. The visible changes a reviewer should check are:

  • dark mode panels are now lighter than the canvas (they were darker, and
    card/sidebar were identical);
  • radii are 6px for controls and 8px for containers, instead of a mix of 4/6/8/12/16px;
  • panels and cards no longer cast shadows; only floating layers do;
  • density is slightly higher (44px panel headers, 36px controls).
Before After

Checklist

  • I have reviewed my own changes.
  • npm run typecheck passes.
  • npm run build passes.
  • I have tested the affected user workflow. Cannot be done here — no display.
  • I have not included unrelated changes.
  • I have updated documentation when necessary.

Desktop / build changes

  • Not applicable

Documents the surface ladder, border and elevation rules, radius scale,
spacing and density tables, three-level text hierarchy, accent discipline,
state expressions and component recipes. Every rule names a token or a
Tailwind class so a new page can be built without inventing conventions.
…ation

Introduces the primitives DESIGN.md describes:

- surface-sunken/base/raised/overlay form a monotonic ladder in both colour
  schemes, replacing the old pair where dark-mode card and sidebar shared one
  value and the panel/canvas direction flipped between light and dark.
- surface-hover/selected are translucent state fills so a row highlights
  correctly on any surface instead of needing per-panel values.
- muted-foreground moves to 0.58 (light) / 0.68 (dark) and a third level,
  subtle-foreground, is added for meta text.
- shadow-elevation and shadow-control replace the six-step shadow scale, which
  now collapses onto them so a missed shadow-sm/md/lg degrades consistently.

Existing token names are kept: background/card/popover/sidebar/accent are now
aliases of the ladder, so untouched components inherit the new consistency
without a mass rename.
Button, Input, Textarea, Card, Badge, Tabs, Dialog, AlertDialog, Sheet,
Select, Tooltip, ContextMenu, Sonner, Checkbox, Switch, Slider, Progress,
Empty and PanelHeader now use the surface ladder, the three-level text
hierarchy and the two elevation tokens instead of bg-card/bg-popover/
bg-background, bg-accent and shadow-sm/md/lg.

Also applies the density table: 36px buttons (32px icon buttons), 36px
inputs, 44px panel headers, 16px dialog/card titles, tighter card padding
and separators instead of gaps. Rounded values collapse onto md (control),
lg (container) and full (pill).

Two latent bugs fixed on the way:
- Empty's container had 'border-dashed' with no border width, so the
  intended outline never rendered.
- ScrollArea's viewport used rounded-[inherit], a fourth radius value that
  Root's overflow-hidden already covers.
@mrsibe
mrsibe merged commit 04baf3f into main Sep 24, 2026
3 checks passed
@mrsibe
mrsibe deleted the design/tokens-and-primitives branch September 24, 2026 07:45
@mrsibe mrsibe added the enhancement New feature or request label Sep 24, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

enhancement New feature or request

Projects

None yet

Development

Successfully merging this pull request may close these issues.

refactor: 建立 KnowNote/DESIGN.md 与语义化 design tokens,收敛散落的 UI 约定

1 participant