Files
clide/.claude/skills/ui-design/references/surface.md
T
jpmschweitzerandClaude Opus 4.8 804bba1680 docs(design): settings-UI wireframes + settings-ui implementation epic (T-302, T-444)
Close T-302 with the Frame0 wireframes for the schema-driven settings UI, and
open the implementation epic T-444 under the Tier-6 epic T-8.

Wireframes (docs/design/wireframes/settings/, JSON source + PNG):
- settings-screen — modal shell + Editor category (all field-type patterns,
  scope tags, carded sections)
- settings-search — cross-category search-active state
- settings-claude — mirrors the sidebar Claude Config panel (settings controls
  + carded config lists)
- settings-appearance — theme-picker swatch grid (live bundled-theme previews)

Design answers: full-screen MODAL overlay; rail + cross-category search IA;
per-field scope-tag model (folder/globe/circle-dashed); carded sections; the
schema-driven renderer makes per-category tabs data, not new design.

Also documents the sectioned-card preference in the ui-design skill
(references/surface.md → "Settings & grouped lists — sectioned cards").

Epic T-444 children: infra (modal shell T-445, rail T-447, field renderer
T-448, scope-tag control T-449, search T-450) + per-category (Editor=T-290
reparented, Keymap T-451, Appearance/theme-picker T-452, Activity T-453,
Terminal T-455, Extensions T-456, Claude T-457).

Also files: T-441/T-442 (UI bugs), T-446 (slash-typeahead intermittent),
T-454 (Claude remote-control not plumbed).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-16 15:41:55 +02:00

4.8 KiB

Surface — token selection per surface type

Pick tokens based on where the widget lives, not what it does.

Chrome (hat bar, status bar, sidebar, context panel, spines, drag handles)

background   → chromeBackground
text         → chromeForeground
border       → chromeBorder (1px)
active text  → globalForeground

Side panels (sidebar, context panel)

background   → chromeBackground (both sides — they're chrome frame)
text         → sidebarForeground
hover        → sidebarItemHover
selected     → sidebarItemSelected
section head → sidebarSectionHeader (muted, used for "START", "FILES", etc.)

Padding: 2px on outer edges, 0px on divider edge.

Center column (workspace, Claude pane, editor)

background   → panelBackground
text         → globalForeground

No padding — content fills edge to edge.

Pane headers (ClidePaneChrome)

background   → panelHeader
text (title) → panelHeaderForeground
text (sub)   → globalTextMuted

Tabs (MultitabPane, ClideTabBar)

strip bg     → tabBarBackground
strip border → bottom: dividerColor (anchors strip to body)
active fg    → tabActiveForeground
inactive fg  → tabInactiveForeground
active bg    → panelHeader (elevated chrome)
inactive bg  → tabBarBackground (blends with strip)
active border→ panelActiveBorder (top accent, 1.5px)
side border  → panelBorder

For control geometry inside tabs (close button placement, padding, two-column title+action layout) see geometry.md.

background   → (none / transparent)
hover bg     → listItemHoverBackground
selected bg  → listItemSelectedBackground
text         → listItemForeground / sidebarForeground (in sidebar)
selected txt → listItemSelectedForeground

In sidebar context, use sidebarItemHover not listItemHoverBackground.

Buttons

normal       → buttonBackground / buttonForeground / buttonBorder
hover        → buttonHoverBackground
active       → buttonActiveBackground
primary      → buttonActiveBackground bg + globalBackground text
subtle       → listItemBackground / listItemHoverBackground (no border)

Dividers and separators

line         → dividerColor (always, everywhere)
drag handle  → 8px hit area, 1px visible line, panel bg fill
hover line   → panelActiveBorder

Status indicators

success/ok   → statusSuccess (green: done, added, connected)
warning      → statusWarning (amber: question, modified, missing)
error        → statusError   (red:   deleted, rejected, cancelled)
info         → statusInfo    (blue:  in_progress, modified)

Map semantic states, not visual styles:

  • done / added / okstatusSuccess
  • in_progress / modifiedstatusInfo
  • question / warningstatusWarning
  • cancelled / deleted / errorstatusError

Overlays (dialogs, palette, tooltips)

dialog bg    → modalSurfaceBackground
dialog border→ modalSurfaceBorder
backdrop     → modalOverlayBackground
tooltip      → tooltipBackground / tooltipForeground / tooltipBorder
dropdown     → dropdownBackground / dropdownForeground / dropdownBorder

Settings & grouped lists — sectioned cards

Settings surfaces and any long grouped list (e.g. the Claude config lists) read as sectioned cards, not bare rows floating on the panel. Each logical group gets its own card; the small-caps section label (+ optional count) sits just above the card.

panel bg      → panelBackground (#20202C)
card surface  → surface (#242838) fill + dividerColor/border (1px), ~6px corners
section head  → sidebarSectionHeader (small-caps), with the count muted to its right
control inset → inputs INSIDE a card recede to panelBackground, so they still
                read as fields against the elevated card
  • One card per group — a settings table, each config list. The card's elevated fill + border do the visual separation; don't rely on spacing alone.
  • Field row inside a card: label (globalForeground) + help (globalTextMuted) + the control right-aligned, with the per-field scope tag in the far-right column.
  • Scroll, don't cram: when stacked cards exceed the modal/pane viewport, the pane scrolls vertically (sticky header, scrolling body) — prefer that over shrinking content to fit one screen.
  • Pattern reference: the settings wireframes under docs/design/wireframes/settings/ (T-302).

Anti-patterns

  • globalBackground for panel fill → use panelBackground
  • Bare settings rows on the panel where a group of them should be one card → see "Settings & grouped lists".
  • listItemHoverBackground in sidebar → use sidebarItemHover
  • Tab active bg = panelBackground → use panelHeader (elevated chrome)
  • Tab active border = globalFocus → use panelActiveBorder