1. format
  2. lint
  3. typecheck
  4. architecture
  5. self-proof
  6. tests
  7. coverage
  8. e2e
  9. duplication
  10. security
main · greenwall 10/10sample

Wesley DeitchFront-End & Design EngineerWellsville, PARemote (ET)

Systems · tokens, light and dark, contrast in CI

Three design systems, built the way this page is built.

Design tokens layered Style, then Brand, then Theme. Light and dark. WCAG AA contrast checked in CI. Storybook. The systems are private npm packages, so the specimen below is this site's own set, built the same way, and not one of theirs.

Move a hueor press Shift Alt I anywhere on the sitethen tap anything to read its tokens

01Token bench · recolor the site, trip the guard

Every color on this page is a token. Move one.

Hue and lightness rewrite the Brand layer inside the sandbox. A WCAG AA check runs on the rendered colors, in both themes. Only a passing set can be merged onto the site, and only by you.

Style, then Brand, then Theme. The Switch in the status bar rewrites only the third.

Presets are hues only. Each product keeps its own token set.

The guard reads rendered rgb(), not the numbers I meant to ship.

Brand layer --wd-amber

presetshues only

restores the site to my amber
sandbox · guard passes · the ruling amber

Amber is the human color: the ruling, the primary action, the focus ring.

  • --wd-amberthe fill
  • --wd-amber-textaccent text
  • --wd-on-amberthe label on the fill
check · minimum AA 4.5:1light (the theme on screen now)dark
accent text on paperthe accent set as running textlight theme, pass, 5.9:1dark theme, pass, 7.7:1
label on accent fillpaper in light, ink in darklight theme, pass, 5.0:1dark theme, pass, 7.7:1
CHK contrast · 5.9:1 text · 5.0:1 label · pass · both themes · rendered rgb()

Token layers · Style, then Brand, then Theme

  1. 01Stylespace, type, radius, motion--wd-space-05 to 12 · --wd-fs--1 to display · --wd-radius-0 to 3 · --wd-font-display, body, monorewritten bycode
  2. 02Brandthe accent and its pairs--wd-amber #A0560F · --wd-amber-text #8F4D10 · --wd-on-amber #F7F3ECrewritten bythe Token Bench
  3. 03Themepaper, ink, rule, the pass and fail states--wd-paper #F7F3EC · --wd-paper-2 #EFE9DF · --wd-ink #191714 · --wd-ink-2 #5C574F · --wd-rule #D9D2C5rewritten bythe Switch

02Systems · one component, six layers

A button is six decisions in a trench coat.

The same Button the rest of this site uses, taken apart. Every layer is a file I would have to get right for the component to be worth publishing.

On a wide screen, hover the stack and it opens so every layer reads. On a touch screen it rests open; below 960 px it stacks flat.

The stack is decorative; the layer nav under it is the control.

Hover the stack to open it.Choose a layer to read its excerpt.

01Primitive

Button.astro
// this site's own Button:// an <a> with an href, a <button> otherwise<button  class:list={['btn', variant, size]}  type={type}  {...rest}>  <slot /></button>

One element, no wrapper divs. Everything else is a layer on top of it.

One component, six layers: the element, the tokens, the states, the accessibility notes, the tests and the story.

03Specimen · this site's own components

No product UI is public, so the specimen is this page.

Every control here is the component this site actually ships, on the same token layers as the systems: keyboard operable, 44 px targets, a visible amber focus ring, and both themes from one set.

Turn Inspect mode on and hover or tab any of these to read its tokens and contrast.

Tab through the sheet. Nothing here needs a mouse.

Button

44 px, amber only for the primary. The one taken apart above.

Switch

role=switch. The knob stretches on the press, then settles.

Segmented

A radiogroup with a roving tabindex. The thumb follows on a spring.

Input

The error names what is wrong instead of only turning red.

Add the domain, so I can write back.

Select

The native control, framed. The keyboard and the mobile picker stay.

Two lanes, no third.

Tabs

Arrow keys move and select. One tab stop for the whole control.

Space, type, radius and motion. The layer the bench never touches.

Tooltip

Hover or focus shows it. Esc dismisses it without moving focus.

20 rules, 82 automated checks, 10 gates. Each check carries a fixture that proves it still fires.

Toast

One aria-live region for the page. Three at a time, then a queue.

CHK contrast · 5.9:1 · pass

Dialog

The native element, so Esc, the backdrop and the focus trap are free.

A rule without a check is a wish.

Every rule in the standard carries an automated check, and every check carries a permanent violation fixture that proves it still fires. A gate's worth is the cost of what it catches, not the count.

Kbd and Tag

The small type that carries the state of the page.

Shift+Ipassfailrulingfact

04Three systems · one token model

Three systems, and one of them I sent back.

Three accessible React design systems, 113-130 components each, with design tokens layered Style, then Brand, then Theme; light and dark; WCAG AA contrast checked in CI; Storybook; published as private npm packages.

113 to 130 components each, across three product lines.

Nothing links out: the packages are private.

Components per system113 to 130

Solid cells show the lower bound; outlined cells run to the upper.

  • Shared systemTokens, light and dark, contrast in CI, Storybook. The one I had rebuilt.
    Tactile
  • ChurchVueKept separate on purpose, so the product's identity stays its own.
    own system
  • DwinterThe games' system, from the same token layers.
    games

Competent but generic.

My verdict on the first version of the shared system, which I had rebuilt behind review gates I signed off myself.

One identity per product

I kept ChurchVue on its own system rather than the shared library, to keep each product's identity distinct. Each product keeps its own token set; the presets on the bench share hues, not identities.

  • 2themes, light and dark, from one token setthe Theme layer of the tokens
  • AAWCAG contrast, checked in CI on every builda standing contrast test

Write to me

What do you need built?

It lands in my inbox and I reply by email. No list, no forwarding, no bot.

The role or the engagement, and what a good outcome looks like.

Nothing sent yet.

or write to deitchwesley@gmail.com