a11y(1.4.11): introduce border-input token so form-input boundaries meet 3:1 against surface-primary in both modes#3480
Draft
canvanooo wants to merge 1 commit into
Draft
Conversation
|
The latest updates on your projects. Learn more about Vercel for GitHub.
|
|
|
Contributor
|
…dary meets 3:1 against surface-primary The --color-border-subtle token at src/lib/theme/variables.ts:185-188 resolved to slate.200 (#AEBED9) in light mode and slate.800 (#273860) in dark mode. Against --color-surface-primary (#FFFFFF light / #000000 dark), those compute to 1.89:1 and 1.83:1 — both below the WCAG SC 1.4.11 Non-text Contrast 3:1 floor. border-subtle is used at 106 sites across 76 files in src/lib/holocene and src/lib/components, on every form-input outer wrapper (Input, Textarea, NumberInput, ChipInput, Combobox, DurationInput, FileInput, RangeInput) AND on the Button "secondary" variant (which Select and MenuButton route through) AND on cards, panels, table-row dividers, nav dividers, and other component-boundary surfaces. All of them currently fail the same SC. This shifts the token to slate.400 (#7C8FB1) light / slate.500 (#667CA1) dark, giving: - light: #7C8FB1 vs #FFFFFF → 3.27:1 ✓ - dark: #667CA1 vs #000000 → ~4.96:1 ✓ The change is a single-line token-value update with no consumer-side modifications and no new token surface. Every consumer of border-subtle improves to ≥ 3:1 atomically. Visual tradeoff: borders that were previously near-invisible become clearly visible across the design system — cards more "carded", tables more grid-like, nav dividers more pronounced. This was the design's intent (these borders exist to demarcate boundaries); the previous values rendered the intent invisibly. Design-team sign-off on the weight shift is in the PR's Merge Checklist. The audit team's verification doc (audit-output/issues/1.4.11-non-text-contrast-verification.md) identified border-subtle as failing universally; the audit-output fix doc (1.4.11-input-border-contrast.md) recommended this exact one-line token darken as Option A. This PR implements that recommendation. Cascades to cloud-ui-main via the @temporalio/ui tarball on next repack. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
9f56796 to
030b8d1
Compare
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Description & motivation 💭
The
--color-border-subtletoken atsrc/lib/theme/variables.ts:185-188resolved to slate.200 (#AEBED9) in light mode and slate.800 (#273860) in dark mode. Against--color-surface-primary(#FFFFFF/#000000), those compute to:#AEBED9(slate.200)#FFFFFF#273860(slate.800)#000000Both below the WCAG 1.4.11 Non-text Contrast 3 : 1 floor.
border-subtleis used at 106 sites across 76 files insrc/lib/holoceneandsrc/lib/components, including every form-input outer wrapper (Input, Textarea, NumberInput, ChipInput, Combobox, DurationInput, FileInput, RangeInput), theButton variant="secondary"rendering (which Select and MenuButton route through), and a long tail of cards, panels, table-row dividers, nav dividers, and other component-boundary surfaces. All of them currently fail the same SC.This PR shifts the token to slate.400 (
#7C8FB1) light / slate.500 (#667CA1) dark:'--color-border-subtle': { - light: 'slate.200', - dark: 'slate.800', + light: 'slate.400', + dark: 'slate.500', },#7C8FB1(slate.400)#FFFFFF#667CA1(slate.500)#000000One line in
src/lib/theme/variables.ts:186-187. No consumer-side changes, no new token surface, no plugin map updates. Every consumer ofborder-subtleimproves to ≥ 3 : 1 atomically.Why a token-level darken rather than a selective swap or new token. Earlier iterations of this branch (history rewritten via force-push, single draft PR) introduced a new
border-inputtoken used selectively on form-input primitives, in an attempt to keepborder-subtleunchanged for non-input consumers. That approach hit two scope-expansion rounds in succession: a missed grep added DurationInput / FileInput / RangeInput, then Select surfaced via the Buttonsecondaryvariant. Each round was the symptom of having picked the wrong abstraction layer. The verification doc (audit-output/issues/1.4.11-non-text-contrast-verification.md) identifiedborder-subtleas failing universally, and the audit fix doc (1.4.11-input-border-contrast.md) recommended this exact one-line token darken as Option A from the start. Implementing Option A directly closes the entire SC failure in one change rather than chasing consumers individually.Cascade.
border-subtleis part of the@temporalio/uidesign-token surface; the change cascades to cloud-ui-main on next tarball repack.Screenshots (if applicable) 📸
Screenshots to be captured by the PR author from the Vercel preview build (link appears once the
Vercelcheck passes). Include light-mode and dark-mode captures for form inputs (Input / Textarea / Select / etc.) AND for representative non-input surfaces (cards on the workflow detail page, tables on the workflow list page, the breadcrumb / nav dividers) to show the universal effect.Design Considerations 🎨
Token-level visual change across ~106 consumers in both modes. The biggest perceptual delta is in dark mode, where borders go from nearly-invisible (
slate.800on#000000) to clearly defined (slate.500on#000000). In light mode, borders go fromslate.200(a very light blue-gray) toslate.400(a medium blue-gray) — visible but not jarring.What gets visibly more present after the change:
variant="secondary"— Cancel, Save, "Add filter", modal action buttons, MenuButton triggers. Boundaries now clearly visible.This is the design's existing intent (these borders exist to demarcate boundaries); the previous values rendered the intent invisibly. Design team should confirm the heavier rendering is acceptable; if not, the conversation is "do we want decorative separators below 3 : 1?" rather than "do we want this fix?" — the contrast fix is required for accessibility regardless.
Testing 🧪
How was this tested 👻
Automated checks performed locally on
a11y/1.4.11-input-border-contrastbefore pushing:pnpm lint— 0 errorspnpm check(svelte-check) — 0 errors (84 pre-existing warnings repo-wide, none introduced by this change)pnpm test -- --run— 142 test files / 2023 tests passlint-staged: eslint --fix, prettier --write, stylelint --fix) clean on the modified fileManual visual testing in Storybook and the live app is the responsibility of the PR author after the preview deploy is ready (see "Steps for others to test" below).
Steps for others to test: 🚶🏽♂️🚶🏽♀️
pnpm installif needed.pnpm stories:dev— open Storybook at http://localhost:6006.main.pnpm dev. Walk a few high-traffic pages:/namespaces/default/standalone-activities/start-activity-form) — confirm timeout DurationInputs, payload FileInput, Combobox selectors all render with the new border./namespaces/default/schedules/create) — confirm interval offset Select picklist and other form inputs./namespaces/default/workflows) — confirm filter Combobox at top + table-row separators below.border-subtleconsumer. Treat as expected; accept as new baseline.Checklists
Draft Checklist
src/lib/theme/variables.ts:186-187pnpm lint,pnpm check,pnpm test -- --runall passMerge Checklist
border-subtle)Issue(s) closed
A11y-Audit-Ref: 1.4.11-input-border-contrast
Closes the border-subtle contrast defect documented in the May 2026 audit (manifest bucket 1, severity serious, scope ui-main). See
scripts/a11y/manifest.ymlfor the canonical entry.Docs
Any docs updates needed?
No external docs (
docs.temporal.io) need updating — this is a design-system internal token-value change with no API surface change. If the team maintains an internal design-system changelog, an entry noting "darkened--color-border-subtlefrom slate.200/slate.800 to slate.400/slate.500 for WCAG AA contrast" would be appropriate.🤖 Generated with Claude Code