Files
deepseek-harness/packages/client/ui-theme
Chinesezjc 0401c3c6c7 test(ui-theme): resolve elevated surfaces from the palette, not from rebinds
The check added last commit derived its elevated set from the sheets that
already rebind, which cannot catch the omission it targets: such a set only
confirms what someone already remembered, and a surface nobody has rebound
yet defines itself as unelevated. Review found the case that proves it —
TodoPanel scrolls in .list on a --dsw-specific-tip card, the same dark rung
as the menu surface, unrebound and with the derived check green.

Resolves the set from the palette's own dark elevation ladder instead: the
surface tokens whose dark value lands on bg-layer-2 or bg-layer-3, which is
the step the l1/l2 split encodes. A new palette token on an elevated rung is
in scope the moment it is defined.

Scope is by token family rather than geometry: only --dsw-alias-bg-* and
--dsw-specific-* name a surface. The button, interactive, and markdown
families reach the same rungs while naming a control or an inline span that
no scroll container renders a bar against, and shape cannot separate them
since a floating button carries a radius, a shadow, and a fixed size —
ChatView's .toBottom pill was the false positive that showed this.

Adds the missing TodoPanel rebind. Mutation-checked all four rebinds in
turn: each is named with its surface. The palette anchoring has its own
control — narrowing the family pattern turns it red on --dsw-specific-menu.
2026-07-28 18:31:52 +08:00
..

@deepseek-ai/dsh-client-ui-theme

English | 中文

Theme plugin: ThemeService over the --dsw-* token base stylesheets (static scale + alias semantic layers). The service owns the theme preference (light/dark/system, persisted under dsh.theme), resolves system through prefers-color-scheme, and publishes immutable ThemeSnapshots on the theme/change event; it never touches the DOM — ui-layout's presenter applies the resolved snapshot (html { color-scheme }, body[data-ds-dark-theme], and inline alias tokens). Contract: api-contracts v3 §8.

src/styles/ holds five sheets, all imported by the web shell's base.css: base.css, design-platform.css, scrollbar.css, gradient-shadow-text.css, and shiki.css. scrollbar.css is the sole consumer of the --dsw-alias-scrollbar-* tokens and must follow design-platform.css, which declares them.

Scrollbar rebinding contract: scrollbar.css binds --dsh-scrollbar-thumb and --dsh-scrollbar-thumb-hover on body to the l1 (base-surface) tokens, and both rendering paths read that pair. An elevated surface (menu, popover, dialog) sets --dsh-scrollbar-thumb: var(--dsw-alias-scrollbar-bg-l2) and --dsh-scrollbar-thumb-hover: var(--dsw-alias-scrollbar-hover-l2) on its own container; one rebind retints whichever path the engine took.

The two paths are mutually exclusive by construction. scrollbar-width/scrollbar-color sit inside @supports not selector(::-webkit-scrollbar) because a non-auto value of either makes Chromium and Safari discard every ::-webkit-scrollbar* rule for that element, ::-webkit-scrollbar-thumb:hover included — declaring both unconditionally leaves --dsh-scrollbar-thumb-hover with no rendering anywhere. Firefox therefore takes the standard properties and WebKit-based engines take the pseudo-elements, so the hover token only ever renders through the pseudo-element path. Reasoning and the measured computed values: the scrollbar Agent Note.

Model Experience

None, as the theme service manages a browser preference; nothing here reaches a model request.

KV Cache effect

None; this package neither assembles nor sends a provider request.

Known Limitations and Deferred Work

  • Third-party themes are a surface, not a product — registering one means overriding same-named alias variables; no validation exists that an override set is complete.
  • The token sheets are the sole color authority — values absent from cssdesign (for example the design's #4176E6 tab blue) are deliberately not appended; the nearest semantic token wins (arbitrated 2026-07-22).