@erclx/canon 5.60.0 → 5.62.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +23 -0
- package/README.md +1 -1
- package/claude/.claude-plugin/plugin.json +1 -1
- package/claude/skills/canon-cli/SKILL.md +2 -1
- package/claude/skills/design-identity/references/card-route.md +3 -3
- package/claude/skills/design-record/references/design.md +19 -0
- package/claude/skills/document-health/REQUIREMENT.md +1 -1
- package/claude/skills/document-health/SKILL.md +6 -5
- package/claude/skills/document-health/references/axes.md +3 -1
- package/claude/skills/review-ui/REQUIREMENT.md +1 -1
- package/claude/skills/review-ui/SKILL.md +3 -2
- package/claude/skills/review-ui/references/post.md +2 -2
- package/claude/skills/target-update/SKILL.md +9 -1
- package/claude/skills/ui-checklist/REQUIREMENT.md +1 -1
- package/claude/skills/ui-checklist/SKILL.md +12 -0
- package/claude/skills/ux-audit/SKILL.md +1 -1
- package/docs/agents/install-and-sync.md +45 -11
- package/docs/agents/records.md +1 -1
- package/docs/index.md +1 -1
- package/docs/target/migrations.md +7 -9
- package/docs/target/sync.md +20 -1
- package/docs/workflow/ai-workflow.md +1 -1
- package/docs/workflow/index.md +3 -3
- package/docs/workflow/parallel-features.md +1 -1
- package/docs/workflow/visual-design-workflow.md +58 -32
- package/governance/detect.toml +8 -0
- package/governance/ledger/ui/a11y.md +8 -6
- package/governance/ledger/ui/keyboard.md +20 -21
- package/governance/ledger/ui/pointer.md +24 -0
- package/governance/ledger/ui/surface-capture.md +12 -12
- package/governance/ledger/ui/ux-completeness.md +11 -23
- package/governance/ledger/ui/ux-controls.md +26 -0
- package/governance/rules/ui/a11y.md +2 -0
- package/governance/rules/ui/keyboard.md +4 -7
- package/governance/rules/ui/pointer.md +23 -0
- package/governance/rules/ui/surface-capture.md +5 -5
- package/governance/rules/ui/ux-completeness.md +2 -10
- package/governance/rules/ui/ux-controls.md +25 -0
- package/governance/splits.toml +15 -0
- package/package.json +2 -1
- package/src/commands/driver.ts +29 -3
- package/src/commands/migrate.ts +7 -0
- package/src/commands/records.ts +3 -2
- package/src/commands/sync.ts +3 -1
- package/src/commands/tooling.ts +329 -10
- package/src/design/audit.ts +25 -1
- package/src/design/budget.ts +2 -1
- package/src/design/document.ts +5 -1
- package/src/design/themes.ts +176 -0
- package/src/design/tokens.ts +3 -0
- package/src/driver/drive.ts +17 -1
- package/src/driver/probes/axe.ts +195 -0
- package/src/driver/steps.ts +20 -1
- package/src/gate/measures.ts +9 -3
- package/src/gov/adapter.ts +53 -4
- package/src/gov/splits.ts +36 -0
- package/src/markdown/structure.ts +4 -1
- package/src/migrate/records.ts +46 -7
- package/src/records/stale-canonical.ts +2 -2
- package/src/sync/check.ts +9 -1
- package/src/sync/stamp.ts +135 -11
- package/src/tooling/disposition.ts +167 -0
- package/src/tooling/inject.ts +17 -2
- package/src/tooling/scan.ts +86 -7
- package/src/tooling/stamp.ts +51 -7
|
@@ -1,57 +1,83 @@
|
|
|
1
1
|
---
|
|
2
2
|
title: Visual design workflow
|
|
3
|
-
description:
|
|
3
|
+
description: How canon plans, builds, and reviews a UI, from the design reference a plan cites to the browser pass that holds a pull request open
|
|
4
4
|
category: Workflow
|
|
5
5
|
---
|
|
6
6
|
|
|
7
7
|
# Visual design workflow
|
|
8
8
|
|
|
9
|
-
|
|
9
|
+
Canon runs a UI feature through one loop. A plan cites the design, a worker builds against it and captures what it painted, and two independent reviews check the result. A project with no graphical design tool runs all of it, since the design lives in prose and in tracked frames.
|
|
10
10
|
|
|
11
|
-
##
|
|
11
|
+
## Plan
|
|
12
12
|
|
|
13
|
-
|
|
13
|
+
`canon:plan-feature` reads `canon/DESIGN.md` and `canon/design/index.md` before it places a UI change. It loads `canon:design-taste`, which decides the layer order a surface is designed in, the coherence locks that keep it consistent, and the defaults a model reaches for that the surface should reach past.
|
|
14
14
|
|
|
15
|
-
- The
|
|
15
|
+
- The plan carries a `## Design references` section naming the accepted design for each surface it changes, or `None identified.` when there is none.
|
|
16
|
+
- A design becomes a reference through `canon:design-record`, which lands an accepted pick in `canon/design/` and carries its values into `canon/DESIGN.md`.
|
|
16
17
|
|
|
17
|
-
|
|
18
|
+
## Build
|
|
18
19
|
|
|
19
|
-
|
|
20
|
-
- `canon:pick-by-eye` drafts candidates as frames on a [Frameboard](https://www.npmjs.com/package/frameboard) board and takes your pick
|
|
21
|
-
- `canon:design-record` lands a pick in `canon/design/` and carries its values into `canon/DESIGN.md`
|
|
22
|
-
- `canon:design-identity` drafts a logo mark and social card
|
|
20
|
+
The worker opens each cited reference, light and dark, before its first edit to that surface. It takes sizes, spacing, and colors from the frame HTML rather than the image, and reports a reference that does not resolve instead of building without it.
|
|
23
21
|
|
|
24
|
-
|
|
22
|
+
- The ui rules fire as a family on the files the worker edits, and `governance/rules/ui/` holds the set.
|
|
23
|
+
- The `surface-capture` rule has the worker capture the full page in every theme the surface ships, against a preview server and never a dev server.
|
|
24
|
+
- It sets the widths too, being 320 plus each breakpoint in `canon/DESIGN.md` for a layout case, and one width for a state case.
|
|
25
25
|
|
|
26
|
-
##
|
|
26
|
+
## Self-check
|
|
27
27
|
|
|
28
|
-
|
|
28
|
+
Before the pull request opens, the worker runs two checks.
|
|
29
29
|
|
|
30
|
-
-
|
|
31
|
-
-
|
|
32
|
-
- Chrome DevTools MCP ([`ChromeDevTools/chrome-devtools-mcp`](https://github.com/ChromeDevTools/chrome-devtools-mcp)) for traces, network, DOM, and CSS
|
|
33
|
-
- Claude Design for codebase extraction or a polished handoff bundle
|
|
34
|
-
- A frontend design skill: [pbakaus/impeccable](https://github.com/pbakaus/impeccable), [nextlevelbuilder/ui-ux-pro-max-skill](https://github.com/nextlevelbuilder/ui-ux-pro-max-skill), or Anthropic's `frontend-design`
|
|
30
|
+
- `canon:ui-checklist` writes the boxes a reviewer reads beside the captures. Each box is one observable behavior, and a box that needs eyes carries a `(taste)` mark.
|
|
31
|
+
- `canon:pr-evidence` posts the captures and the checklist on the pull request as one comment, which the reviews read.
|
|
35
32
|
|
|
36
|
-
|
|
33
|
+
`canon drive <url> <run>` covers states a first render cannot reach. A run file walks a page through named interactions and measures each state, with three probes:
|
|
37
34
|
|
|
38
|
-
|
|
35
|
+
- `focus` reads where keyboard focus lands and whether it shows
|
|
36
|
+
- `details` reads disclosure state
|
|
37
|
+
- `axe` runs the accessibility engine
|
|
39
38
|
|
|
40
|
-
|
|
39
|
+
Run `canon drive --help` for the step kinds and the run file shape.
|
|
41
40
|
|
|
42
|
-
|
|
41
|
+
## Review
|
|
43
42
|
|
|
44
|
-
|
|
45
|
-
- Claude Design with its Claude Code handoff bundle for teams without Figma. The handoff is one-way.
|
|
46
|
-
- The Playwright and Chrome DevTools MCPs from tier 1
|
|
43
|
+
Two reviews run beside each other and finish on their own clocks.
|
|
47
44
|
|
|
48
|
-
|
|
45
|
+
- `canon:review-pr` reads the code and the stills in the evidence comment, and posts under `## Review`.
|
|
46
|
+
- `canon:review-ui` never reads the diff. It drives each checklist box in the running app through the pinned `@playwright/cli` and posts under `## UI review`.
|
|
47
|
+
- Every box gets one verdict, being pass, fail, needs eyes, or not driven.
|
|
49
48
|
|
|
50
|
-
|
|
49
|
+
After the boxes, `review-ui` sweeps every route they reached:
|
|
51
50
|
|
|
52
|
-
|
|
51
|
+
- console errors on each route
|
|
52
|
+
- sideways overflow at each width a box named
|
|
53
|
+
- the `focus`, `details`, and `axe` probes through `canon drive`
|
|
53
54
|
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
55
|
+
## What holds a review open
|
|
56
|
+
|
|
57
|
+
A UI review stays open while the branch owes a fix. Three things owe one:
|
|
58
|
+
|
|
59
|
+
- a failed box
|
|
60
|
+
- a sweep finding, being a console error, an overflow, or an axe violation of a gated class
|
|
61
|
+
- a box the page kept the pass from driving
|
|
62
|
+
|
|
63
|
+
Two kinds of result report without holding the review open.
|
|
64
|
+
|
|
65
|
+
- A taste box needs eyes, so the pass captures both themes and leaves the call to you.
|
|
66
|
+
- Every other probe result, and every axe `incomplete`, is a reading to confirm, since each probe carries a known class of false finding.
|
|
67
|
+
|
|
68
|
+
At the time of writing, the gated axe classes are contrast, target size, accessible names, labels, alt text, document title and language, valid ARIA, and nested interactive controls. A rule leaves the list on its first false finding, so `canon drive --help` and the `review-ui` skill carry the current one.
|
|
69
|
+
|
|
70
|
+
A close posts as `## UI review closed`. The reviewers lift the draft mark on their close, and you merge.
|
|
71
|
+
|
|
72
|
+
## Design authoring
|
|
73
|
+
|
|
74
|
+
Most projects author design in the loop above and need nothing more. Start with `canon:pick-by-eye`, which drafts candidates as frames on a [Frameboard](https://www.npmjs.com/package/frameboard) board and takes your pick, then record the pick with `canon:design-record`. `canon:design-identity` drafts a logo mark and social card the same way.
|
|
75
|
+
|
|
76
|
+
A graphical tool earns its place when design is the product, a designer owns it, and it changes more often than code. Then the tool is the source of truth, and `canon/DESIGN.md` carries a top note naming the upstream project.
|
|
77
|
+
|
|
78
|
+
- Figma with the official [Figma Dev Mode MCP](https://www.figma.com/blog/introducing-claude-code-to-figma/), for a team already on Figma. It syncs both ways and captures a running UI into editable frames.
|
|
79
|
+
- [Claude Design](../../wiki/claude/design.md) with its Claude Code handoff bundle, for a team without Figma. The handoff is one-way.
|
|
80
|
+
|
|
81
|
+
The loop above runs unchanged on either, with the tool's export standing in for the pick.
|
|
82
|
+
|
|
83
|
+
For the skills by moment, see the [skill map](skill-map.md).
|
package/governance/detect.toml
CHANGED
|
@@ -172,6 +172,10 @@ files = ["index.html", "*/index.html"]
|
|
|
172
172
|
deps = ["react", "vue", "svelte", "astro", "next", "solid-js", "preact"]
|
|
173
173
|
files = ["index.html", "*/index.html"]
|
|
174
174
|
|
|
175
|
+
["pointer"]
|
|
176
|
+
deps = ["react", "vue", "svelte", "astro", "next", "solid-js", "preact"]
|
|
177
|
+
files = ["index.html", "*/index.html"]
|
|
178
|
+
|
|
175
179
|
["forms"]
|
|
176
180
|
deps = ["react", "vue", "svelte", "astro", "next", "solid-js", "preact"]
|
|
177
181
|
files = ["index.html", "*/index.html"]
|
|
@@ -180,6 +184,10 @@ files = ["index.html", "*/index.html"]
|
|
|
180
184
|
deps = ["react", "vue", "svelte", "astro", "next", "solid-js", "preact"]
|
|
181
185
|
files = ["index.html", "*/index.html"]
|
|
182
186
|
|
|
187
|
+
["ux-controls"]
|
|
188
|
+
deps = ["react", "vue", "svelte", "astro", "next", "solid-js", "preact"]
|
|
189
|
+
files = ["index.html", "*/index.html"]
|
|
190
|
+
|
|
183
191
|
["surface-capture"]
|
|
184
192
|
deps = ["react", "vue", "svelte", "astro", "next", "solid-js", "preact"]
|
|
185
193
|
files = ["index.html", "*/index.html"]
|
|
@@ -9,12 +9,13 @@ The field is web accessibility, and the authority is the W3C, through WCAG 2.2 a
|
|
|
9
9
|
|
|
10
10
|
## Semantics
|
|
11
11
|
|
|
12
|
-
| Bullet | Source
|
|
13
|
-
| ----------------------------------------- |
|
|
14
|
-
| Native `<button>` or `<a>` over a `<div>` | [Using ARIA, first rule](https://www.w3.org/TR/using-aria/): "If you can use a native HTML element or attribute with the semantics and behavior you require already built in", use it "instead of re-purposing an element and adding an ARIA role"
|
|
15
|
-
| Attribute spelling per syntax | [React common components](https://react.dev/reference/react-dom/components/common): the DOM prop is `tabIndex`, "A number. Overrides the default Tab button behavior", where HTML spells it `tabindex`
|
|
16
|
-
| Role and synchronized state | [Understanding Name, Role, Value](https://www.w3.org/WAI/WCAG22/Understanding/name-role-value.html): "the name and role can be programmatically determined" and "notification of changes to these items is available to user agents"
|
|
17
|
-
| Name for a control with no visible text | [Understanding Name, Role, Value](https://www.w3.org/WAI/WCAG22/Understanding/name-role-value.html): every user interface component's "name and role can be programmatically determined"
|
|
12
|
+
| Bullet | Source | Read |
|
|
13
|
+
| ----------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -------------------- |
|
|
14
|
+
| Native `<button>` or `<a>` over a `<div>` | [Using ARIA, first rule](https://www.w3.org/TR/using-aria/): "If you can use a native HTML element or attribute with the semantics and behavior you require already built in", use it "instead of re-purposing an element and adding an ARIA role" | 2026-10-18 |
|
|
15
|
+
| Attribute spelling per syntax | [React common components](https://react.dev/reference/react-dom/components/common): the DOM prop is `tabIndex`, "A number. Overrides the default Tab button behavior", where HTML spells it `tabindex` | 2026-10-18, React 19 |
|
|
16
|
+
| Role and synchronized state | [Understanding Name, Role, Value](https://www.w3.org/WAI/WCAG22/Understanding/name-role-value.html): "the name and role can be programmatically determined" and "notification of changes to these items is available to user agents" | 2026-10-18, WCAG 2.2 |
|
|
17
|
+
| Name for a control with no visible text | [Understanding Name, Role, Value](https://www.w3.org/WAI/WCAG22/Understanding/name-role-value.html): every user interface component's "name and role can be programmatically determined" | 2026-10-18, WCAG 2.2 |
|
|
18
|
+
| Name contains the visible label | [Understanding Label in Name](https://www.w3.org/WAI/WCAG22/Understanding/label-in-name.html): "the name contains the text that is presented visually", and the start position is "A best practice". "People who operate with voice interaction use the visible labels in their commands" | 2026-10-23, WCAG 2.2 |
|
|
18
19
|
|
|
19
20
|
## Text alternatives
|
|
20
21
|
|
|
@@ -28,6 +29,7 @@ The field is web accessibility, and the authority is the W3C, through WCAG 2.2 a
|
|
|
28
29
|
| Bullet | Source | Read |
|
|
29
30
|
| ------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -------------------- |
|
|
30
31
|
| 3:1 for boundaries and graphics | [Understanding Non-text Contrast](https://www.w3.org/WAI/WCAG22/Understanding/non-text-contrast.html): "Ensure meaningful visual cues achieve 3:1 against the background" | 2026-10-18, WCAG 2.2 |
|
|
32
|
+
| 4.5:1 for text | [Understanding Contrast (Minimum)](https://www.w3.org/WAI/WCAG22/Understanding/contrast-minimum.html): "The visual presentation of text and images of text has a contrast ratio of at least 4.5:1", with "Large-scale text" at 3:1 | 2026-10-23, WCAG 2.2 |
|
|
31
33
|
| Color never the only carrier | [Understanding Use of Color](https://www.w3.org/WAI/WCAG22/Understanding/use-of-color.html): "Color is not used as the only visual means of conveying information, indicating an action, prompting a response, or distinguishing a visual element" | 2026-10-18, WCAG 2.2 |
|
|
32
34
|
|
|
33
35
|
## Reflow
|
|
@@ -9,26 +9,28 @@ The field is web accessibility, and the authorities are the W3C, through WCAG 2.
|
|
|
9
9
|
|
|
10
10
|
## Focus styles
|
|
11
11
|
|
|
12
|
-
| Bullet | Source
|
|
13
|
-
| ---------------------------------------- |
|
|
14
|
-
| One project focus ring | House choice: per-component focus styles drift apart, and `canon inventory` reports the ring by computed style, so a one-off treatment shows as its own row
|
|
15
|
-
| No outline removal without a replacement | [outline](https://developer.mozilla.org/en-US/docs/Web/CSS/outline): "Assigning outline a value of 0 or none will remove the browser's default focus style. If an element can be interacted with it must have a visible focus indicator."
|
|
16
|
-
| 3:1 ring in every theme | [Understanding Non-text Contrast](https://www.w3.org/WAI/WCAG22/Understanding/non-text-contrast.html): visual information needed to identify a state needs "a contrast ratio of at least 3:1 against adjacent color(s)"
|
|
12
|
+
| Bullet | Source | Read |
|
|
13
|
+
| ---------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -------------------- |
|
|
14
|
+
| One project focus ring | House choice: per-component focus styles drift apart, and `canon inventory` reports the ring by computed style, so a one-off treatment shows as its own row | 2026-10-18 |
|
|
15
|
+
| No outline removal without a replacement | [outline](https://developer.mozilla.org/en-US/docs/Web/CSS/outline): "Assigning outline a value of 0 or none will remove the browser's default focus style. If an element can be interacted with it must have a visible focus indicator." | 2026-10-18 |
|
|
16
|
+
| 3:1 ring in every theme | [Understanding Non-text Contrast](https://www.w3.org/WAI/WCAG22/Understanding/non-text-contrast.html): visual information needed to identify a state needs "a contrast ratio of at least 3:1 against adjacent color(s)" | 2026-10-18, WCAG 2.2 |
|
|
17
|
+
| Ring kept whole | [CSS UI 4](https://www.w3.org/TR/css-ui-4/): "By default, the outline is drawn starting just outside the border edge", and negative `outline-offset` values "must cause the outline to shrink into the border box". [MDN overflow](https://developer.mozilla.org/en-US/docs/Web/CSS/overflow): with `hidden`, "Overflow content is clipped at the element's padding box". [Understanding Focus Appearance](https://www.w3.org/WAI/WCAG22/Understanding/focus-appearance.html), Level AAA, asks for an indicator "at least as large as the area of a 2 CSS pixel thick perimeter". A partial clip passes AA, so the bullet rests on the project's own ring rule | 2026-10-23 |
|
|
17
18
|
|
|
18
19
|
## Keyboard operation
|
|
19
20
|
|
|
20
|
-
| Bullet
|
|
21
|
-
|
|
|
22
|
-
| Escape closes
|
|
23
|
-
| No bare character shortcut
|
|
24
|
-
|
|
|
21
|
+
| Bullet | Source | Read |
|
|
22
|
+
| -------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -------------------- |
|
|
23
|
+
| Escape closes | [Dialog (modal) pattern](https://www.w3.org/WAI/ARIA/apg/patterns/dialog-modal/): "Escape : Closes the dialog", and the [combobox pattern](https://www.w3.org/WAI/ARIA/apg/patterns/combobox/) gives Escape the same job for a popup | 2026-10-18, APG |
|
|
24
|
+
| No bare character shortcut | [Understanding Character Key Shortcuts](https://www.w3.org/WAI/WCAG22/Understanding/character-key-shortcuts.html): a character-only shortcut needs a way to "Turn off", to "Remap", or to be "Active only on focus" | 2026-10-18, WCAG 2.2 |
|
|
25
|
+
| No keyboard trap | [Understanding No Keyboard Trap](https://www.w3.org/WAI/WCAG22/Understanding/no-keyboard-trap.html): "If keyboard focus can be moved to a component of the page using a keyboard interface, then focus can be moved away from that component using only a keyboard interface" | 2026-10-23, WCAG 2.2 |
|
|
25
26
|
|
|
26
27
|
## Composite widgets
|
|
27
28
|
|
|
28
|
-
| Bullet
|
|
29
|
-
|
|
|
30
|
-
| One item in the tab sequence
|
|
31
|
-
| Combobox keys
|
|
29
|
+
| Bullet | Source | Read |
|
|
30
|
+
| --------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | --------------- |
|
|
31
|
+
| One item in the tab sequence | [Developing a keyboard interface](https://www.w3.org/WAI/ARIA/apg/practices/keyboard-interface/): "the tab sequence should include only one focusable element of a composite UI component", managed by "a roving tabindex" or "the aria-activedescendant property" | 2026-10-18, APG |
|
|
32
|
+
| Combobox keys | [Combobox pattern](https://www.w3.org/WAI/ARIA/apg/patterns/combobox/): "Down Arrow : If the popup is available, moves focus into the popup", Enter accepts the focused option, and "Escape : Dismisses the popup if it is visible" | 2026-10-18, APG |
|
|
33
|
+
| Spinbutton keys and the pattern pointer | [Spinbutton pattern](https://www.w3.org/WAI/ARIA/apg/patterns/spinbutton/): Up Arrow "Increases the value", Down Arrow decreases it, Home and End set the limits where they exist, and Page Up is optional, "by a larger step than Up Arrow". The pointer to other patterns rests on the [APG patterns index](https://www.w3.org/WAI/ARIA/apg/patterns/), "How to build accessibility semantics into web patterns and widgets", and a bullet per pattern is declined below | 2026-10-23, APG |
|
|
32
34
|
|
|
33
35
|
## Focus management
|
|
34
36
|
|
|
@@ -37,17 +39,14 @@ The field is web accessibility, and the authorities are the W3C, through WCAG 2.
|
|
|
37
39
|
| Focus into a dialog and back | [Dialog (modal) pattern](https://www.w3.org/WAI/ARIA/apg/patterns/dialog-modal/): "When a dialog opens, focus moves to an element inside the dialog", and "When a dialog closes, focus returns to the element that invoked the dialog" | 2026-10-18, APG |
|
|
38
40
|
| Focus never covered | [Understanding Focus Not Obscured (Minimum)](https://www.w3.org/WAI/WCAG22/Understanding/focus-not-obscured-minimum.html): "the component is not entirely hidden due to author-created content" | 2026-10-18, WCAG 2.2 |
|
|
39
41
|
|
|
40
|
-
## Pointer targets
|
|
41
|
-
|
|
42
|
-
| Bullet | Source | Read |
|
|
43
|
-
| ------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -------------------- |
|
|
44
|
-
| 24 by 24 on the web | [Understanding Target Size (Minimum)](https://www.w3.org/WAI/WCAG22/Understanding/target-size-minimum.html): "at least 24 by 24 CSS pixels", except where "a 24 CSS pixel diameter circle is centered on the bounding box of each" and "the circles do not intersect" | 2026-10-18, WCAG 2.2 |
|
|
45
|
-
| Native figures | [Apple accessibility guidelines](https://developer.apple.com/design/human-interface-guidelines/accessibility): a default "44x44 pt" control size on iOS and iPadOS, and [Android accessibility](https://developer.android.com/guide/topics/ui/accessibility/apps): "a focusable area, or touch target size , of at least 48dpx48dp" | 2026-10-18 |
|
|
46
|
-
|
|
47
42
|
## Declined
|
|
48
43
|
|
|
49
44
|
Every bullet the split removed or reshaped, grouped by why.
|
|
50
45
|
|
|
46
|
+
### Left to axe or to a person
|
|
47
|
+
|
|
48
|
+
- Declined a bullet per APG pattern. One pointer to the pattern page costs a line, and a bullet per pattern costs context on every component edit.
|
|
49
|
+
|
|
51
50
|
### Browser defaults
|
|
52
51
|
|
|
53
52
|
- Cut the Tab, Enter, and Space bullets of the old keyboard model. A native element does each by default, and `a11y.md` already sends a session to the native element.
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
---
|
|
2
|
+
title: Pointer rule ledger
|
|
3
|
+
description: Sources for governance/rules/ui/pointer.md, one row per bullet
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# Pointer rule ledger
|
|
7
|
+
|
|
8
|
+
The field is web accessibility, and the authorities are the W3C, through WCAG 2.2 and the ARIA Authoring Practices Guide, MDN for popover behavior, and the platform guidelines from Apple and Android for native targets. These bullets were split from `keyboard.md`.
|
|
9
|
+
|
|
10
|
+
## Pointer actions
|
|
11
|
+
|
|
12
|
+
| Bullet | Source | Read |
|
|
13
|
+
| ------------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -------------------- |
|
|
14
|
+
| Drag has a single-pointer path | [Understanding Dragging Movements](https://www.w3.org/WAI/WCAG22/Understanding/dragging-movements.html): "For any action that involves dragging, provide a simple pointer alternative" | 2026-10-18, WCAG 2.2 |
|
|
15
|
+
| Outside press and focus leave dismiss | [Using the Popover API](https://developer.mozilla.org/en-US/docs/Web/API/Popover_API/Using): you can hide the popover "by clicking outside it", and [the APG disclosure navigation example](https://www.w3.org/WAI/ARIA/apg/patterns/disclosure/examples/disclosure-navigation/): "Moving focus out of the navigation region also closes an open dropdown" | 2026-10-23 |
|
|
16
|
+
| Pointer action on release | [Understanding Pointer Cancellation](https://www.w3.org/WAI/WCAG22/Understanding/pointer-cancellation.html): one of "No Down-Event", "Abort or Undo", or "Up Reversal" holds for single-pointer functionality | 2026-10-23, WCAG 2.2 |
|
|
17
|
+
| Gestures have a single-pointer path | [Understanding Pointer Gestures](https://www.w3.org/WAI/WCAG22/Understanding/pointer-gestures.html): "All functionality that uses multipoint or path-based gestures for operation can be operated with a single pointer without a path-based gesture" | 2026-10-23, WCAG 2.2 |
|
|
18
|
+
|
|
19
|
+
## Pointer targets
|
|
20
|
+
|
|
21
|
+
| Bullet | Source | Read |
|
|
22
|
+
| ------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -------------------- |
|
|
23
|
+
| 24 by 24 on the web | [Understanding Target Size (Minimum)](https://www.w3.org/WAI/WCAG22/Understanding/target-size-minimum.html): "at least 24 by 24 CSS pixels", except where "a 24 CSS pixel diameter circle is centered on the bounding box of each" and "the circles do not intersect" | 2026-10-18, WCAG 2.2 |
|
|
24
|
+
| Native figures | [Apple accessibility guidelines](https://developer.apple.com/design/human-interface-guidelines/accessibility): a default "44x44 pt" control size on iOS and iPadOS, and [Android accessibility](https://developer.android.com/guide/topics/ui/accessibility/apps): "a focusable area, or touch target size , of at least 48dpx48dp" | 2026-10-18 |
|
|
@@ -16,21 +16,21 @@ The rule states canon's own evidence procedure for a rendered change, so most ro
|
|
|
16
16
|
|
|
17
17
|
## When to capture
|
|
18
18
|
|
|
19
|
-
| Bullet
|
|
20
|
-
|
|
|
21
|
-
| Preview, not dev server
|
|
22
|
-
| Every theme, and again
|
|
19
|
+
| Bullet | Source | Read |
|
|
20
|
+
| ---------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ---------- |
|
|
21
|
+
| Preview, not dev server | House choice: a dev server injects overlays and skips the production build's transforms, so its frame differs from what ships | 2026-10-18 |
|
|
22
|
+
| Every theme, and again | House choice: a defect in the dark theme passes a light-only capture, and a repair inside a shared stylesheet can cancel a rule written earlier in the same file | 2026-10-18 |
|
|
23
|
+
| Read the capture before the pull request | House choice: a defect visible in the worker's own capture, such as a 20px target under the 24px bullet in `pointer.md`, reached review because nobody read the frame against the checklist first, and each review round re-runs both reviews. The skill ships with the plugin, so the bullet carries a report-if-missing clause | 2026-10-23 |
|
|
23
24
|
|
|
24
25
|
## What a capture covers
|
|
25
26
|
|
|
26
|
-
| Bullet
|
|
27
|
-
|
|
|
28
|
-
| Full page
|
|
29
|
-
| 320 plus breakpoints
|
|
30
|
-
| Chrome at both clamps
|
|
31
|
-
| State case at one width
|
|
32
|
-
|
|
|
33
|
-
| Case lives with the surface | House choice: a surface with no case ships uncaptured, and a case left after its surface goes fails every later capture run | 2026-10-18 |
|
|
27
|
+
| Bullet | Source | Read |
|
|
28
|
+
| ------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -------------------- |
|
|
29
|
+
| Full page | House choice: a component captured alone shows none of the spacing, overflow, or stacking its page imposes on it | 2026-10-18 |
|
|
30
|
+
| 320 plus breakpoints | [Understanding Reflow](https://www.w3.org/WAI/WCAG22/Understanding/reflow.html): the criterion tests "a width equivalent to 320 CSS pixels". A 320 frame proves a frame was taken there, never that the page reflows, which `a11y.md` states. | 2026-10-18, WCAG 2.2 |
|
|
31
|
+
| Chrome at both clamps | House choice: a sidebar widened to its clamp leaves the content under the floor at a window width the criterion passes, and a frame where the chrome turned into an overlay shows none of the width it takes | 2026-10-18 |
|
|
32
|
+
| State case at one width, driven | House choice: a case driving a menu open tests the state, and repeating it at every layout width multiplies the evidence with no layout to compare, and an initial render reports nothing about a menu that opens, an answer that is chosen, or a rail that tracks scrolling | 2026-10-18 |
|
|
33
|
+
| Case lives with the surface | House choice: a surface with no case ships uncaptured, and a case left after its surface goes fails every later capture run | 2026-10-18 |
|
|
34
34
|
|
|
35
35
|
## Sharing a capture
|
|
36
36
|
|
|
@@ -9,11 +9,12 @@ The field is interaction design, and the authorities are the Nielsen Norman Grou
|
|
|
9
9
|
|
|
10
10
|
## Feedback
|
|
11
11
|
|
|
12
|
-
| Bullet
|
|
13
|
-
|
|
|
14
|
-
| Confirm success and failure
|
|
15
|
-
| Auto-dismiss only a redundant message
|
|
16
|
-
|
|
|
12
|
+
| Bullet | Source | Read |
|
|
13
|
+
| -------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -------------------- |
|
|
14
|
+
| Confirm success and failure | [Visibility of system status](https://www.nngroup.com/articles/visibility-system-status/): "Whenever users interact with a system, they need to know whether the interaction was successful" | 2026-10-18 |
|
|
15
|
+
| Auto-dismiss only a redundant message | [Understanding Timing Adjustable](https://www.w3.org/WAI/WCAG22/Understanding/timing-adjustable.html): "If the user has no other means of discovering the same information (or performing the same function), then each message would need to meet this success criterion" | 2026-10-18, WCAG 2.2 |
|
|
16
|
+
| Timed messages pause and take no focus | [Fluent 2, Toast usage](https://fluent2.microsoft.design/components/web/react/core/toast/usage): a toast with no action times out "after seven seconds", and mouse users "can pause the timer by hovering". [Understanding Status Messages](https://www.w3.org/WAI/WCAG22/Understanding/status-messages.html): status messages are presented "without receiving focus". The pause leaves the redundant-message bullet's rule for when a message may leave unchanged | 2026-10-23 |
|
|
17
|
+
| No optimistic status | House choice: a "connected" dot shown over unsaved edits reports a state the system has not reached, and the person leaves believing their change took | 2026-10-18 |
|
|
17
18
|
|
|
18
19
|
## Empty states
|
|
19
20
|
|
|
@@ -29,26 +30,13 @@ The field is interaction design, and the authorities are the Nielsen Norman Grou
|
|
|
29
30
|
| Indicator past one second | [Progress indicators](https://www.nngroup.com/articles/progress-indicators/): "Use a progress indicator for any action that takes longer than about 1.0 second" | 2026-10-18 |
|
|
30
31
|
| Mark stale content as updating | [Progress indicators](https://www.nngroup.com/articles/progress-indicators/): "Without any visual change from the system, most users will assume the action was not registered and they will try again" | 2026-10-18 |
|
|
31
32
|
|
|
32
|
-
## Destructive actions
|
|
33
|
-
|
|
34
|
-
| Bullet | Source | Read |
|
|
35
|
-
| ----------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | ---------- |
|
|
36
|
-
| Confirm unless undoable | [Confirmation dialogs](https://www.nngroup.com/articles/confirmation-dialog/): "consider a confirmation dialog before actions that cannot be undone", and "do try your best to offer undo" | 2026-10-18 |
|
|
37
|
-
|
|
38
|
-
## Element states
|
|
39
|
-
|
|
40
|
-
| Bullet | Source | Read |
|
|
41
|
-
| --------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ---------- |
|
|
42
|
-
| Distinct interaction states | [Visibility of system status](https://www.nngroup.com/articles/visibility-system-status/): "Did the system actually catch that button press", and an element with no pressed or hover response leaves the person unable to tell | 2026-10-18 |
|
|
43
|
-
| No intermediate flash | [Cumulative Layout Shift](https://web.dev/articles/cls): "Unexpected layout shifts can disrupt the user experience", caused by content "dynamically added to the page before existing content" | 2026-10-18 |
|
|
44
|
-
|
|
45
33
|
## Overflow
|
|
46
34
|
|
|
47
|
-
| Bullet
|
|
48
|
-
|
|
|
49
|
-
| Ellipsis over overflow
|
|
50
|
-
| Never `title` alone
|
|
51
|
-
|
|
|
35
|
+
| Bullet | Source | Read |
|
|
36
|
+
| ------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ---------- |
|
|
37
|
+
| Ellipsis over overflow | [text-overflow](https://developer.mozilla.org/en-US/docs/Web/CSS/text-overflow): `text-overflow: ellipsis` with `overflow: hidden` and `white-space: nowrap` clips text at the box with a visible marker | 2026-10-18 |
|
|
38
|
+
| Never `title` alone | [The title attribute](https://developer.mozilla.org/en-US/docs/Web/HTML/Reference/Global_attributes/title): "Use of the title attribute is highly problematic for" people using touch-only devices, keyboards, and assistive technology | 2026-10-18 |
|
|
39
|
+
| Borders clear of clipping | House choice: a ring cut off by a parent's `overflow` shows on the middle items of a list and vanishes on the first and last, so the focus indicator fails exactly where the list ends | 2026-10-18 |
|
|
52
40
|
|
|
53
41
|
## Declined
|
|
54
42
|
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
---
|
|
2
|
+
title: UX controls rule ledger
|
|
3
|
+
description: Sources for governance/rules/ui/ux-controls.md, one row per bullet
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# UX controls rule ledger
|
|
7
|
+
|
|
8
|
+
The field is interaction design, and the authorities are the Nielsen Norman Group, WCAG 2.2, Primer, Cloudscape, MDN, and web.dev. These bullets were split from `ux-completeness.md`.
|
|
9
|
+
|
|
10
|
+
## Destructive actions
|
|
11
|
+
|
|
12
|
+
| Bullet | Source | Read |
|
|
13
|
+
| ----------------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ---------- |
|
|
14
|
+
| Confirm unless undoable | [Confirmation dialogs](https://www.nngroup.com/articles/confirmation-dialog/): "consider a confirmation dialog before actions that cannot be undone", and "do try your best to offer undo" | 2026-10-18 |
|
|
15
|
+
| Cancelled edit restores, never discards unasked | [Primer, Edit pattern](https://primer.style/product/scenario-patterns/edit): "Put the content back to the value it had before the edit when someone cancels", and "Confirm before discarding an edit someone has put work into". The anti-pattern is to "Discard a half-written edit because someone pressed Escape or clicked outside the editor" | 2026-10-23 |
|
|
16
|
+
|
|
17
|
+
## Element states
|
|
18
|
+
|
|
19
|
+
| Bullet | Source | Read |
|
|
20
|
+
| -------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -------------------- |
|
|
21
|
+
| Distinct interaction states | [Visibility of system status](https://www.nngroup.com/articles/visibility-system-status/): "Did the system actually catch that button press", and an element with no pressed or hover response leaves the person unable to tell | 2026-10-18 |
|
|
22
|
+
| Say why a control is disabled | [Cloudscape, Disabled and read-only states](https://cloudscape.design/patterns/general/disabled-and-read-only-states/): "Use disabled reasons where adequate context is not provided through disabled button or label text", and `aria-disabled="true"` is used "so that it will remain focusable" | 2026-10-23 |
|
|
23
|
+
| Declare `color-scheme` | [MDN, color-scheme](https://developer.mozilla.org/en-US/docs/Web/CSS/Reference/Properties/color-scheme): the user agent adapts "The default colors of scrollbars and other interaction UI" and "The default colors of form controls", and the page opts in by declaring it on the `:root` element | 2026-10-23 |
|
|
24
|
+
| Hover and focus content | [Understanding Content on Hover or Focus](https://www.w3.org/WAI/WCAG22/Understanding/content-on-hover-or-focus.html): additional content is "Dismissible" without moving hover or focus, "Hoverable" so the pointer can move over it, and "Persistent" until "the hover or focus trigger is removed, the user dismisses it, or its information is no longer valid" | 2026-10-23, WCAG 2.2 |
|
|
25
|
+
| No change of context on focus or input | [Understanding On Focus](https://www.w3.org/WAI/WCAG22/Understanding/on-focus.html): "When any user interface component receives focus, it does not initiate a change of context". [Understanding On Input](https://www.w3.org/WAI/WCAG22/Understanding/on-input.html): changing a setting does not cause one "unless the user has been advised of the behavior before using the component" | 2026-10-23, WCAG 2.2 |
|
|
26
|
+
| No intermediate flash | [Cumulative Layout Shift](https://web.dev/articles/cls): "Unexpected layout shifts can disrupt the user experience", caused by content "dynamically added to the page before existing content" | 2026-10-18 |
|
|
@@ -16,6 +16,7 @@ paths:
|
|
|
16
16
|
- Spell an attribute the way the file's syntax spells it, being `onclick` and `tabindex` in HTML and Astro markup and `onClick` and `tabIndex` in JSX.
|
|
17
17
|
- Give a custom control the role its pattern names, such as `combobox` or `listbox`, and keep `aria-expanded`, `aria-selected`, and `aria-checked` in step with what it shows.
|
|
18
18
|
- Give an interactive element with no visible text label a name through `aria-label` or `aria-labelledby`.
|
|
19
|
+
- Put the visible text in the accessible name, first where you can (WCAG 2.5.3).
|
|
19
20
|
|
|
20
21
|
## Text alternatives
|
|
21
22
|
|
|
@@ -26,6 +27,7 @@ paths:
|
|
|
26
27
|
|
|
27
28
|
- Give a control's visual boundary and every graphic that carries meaning at least 3:1 contrast against adjacent colors (WCAG 1.4.11).
|
|
28
29
|
- Never make color the only carrier of a state, error, or distinction. Pair it with text, an icon, or a pattern (WCAG 1.4.1).
|
|
30
|
+
- Give text 4.5:1 contrast, or 3:1 when large (WCAG 1.4.3).
|
|
29
31
|
|
|
30
32
|
## Reflow
|
|
31
33
|
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
---
|
|
2
|
-
description: Focus styles, keyboard operation,
|
|
2
|
+
description: Focus styles, keyboard operation, composite widgets, and focus management for rendered UI
|
|
3
3
|
paths:
|
|
4
4
|
- '**/*.tsx'
|
|
5
5
|
- '**/*.jsx'
|
|
@@ -15,24 +15,21 @@ paths:
|
|
|
15
15
|
- Style focus through the project's one focus ring rather than a per-component focus style.
|
|
16
16
|
- Never set `outline: none` or `outline-none` without a replacement focus indicator in the same rule.
|
|
17
17
|
- Give the focus ring 3:1 contrast against its background in every theme the project ships.
|
|
18
|
+
- Keep the focus ring whole. Where an ancestor's `overflow` would clip it, inset it with a negative `outline-offset` or pad the edge items of the list.
|
|
18
19
|
|
|
19
20
|
## Keyboard operation
|
|
20
21
|
|
|
21
22
|
- Close a dialog, popover, menu, or inline confirmation on Escape, and cancel an in-progress edit the same way.
|
|
23
|
+
- Never trap keyboard focus. A person who tabs into a component can leave it by keyboard alone, and a modal dialog leaves on Escape (WCAG 2.1.2).
|
|
22
24
|
- Bind no single printable character as a shortcut unless a person can turn it off or remap it, or it fires only while its control has focus (WCAG 2.1.4).
|
|
23
|
-
- Give every author-defined drag a single-pointer alternative and a keyboard path, such as move buttons or arrow-key reordering (WCAG 2.5.7).
|
|
24
25
|
|
|
25
26
|
## Composite widgets
|
|
26
27
|
|
|
27
28
|
- Keep one item of a composite widget in the tab sequence, and move between its items with the arrow keys through roving `tabindex` or `aria-activedescendant`.
|
|
28
29
|
- Open a combobox popup on Down Arrow, accept the focused option on Enter, and close the popup on Escape without changing the value.
|
|
30
|
+
- Give a custom number input the spinbutton keys, Up and Down to step and Home and End for the limits. Take the keys of any other custom widget from its ARIA Authoring Practices Guide pattern.
|
|
29
31
|
|
|
30
32
|
## Focus management
|
|
31
33
|
|
|
32
34
|
- Move focus into a dialog when it opens, and return it to the element that opened it when it closes.
|
|
33
35
|
- Never let a sticky header, footer, or overlay fully cover the focused control. Scroll it clear of them (WCAG 2.4.11).
|
|
34
|
-
|
|
35
|
-
## Pointer targets
|
|
36
|
-
|
|
37
|
-
- Size a web pointer target at least 24 by 24 CSS pixels, or space it so a 24 pixel circle centered on it touches no other target (WCAG 2.5.8).
|
|
38
|
-
- Size a native touch target at the platform figure, 44 points on iOS and 48 dp on Android, and never swap the web and native figures.
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
---
|
|
2
|
+
description: Pointer actions, gestures, outside-press dismissal, and target size for rendered UI
|
|
3
|
+
paths:
|
|
4
|
+
- '**/*.tsx'
|
|
5
|
+
- '**/*.jsx'
|
|
6
|
+
- '**/*.astro'
|
|
7
|
+
- '**/*.html'
|
|
8
|
+
- '**/*.css'
|
|
9
|
+
---
|
|
10
|
+
|
|
11
|
+
# Pointer standards
|
|
12
|
+
|
|
13
|
+
## Pointer actions
|
|
14
|
+
|
|
15
|
+
- Dismiss a popover or menu on a press outside it and when focus leaves it, as well as on Escape.
|
|
16
|
+
- Run a pointer action on release rather than press, so a person can slide off the target to abort it (WCAG 2.5.2).
|
|
17
|
+
- Give a path-based or multipoint gesture, such as a swipe or pinch, a single-pointer alternative with no path (WCAG 2.5.1).
|
|
18
|
+
- Give every author-defined drag a single-pointer alternative and a keyboard path, such as move buttons or arrow-key reordering (WCAG 2.5.7).
|
|
19
|
+
|
|
20
|
+
## Pointer targets
|
|
21
|
+
|
|
22
|
+
- Size a web pointer target at least 24 by 24 CSS pixels, or space it so a 24 pixel circle centered on it touches no other target (WCAG 2.5.8).
|
|
23
|
+
- Size a native touch target at the platform figure, 44 points on iOS and 48 dp on Android, and never swap the web and native figures.
|
|
@@ -12,21 +12,21 @@ paths:
|
|
|
12
12
|
|
|
13
13
|
## What a surface is
|
|
14
14
|
|
|
15
|
-
- Treat anything the project renders for a person as a surface,
|
|
15
|
+
- Treat anything the project renders for a person as a surface, generated pages included.
|
|
16
16
|
- Skip a component the production build strips out, such as a dev-only switcher.
|
|
17
17
|
|
|
18
18
|
## When to capture
|
|
19
19
|
|
|
20
|
-
- Run the project's capture command against a preview server, never a dev server, after changing a surface. Report
|
|
21
|
-
- Capture every theme the surface ships, and again after fixing a defect
|
|
20
|
+
- Run the project's capture command against a preview server, never a dev server, after changing a surface. Report a project with none.
|
|
21
|
+
- Capture every theme the surface ships, and again after fixing a defect found.
|
|
22
|
+
- Read your capture against the `canon:ui-checklist` boxes before opening the pull request, reporting a skill that does not resolve.
|
|
22
23
|
|
|
23
24
|
## What a capture covers
|
|
24
25
|
|
|
25
26
|
- Capture the full page, never a component in isolation.
|
|
26
27
|
- Capture a layout case at 320, the reflow floor in `a11y`, plus each breakpoint in the `## Layout` section of `DESIGN.md`, or at 320 alone when there is none.
|
|
27
28
|
- Capture resizable chrome at its narrowest and widest clamp, at the narrowest width keeping it persistent. Judge the content width beside it.
|
|
28
|
-
- Capture a state case at one width
|
|
29
|
-
- Drive a state an initial render cannot reach, such as an open menu or a rail tracking scroll.
|
|
29
|
+
- Capture a state case at one width, driving states a first render cannot reach, such as an open menu.
|
|
30
30
|
- Add a surface's case with the surface, and remove it with the surface.
|
|
31
31
|
|
|
32
32
|
## Sharing a capture
|
|
@@ -14,6 +14,7 @@ paths:
|
|
|
14
14
|
|
|
15
15
|
- Confirm every user-initiated mutation, such as a save, delete, or import, inline on success, and show an inline error when it fails.
|
|
16
16
|
- Auto-dismiss a success message only when its outcome stays visible elsewhere. Keep a message carrying the only copy of its information until dismissed (WCAG 2.2.1).
|
|
17
|
+
- Pause a timed message while it has pointer hover or keyboard focus, and take no focus for it. A person finishes reading it, and a status message never interrupts typing (WCAG 4.1.3).
|
|
17
18
|
- Show no optimistic status, such as a green dot or "connected", while unsaved edits are pending.
|
|
18
19
|
|
|
19
20
|
## Empty states
|
|
@@ -26,17 +27,8 @@ paths:
|
|
|
26
27
|
- Show a progress indicator for any operation a person waits on for longer than about one second.
|
|
27
28
|
- Mark previous content as updating while new content loads, rather than showing it unmarked as current.
|
|
28
29
|
|
|
29
|
-
## Destructive actions
|
|
30
|
-
|
|
31
|
-
- Confirm a destructive action, such as a delete, disconnect, or discard, before it runs, unless it can be undone afterward.
|
|
32
|
-
|
|
33
|
-
## Element states
|
|
34
|
-
|
|
35
|
-
- Give every interactive element distinct hover, active, focus, and disabled styles.
|
|
36
|
-
- Never flash an intermediate state, such as a light frame before a dark theme or a layout jump before data arrives. Reserve the space or settle it first.
|
|
37
|
-
|
|
38
30
|
## Overflow
|
|
39
31
|
|
|
40
32
|
- Truncate long text in a constrained container with an ellipsis rather than letting it overflow.
|
|
41
33
|
- Expose truncated text through an expand control or full text on focus, never through a `title` tooltip alone.
|
|
42
|
-
- Keep
|
|
34
|
+
- Keep interactive borders clear of a parent's `overflow` clipping, padding the edge items of a scrollable list.
|