Repository navigation
Two theme-token gaps that keep plugin overlays below 3:1 (no light surface step, no elevation recipe) #12770
Awenforever
started this conversation in
Ideas
Replies: 0 comments
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Uh oh!
There was an error while loading. Please reload this page.
Two theme-token gaps that keep plugin overlays below 3:1
I maintain a split-view plugin for DSH (
dsh-multiview) and recently took it through alight/dark contrast audit. Everything the plugin draws is expressed with the shipped
--dsw-alias-*tokens, and it deliberately never uses colour literals. Two gaps in thetoken set mean a plugin cannot meet WCAG 1.4.11 (non-text contrast, 3:1) for raised
surfaces, no matter how it combines the tokens. Both are reported here with measured
values so you can decide whether they are design intent or oversights.
Everything below was read out of
@deepseek-ai/dsh-client-ui-themelib/client.jsin DSH0.2.2-rc.1. Light = thebody{…}alias layer, dark =body[data-ds-dark-theme]{…}.Ratios are WCAG 2.1 computed from the resolved hex values.
Gap 1 — there is no light-theme surface step, and the dark ladder tops out at 1.51:1
The surface ladder resolves like this:
bg-base(dark)--dsw-alias-bg-base#ffffff#151517--dsw-alias-bg-layer-1#ffffff#232324--dsw-alias-bg-layer-2#ffffff#2c2c2e--dsw-alias-bg-layer-3#ffffff#353638In light the three layer tokens are identical to the page, so a raised surface
(dialog, popover, dropdown, toast) can only be distinguished by a hairline:
#151517--dsw-alias-border-l3--dsw-alias-border-l4Taking the strongest tokens available —
bg-layer-3for the surface,border-l4for theedge, and
bg-mask-1for the scrim behind it — a modal dialog reaches only:That is the ceiling; there is no combination of existing tokens that gets higher. A
stronger mask (
bg-mask-3,bg-mask-photo) would raise the number only by darkening thepage far beyond what a normal modal scrim does, which is a redesign rather than a token
choice.
There is also no elevation recipe. The only shadow-named alias is
--dsw-alias-illustration-shadow, and it is a solid colour (#edf0f4light /#43454adark), not a
box-shadowvalue, so it cannot be used to lift a surface. I grepped thewhole alias layer: there is no
bg-layer-4and no shadow token family.What would fix it
Either would be enough:
#ffffff— e.g.bg-layer-1..3mapping to something like#fafafa/#f4f5f6/#eceef0, mirroring howthe dark ladder already steps — and dark steps that reach ~3:1 for the topmost layer
(
bg-layer-3would need to be around#4a4b4eagainst#151517).--dsw-alias-shadow-overlay: 0 8px 24px #0000001fper theme, so a plugin can raise asurface without a literal.
Gap 2 —
state-business-secondaryis missing from an otherwise complete familyThe semantic state family is nearly symmetric, with one hole:
state-success-primary/-secondary/-tertiary✅state-warn-primary/-secondary/-tertiary✅ (pluswarn-label)state-error-primary/-secondary✅state-business-primary✅ /state-business-secondary❌ missing /state-business-tertiary✅Full list as shipped:
business-primary, business-tertiary, done-primary, error-primary, error-secondary, idle-primary, success-primary, success-secondary, success-tertiary, warn-label, warn-primary, warn-secondary, warn-tertiary.Why this bites: a plugin that follows the naming convention writes
color: var(--dsw-alias-state-business-secondary). An undefined custom property does notthrow — the declaration is simply invalid at computed-value time, so the element silently
keeps its inherited colour. During my audit this is exactly the kind of thing that
produced an invisible control that no error report pointed at.
What would fix it
Add
--dsw-alias-state-business-secondary(the natural value would sit betweenbusiness-primary#4176e6/#7aaaffandbusiness-tertiary#e4edfd/#34415b), ordocument the family contract so authors know
businessintentionally has only two steps.Context on my side
uses
bg-layer-3+border-l4+bg-mask-1and reaches the ceilings quoted above.check.mjsguard that bans colour literals in the shipped bundle, and it alsonever validates token names against the theme — which is how the missing
state-business-secondaryclass of bug gets past it. If the theme exposed a stable,machine-readable token list at build time, a plugin could fail its own build on an
unknown name; that would be a third, smaller ask.
Idea: let the host declare a rendering priority for embedded conversations (multi-pane streaming drops to ~24fps) #12559.
All reactions