@brunosps00/dev-workflow 0.11.0 → 0.15.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/README.md +54 -5
- package/lib/constants.js +20 -20
- package/lib/init.js +24 -1
- package/lib/migrate-skills.js +129 -0
- package/lib/removed-bundled-skills.js +16 -0
- package/lib/uninstall.js +6 -2
- package/lib/utils.js +43 -1
- package/package.json +1 -1
- package/scaffold/en/agent-instructions.md +68 -0
- package/scaffold/en/commands/dw-autopilot.md +1 -1
- package/scaffold/en/commands/dw-brainstorm.md +1 -1
- package/scaffold/en/commands/dw-bugfix.md +4 -3
- package/scaffold/en/commands/dw-code-review.md +1 -0
- package/scaffold/en/commands/dw-create-tasks.md +6 -0
- package/scaffold/en/commands/dw-create-techspec.md +1 -1
- package/scaffold/en/commands/dw-deps-audit.md +1 -1
- package/scaffold/en/commands/dw-fix-qa.md +1 -1
- package/scaffold/en/commands/dw-functional-doc.md +2 -2
- package/scaffold/en/commands/dw-help.md +2 -2
- package/scaffold/en/commands/dw-redesign-ui.md +7 -7
- package/scaffold/en/commands/dw-run-qa.md +5 -4
- package/scaffold/en/commands/dw-run-task.md +2 -2
- package/scaffold/en/templates/constitution-template.md +1 -1
- package/scaffold/pt-br/agent-instructions.md +68 -0
- package/scaffold/pt-br/commands/dw-autopilot.md +1 -1
- package/scaffold/pt-br/commands/dw-brainstorm.md +1 -1
- package/scaffold/pt-br/commands/dw-bugfix.md +4 -3
- package/scaffold/pt-br/commands/dw-code-review.md +1 -0
- package/scaffold/pt-br/commands/dw-create-tasks.md +6 -0
- package/scaffold/pt-br/commands/dw-create-techspec.md +1 -1
- package/scaffold/pt-br/commands/dw-deps-audit.md +1 -1
- package/scaffold/pt-br/commands/dw-fix-qa.md +1 -1
- package/scaffold/pt-br/commands/dw-functional-doc.md +2 -2
- package/scaffold/pt-br/commands/dw-help.md +2 -2
- package/scaffold/pt-br/commands/dw-redesign-ui.md +7 -7
- package/scaffold/pt-br/commands/dw-run-qa.md +5 -4
- package/scaffold/pt-br/commands/dw-run-task.md +2 -2
- package/scaffold/pt-br/templates/constitution-template.md +1 -1
- package/scaffold/skills/dw-council/SKILL.md +1 -1
- package/scaffold/skills/dw-incident-response/SKILL.md +164 -0
- package/scaffold/skills/dw-incident-response/references/blameless-discipline.md +126 -0
- package/scaffold/skills/dw-incident-response/references/communication-templates.md +107 -0
- package/scaffold/skills/dw-incident-response/references/postmortem-template.md +133 -0
- package/scaffold/skills/dw-incident-response/references/runbook-templates.md +169 -0
- package/scaffold/skills/dw-incident-response/references/severity-and-triage.md +186 -0
- package/scaffold/skills/dw-llm-eval/SKILL.md +148 -0
- package/scaffold/skills/dw-llm-eval/references/agent-eval.md +252 -0
- package/scaffold/skills/dw-llm-eval/references/judge-calibration.md +169 -0
- package/scaffold/skills/dw-llm-eval/references/oracle-ladder.md +171 -0
- package/scaffold/skills/dw-llm-eval/references/rag-metrics.md +186 -0
- package/scaffold/skills/dw-llm-eval/references/reference-dataset.md +190 -0
- package/scaffold/skills/dw-testing-discipline/SKILL.md +171 -0
- package/scaffold/skills/dw-testing-discipline/references/agent-guardrails.md +170 -0
- package/scaffold/skills/dw-testing-discipline/references/anti-patterns.md +336 -0
- package/scaffold/skills/dw-testing-discipline/references/core-rules.md +128 -0
- package/scaffold/skills/dw-testing-discipline/references/flaky-discipline.md +163 -0
- package/scaffold/skills/dw-testing-discipline/references/patterns.md +241 -0
- package/scaffold/skills/dw-testing-discipline/references/playwright-recipes.md +282 -0
- package/scaffold/skills/{webapp-testing → dw-testing-discipline}/references/security-boundary.md +1 -1
- package/scaffold/skills/dw-ui-discipline/SKILL.md +150 -0
- package/scaffold/skills/dw-ui-discipline/references/accessibility-floor.md +225 -0
- package/scaffold/skills/dw-ui-discipline/references/curated-defaults.md +195 -0
- package/scaffold/skills/dw-ui-discipline/references/hard-gate.md +162 -0
- package/scaffold/skills/dw-ui-discipline/references/state-matrix.md +101 -0
- package/scaffold/skills/dw-ui-discipline/references/visual-slop.md +152 -0
- package/scaffold/skills/ui-ux-pro-max/LICENSE +0 -21
- package/scaffold/skills/ui-ux-pro-max/SKILL.md +0 -659
- package/scaffold/skills/ui-ux-pro-max/data/_sync_all.py +0 -414
- package/scaffold/skills/ui-ux-pro-max/data/app-interface.csv +0 -31
- package/scaffold/skills/ui-ux-pro-max/data/charts.csv +0 -26
- package/scaffold/skills/ui-ux-pro-max/data/colors.csv +0 -162
- package/scaffold/skills/ui-ux-pro-max/data/design.csv +0 -1776
- package/scaffold/skills/ui-ux-pro-max/data/draft.csv +0 -1779
- package/scaffold/skills/ui-ux-pro-max/data/google-fonts.csv +0 -1924
- package/scaffold/skills/ui-ux-pro-max/data/icons.csv +0 -106
- package/scaffold/skills/ui-ux-pro-max/data/landing.csv +0 -35
- package/scaffold/skills/ui-ux-pro-max/data/products.csv +0 -162
- package/scaffold/skills/ui-ux-pro-max/data/react-performance.csv +0 -45
- package/scaffold/skills/ui-ux-pro-max/data/stacks/angular.csv +0 -51
- package/scaffold/skills/ui-ux-pro-max/data/stacks/astro.csv +0 -54
- package/scaffold/skills/ui-ux-pro-max/data/stacks/flutter.csv +0 -53
- package/scaffold/skills/ui-ux-pro-max/data/stacks/html-tailwind.csv +0 -56
- package/scaffold/skills/ui-ux-pro-max/data/stacks/jetpack-compose.csv +0 -53
- package/scaffold/skills/ui-ux-pro-max/data/stacks/laravel.csv +0 -51
- package/scaffold/skills/ui-ux-pro-max/data/stacks/nextjs.csv +0 -53
- package/scaffold/skills/ui-ux-pro-max/data/stacks/nuxt-ui.csv +0 -51
- package/scaffold/skills/ui-ux-pro-max/data/stacks/nuxtjs.csv +0 -59
- package/scaffold/skills/ui-ux-pro-max/data/stacks/react-native.csv +0 -52
- package/scaffold/skills/ui-ux-pro-max/data/stacks/react.csv +0 -54
- package/scaffold/skills/ui-ux-pro-max/data/stacks/shadcn.csv +0 -61
- package/scaffold/skills/ui-ux-pro-max/data/stacks/svelte.csv +0 -54
- package/scaffold/skills/ui-ux-pro-max/data/stacks/swiftui.csv +0 -51
- package/scaffold/skills/ui-ux-pro-max/data/stacks/threejs.csv +0 -54
- package/scaffold/skills/ui-ux-pro-max/data/stacks/vue.csv +0 -50
- package/scaffold/skills/ui-ux-pro-max/data/styles.csv +0 -85
- package/scaffold/skills/ui-ux-pro-max/data/typography.csv +0 -74
- package/scaffold/skills/ui-ux-pro-max/data/ui-reasoning.csv +0 -162
- package/scaffold/skills/ui-ux-pro-max/data/ux-guidelines.csv +0 -100
- package/scaffold/skills/ui-ux-pro-max/scripts/core.py +0 -262
- package/scaffold/skills/ui-ux-pro-max/scripts/design_system.py +0 -1148
- package/scaffold/skills/ui-ux-pro-max/scripts/search.py +0 -114
- package/scaffold/skills/ui-ux-pro-max/skills/brand/SKILL.md +0 -97
- package/scaffold/skills/ui-ux-pro-max/skills/design/SKILL.md +0 -302
- package/scaffold/skills/ui-ux-pro-max/skills/design-system/SKILL.md +0 -244
- package/scaffold/skills/ui-ux-pro-max/templates/base/quick-reference.md +0 -297
- package/scaffold/skills/ui-ux-pro-max/templates/base/skill-content.md +0 -358
- package/scaffold/skills/ui-ux-pro-max/templates/platforms/agent.json +0 -21
- package/scaffold/skills/ui-ux-pro-max/templates/platforms/augment.json +0 -18
- package/scaffold/skills/ui-ux-pro-max/templates/platforms/claude.json +0 -21
- package/scaffold/skills/ui-ux-pro-max/templates/platforms/codebuddy.json +0 -21
- package/scaffold/skills/ui-ux-pro-max/templates/platforms/codex.json +0 -21
- package/scaffold/skills/ui-ux-pro-max/templates/platforms/continue.json +0 -21
- package/scaffold/skills/ui-ux-pro-max/templates/platforms/copilot.json +0 -21
- package/scaffold/skills/ui-ux-pro-max/templates/platforms/cursor.json +0 -21
- package/scaffold/skills/ui-ux-pro-max/templates/platforms/droid.json +0 -21
- package/scaffold/skills/ui-ux-pro-max/templates/platforms/gemini.json +0 -21
- package/scaffold/skills/ui-ux-pro-max/templates/platforms/kilocode.json +0 -21
- package/scaffold/skills/ui-ux-pro-max/templates/platforms/kiro.json +0 -21
- package/scaffold/skills/ui-ux-pro-max/templates/platforms/opencode.json +0 -21
- package/scaffold/skills/ui-ux-pro-max/templates/platforms/qoder.json +0 -21
- package/scaffold/skills/ui-ux-pro-max/templates/platforms/roocode.json +0 -21
- package/scaffold/skills/ui-ux-pro-max/templates/platforms/trae.json +0 -21
- package/scaffold/skills/ui-ux-pro-max/templates/platforms/warp.json +0 -18
- package/scaffold/skills/ui-ux-pro-max/templates/platforms/windsurf.json +0 -21
- package/scaffold/skills/webapp-testing/SKILL.md +0 -138
- package/scaffold/skills/webapp-testing/assets/test-helper.js +0 -56
- /package/scaffold/skills/{webapp-testing → dw-testing-discipline}/references/three-workflow-patterns.md +0 -0
|
@@ -0,0 +1,150 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: dw-ui-discipline
|
|
3
|
+
description: Use BEFORE any UI work — runs a 4-question grounding (where do design decisions come from, what does this surface help the user do, what states does it have, who uses it where), then enforces the WCAG 2.2 AA floor and 14 visual-slop checks so UI ships with intent instead of training-data defaults.
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# UI Discipline
|
|
7
|
+
|
|
8
|
+
Training-data defaults are the enemy. An ungrounded LLM proposing UI will reach for `#3B82F6` blue, `rounded-lg` radius, center-aligned text, and gradient backgrounds — because those screenshots dominate training data. The surface ends up looking like every other SaaS dashboard, and users can't tell what to look at first.
|
|
9
|
+
|
|
10
|
+
This skill blocks that autopilot at four grounding questions before any visual decision lands. After the questions pass, it enforces an accessibility floor and runs a visual-slop catalog as the proposed design comes together.
|
|
11
|
+
|
|
12
|
+
## When to use
|
|
13
|
+
|
|
14
|
+
- Inside `/dw-redesign-ui` — both proposal and validation steps.
|
|
15
|
+
- Inside `/dw-create-techspec` when the spec has UI sections.
|
|
16
|
+
- Inside `/dw-functional-doc` when documenting screen-level patterns.
|
|
17
|
+
- Inside `/dw-code-review` when the diff touches UI files (CSS, JSX, templates).
|
|
18
|
+
- Inside `/dw-brainstorm` when the conversation drifts into visual direction.
|
|
19
|
+
|
|
20
|
+
If you're tempted to skip this "because it's just a small tweak" — that's the trigger. Run the grounding.
|
|
21
|
+
|
|
22
|
+
## The four grounding questions
|
|
23
|
+
|
|
24
|
+
Answer all four before proposing colors, layouts, components, or any visual decision.
|
|
25
|
+
|
|
26
|
+
### 1. Where do design decisions come from?
|
|
27
|
+
|
|
28
|
+
Find the project's design source-of-truth in this order:
|
|
29
|
+
1. `.dw/rules/<frontend-module>.md` design system section.
|
|
30
|
+
2. `DESIGN.md`, `BRAND.md`, `STYLE_GUIDE.md` at project root.
|
|
31
|
+
3. Design token config — Tailwind theme, CSS variables in `theme.css`/`globals.css`, MUI/Chakra theme.
|
|
32
|
+
4. Component library config — `components.json` for shadcn, theme exports.
|
|
33
|
+
5. Storybook stories (implicit canonical components).
|
|
34
|
+
|
|
35
|
+
If **at least one** exists: it wins. Defer to it. If a needed token is missing (e.g., a danger-secondary color), propose adding it to the authority FIRST, not inline.
|
|
36
|
+
|
|
37
|
+
If **none exists**: read `references/curated-defaults.md` and pick one of the 10 neutral palettes + one of the 10 font pairings shipped there. Mark the choice in the techspec/PR description: "Design source: no project authority found; using curated default `<name>`; recommend establishing `DESIGN.md`."
|
|
38
|
+
|
|
39
|
+
**Anti-patterns at this question:**
|
|
40
|
+
- Inventing color hex values inline (`bg-[#FF6B35]`).
|
|
41
|
+
- "I'll use Tailwind defaults" — that's training-data defaults, not project authority.
|
|
42
|
+
- Copying values from "a site I like" without understanding what it solved.
|
|
43
|
+
|
|
44
|
+
### 2. What does this surface help the user do?
|
|
45
|
+
|
|
46
|
+
Write one sentence: **"This surface helps the user `<verb-phrase>` so that `<outcome>`."**
|
|
47
|
+
|
|
48
|
+
Good examples:
|
|
49
|
+
- "...helps the user filter overdue invoices so they can chase late payers in under 30 seconds."
|
|
50
|
+
- "...helps the on-call engineer diagnose which deploy caused the spike so they can roll back without paging the team."
|
|
51
|
+
- "...helps the manager approve or reject expense reports without leaving Slack."
|
|
52
|
+
|
|
53
|
+
Bad examples:
|
|
54
|
+
- "This surface displays invoice data." (no user, no outcome)
|
|
55
|
+
- "Settings page for managing the account." (vague, no specificity)
|
|
56
|
+
- "Dashboard." (one word)
|
|
57
|
+
|
|
58
|
+
If you can't write the sentence, the requirements are unclear. Stop and clarify before proceeding.
|
|
59
|
+
|
|
60
|
+
### 3. What states does the surface have?
|
|
61
|
+
|
|
62
|
+
Enumerate all states before designing the happy path. Minimum nine, plus domain-specific ones — see `references/state-matrix.md`:
|
|
63
|
+
|
|
64
|
+
`default`, `hover`, `active`, `focus-visible`, `disabled`, `loading`, `empty`, `error`, `success` plus any domain states (read/unread, online/offline, stale/fresh, pending/approved/rejected, draft/saved/dirty, partial/complete, etc.).
|
|
65
|
+
|
|
66
|
+
Missing a state at design time = production bug later. The "we'll add empty state later" trap is real.
|
|
67
|
+
|
|
68
|
+
### 4. Who uses this surface, where, and in what mood?
|
|
69
|
+
|
|
70
|
+
One sentence: **"`<Who>` uses this on `<where>` in `<what light>` while `<what mood>`."**
|
|
71
|
+
|
|
72
|
+
Good examples:
|
|
73
|
+
- "An on-call engineer uses this on a dark-room laptop at 3am while troubleshooting a fire."
|
|
74
|
+
- "A field nurse uses this on a phone in bright outdoor light while juggling clipboards."
|
|
75
|
+
- "A receptionist uses this on a 24″ monitor at a busy front desk while talking to a visitor."
|
|
76
|
+
|
|
77
|
+
Decisions cascade from the answer:
|
|
78
|
+
- 3am dark room → dark mode, high contrast, no flashing animations.
|
|
79
|
+
- Bright outdoor → minimum 7:1 contrast, larger touch targets, no thin fonts.
|
|
80
|
+
- Busy front desk → glanceable info, no nested menus, large numbers.
|
|
81
|
+
|
|
82
|
+
Without this sentence, defaults take over: light mode, default contrasts, animations, regular touch targets. Production users hate it; you can't articulate why.
|
|
83
|
+
|
|
84
|
+
## Required reading by context
|
|
85
|
+
|
|
86
|
+
| Doing what | Read |
|
|
87
|
+
|------------|------|
|
|
88
|
+
| Any UI work (the full version of the grounding) | `references/hard-gate.md` |
|
|
89
|
+
| Reviewing or proposing a design | `references/visual-slop.md` (14 patterns + specific anti-default values) |
|
|
90
|
+
| Designing state coverage | `references/state-matrix.md` |
|
|
91
|
+
| Interactive widget (button, form, modal, anything clickable) | `references/accessibility-floor.md` |
|
|
92
|
+
| No design authority exists in the project | `references/curated-defaults.md` (palettes / fonts / scales) |
|
|
93
|
+
|
|
94
|
+
## The 14 visual-slop patterns (full catalog in `references/visual-slop.md`)
|
|
95
|
+
|
|
96
|
+
Watch for these in proposed designs and PR diffs:
|
|
97
|
+
|
|
98
|
+
1. **Uniform-section flatness** — every section looks like every other section; no anchor for the eye.
|
|
99
|
+
2. **Soft hierarchy** — headings barely larger than body; primary CTA same color as secondary.
|
|
100
|
+
3. **Decorative hover** — hover states that don't change anything functional or clickable.
|
|
101
|
+
4. **Emoji as ornament** — emojis in headers, CTAs, section labels where they add no information.
|
|
102
|
+
5. **Gradient cover** — gradients used to mask weak composition rather than serve a poetic hero.
|
|
103
|
+
6. **Glass-on-everything** — frosted-glass effect on every panel, including ones with nothing behind.
|
|
104
|
+
7. **Center-aligned by default** — body paragraphs and forms reading center where left would read better.
|
|
105
|
+
8. **Grayscale wash** — neutral grays everywhere, no accent personality, no character.
|
|
106
|
+
9. **Verb-less CTAs** — "Get Started", "Learn More", "Click Here", "Submit", "OK".
|
|
107
|
+
10. **Stock-illustration hero** — figure-with-laptop, diverse-team-around-table, abstract floating shapes.
|
|
108
|
+
11. **Shadow soup** — shadows on cards on shadows on borders on gradients on one element.
|
|
109
|
+
12. **Generic spinner** — wall-clock spinner as the only loading state for every operation.
|
|
110
|
+
13. **Silent empty state** — "No items found." centered. Nothing else. No guidance.
|
|
111
|
+
14. **Toast everywhere** — every UI event becomes a toast; five stack up and none get read.
|
|
112
|
+
|
|
113
|
+
Plus 17 anti-default values (specific colors, radii, font choices, spacing presets) that signal "no thought went into this" — full list in `references/visual-slop.md`.
|
|
114
|
+
|
|
115
|
+
## Accessibility floor — non-negotiable
|
|
116
|
+
|
|
117
|
+
Before any interactive widget ships:
|
|
118
|
+
|
|
119
|
+
- [ ] Color contrast meets WCAG 2.2 AA (4.5:1 body, 3:1 large text and UI components).
|
|
120
|
+
- [ ] Focus-visible state distinct from hover.
|
|
121
|
+
- [ ] Keyboard navigation works end-to-end.
|
|
122
|
+
- [ ] ARIA labels for icon-only buttons.
|
|
123
|
+
- [ ] Form errors announced to screen readers.
|
|
124
|
+
- [ ] No keyboard traps.
|
|
125
|
+
- [ ] Touch targets ≥24×24 CSS pixels (≥44×44 recommended on mobile).
|
|
126
|
+
- [ ] Heading hierarchy is semantic (no skipped levels).
|
|
127
|
+
- [ ] `prefers-reduced-motion` honored.
|
|
128
|
+
|
|
129
|
+
Full verification recipes in `references/accessibility-floor.md`. `/dw-code-review` rejects the verdict if any interactive widget ships without these.
|
|
130
|
+
|
|
131
|
+
## When the grounding bends
|
|
132
|
+
|
|
133
|
+
- **Bug fix in existing UI** — grounding applies only to the area touched, not the whole surface.
|
|
134
|
+
- **Pure copy change** — only the "what does this help the user do" question still applies as a sanity check.
|
|
135
|
+
- **Throwaway spike** — grounding skippable if the spike is explicitly marked non-production.
|
|
136
|
+
|
|
137
|
+
In all bend cases, document the bend in the PR (one line). "I skipped the state matrix because this is a one-line copy fix" is fine. "I skipped because I was in a hurry" is not.
|
|
138
|
+
|
|
139
|
+
## Integration with dev-workflow commands
|
|
140
|
+
|
|
141
|
+
- `/dw-redesign-ui` runs the grounding end-to-end. Steps 4 (propose) and 7 (validate) consult this skill explicitly.
|
|
142
|
+
- `/dw-create-techspec` UI sections must answer the 4 grounding questions and reference the state matrix.
|
|
143
|
+
- `/dw-code-review` checks UI diffs against the 14 visual-slop patterns and the accessibility floor.
|
|
144
|
+
- `/dw-functional-doc` records the surface-job and scene sentences in the overview for each screen.
|
|
145
|
+
|
|
146
|
+
## Why this approach
|
|
147
|
+
|
|
148
|
+
The shorter route — "agent loads a 161-palette catalog and picks one" — produces dashboards that look like every other dashboard because the agent has no constraint that pulls it away from training-data centers of mass.
|
|
149
|
+
|
|
150
|
+
The grounding pulls the design toward the specific surface, the specific user, the specific moment. Even with the same palette catalog, a "3am on-call dark room troubleshooting" design lands different choices than a "morning manager approving expenses" design. That difference is where surface quality lives.
|
|
@@ -0,0 +1,225 @@
|
|
|
1
|
+
# Accessibility floor — WCAG 2.2 AA is the minimum, not the goal
|
|
2
|
+
|
|
3
|
+
This reference is read in full before any interactive widget ships. Skipping any item below is a hard-block in `/dw-code-review`.
|
|
4
|
+
|
|
5
|
+
## The non-negotiables
|
|
6
|
+
|
|
7
|
+
### 1. Color contrast
|
|
8
|
+
|
|
9
|
+
| Element | Minimum ratio (WCAG 2.2 AA) |
|
|
10
|
+
|---------|----------------------------|
|
|
11
|
+
| Body text (under 18pt or under 14pt bold) | 4.5:1 |
|
|
12
|
+
| Large text (18pt+ or 14pt+ bold) | 3:1 |
|
|
13
|
+
| UI components (button borders, icons, focus rings) | 3:1 |
|
|
14
|
+
| Decorative graphics | No requirement |
|
|
15
|
+
|
|
16
|
+
**Verification:**
|
|
17
|
+
- Use `axe DevTools` browser extension OR `playwright/test` with `@axe-core/playwright`.
|
|
18
|
+
- Manual quick check: `chrome://flags` → Enable "Simulate Vision Deficiencies" + try "Achromatopsia" (no colors). If buttons still legible, contrast is doing its job.
|
|
19
|
+
|
|
20
|
+
**Common violation:** Light gray text on white. `#9CA3AF` on white = 2.85:1. FAIL.
|
|
21
|
+
|
|
22
|
+
### 2. Focus-visible state
|
|
23
|
+
|
|
24
|
+
Every interactive element must have a distinct focus-visible state when keyboard-focused.
|
|
25
|
+
|
|
26
|
+
**Rules:**
|
|
27
|
+
- `:focus-visible` MUST be distinct from `:hover` — keyboard users need an affordance.
|
|
28
|
+
- Default browser outline is acceptable; replacing with `outline: none` requires alternative (border, ring, shadow).
|
|
29
|
+
- Focus must be visible against any background the element can appear on (dark + light themes).
|
|
30
|
+
|
|
31
|
+
**Tailwind pattern:**
|
|
32
|
+
```css
|
|
33
|
+
focus-visible:outline-none
|
|
34
|
+
focus-visible:ring-2
|
|
35
|
+
focus-visible:ring-offset-2
|
|
36
|
+
focus-visible:ring-blue-500
|
|
37
|
+
```
|
|
38
|
+
|
|
39
|
+
**Verification:**
|
|
40
|
+
- Tab through the entire surface with keyboard. Every interactive element must light up visibly.
|
|
41
|
+
- If you can't tell what's focused, the contrast on the focus ring is too low.
|
|
42
|
+
|
|
43
|
+
### 3. Keyboard navigation
|
|
44
|
+
|
|
45
|
+
| Capability | Requirement |
|
|
46
|
+
|------------|-------------|
|
|
47
|
+
| Tab order | Logical (left-to-right, top-to-bottom in LTR) |
|
|
48
|
+
| Modals | Tab cycles WITHIN modal; Escape closes; focus returns to trigger |
|
|
49
|
+
| Dropdowns / select | Arrow keys navigate options; Enter selects; Escape closes |
|
|
50
|
+
| Forms | Enter submits; Tab moves to next field; Shift+Tab moves back |
|
|
51
|
+
| Custom widgets | Match the ARIA Authoring Practices Guide patterns |
|
|
52
|
+
|
|
53
|
+
**Verification:**
|
|
54
|
+
- Unplug mouse. Complete the primary user flow with keyboard only.
|
|
55
|
+
- If you got stuck or couldn't reach an element, keyboard nav is broken.
|
|
56
|
+
|
|
57
|
+
### 4. ARIA labels for icon-only interactives
|
|
58
|
+
|
|
59
|
+
Icon-only buttons (e.g., a trash can icon as a delete button) need `aria-label` describing the action.
|
|
60
|
+
|
|
61
|
+
```html
|
|
62
|
+
<!-- BAD -->
|
|
63
|
+
<button><TrashIcon /></button>
|
|
64
|
+
|
|
65
|
+
<!-- GOOD -->
|
|
66
|
+
<button aria-label="Delete invoice"><TrashIcon /></button>
|
|
67
|
+
```
|
|
68
|
+
|
|
69
|
+
Same applies to:
|
|
70
|
+
- Icon-only links
|
|
71
|
+
- Icon-only toggles
|
|
72
|
+
- Tooltips (the trigger needs aria-describedby pointing to the tooltip)
|
|
73
|
+
- Decorative images (`aria-hidden="true"` if purely decorative; `alt=""` not enough)
|
|
74
|
+
|
|
75
|
+
### 5. Form errors announced to screen readers
|
|
76
|
+
|
|
77
|
+
When a form field errors:
|
|
78
|
+
|
|
79
|
+
```html
|
|
80
|
+
<label for="email">Email</label>
|
|
81
|
+
<input
|
|
82
|
+
id="email"
|
|
83
|
+
type="email"
|
|
84
|
+
aria-describedby="email-error"
|
|
85
|
+
aria-invalid="true"
|
|
86
|
+
/>
|
|
87
|
+
<span id="email-error" role="alert">
|
|
88
|
+
Email is required
|
|
89
|
+
</span>
|
|
90
|
+
```
|
|
91
|
+
|
|
92
|
+
Key points:
|
|
93
|
+
- `aria-invalid="true"` on the input.
|
|
94
|
+
- `aria-describedby` links the input to the error message.
|
|
95
|
+
- `role="alert"` on the error message announces it.
|
|
96
|
+
|
|
97
|
+
**Anti-pattern:** Red border + tooltip on hover. Screen reader users get nothing.
|
|
98
|
+
|
|
99
|
+
### 6. No keyboard traps
|
|
100
|
+
|
|
101
|
+
A "keyboard trap" is when focus enters a widget and can't leave with the keyboard. Most common cause: custom-built modals or carousels.
|
|
102
|
+
|
|
103
|
+
**Rule:** Every modal, drawer, or overlay must let Escape close it and return focus to the trigger element.
|
|
104
|
+
|
|
105
|
+
**Verification:**
|
|
106
|
+
- Open the widget with keyboard. Press Escape. Does focus return to where it was?
|
|
107
|
+
- Tab through the widget. After last element, does Tab cycle to first (within widget) instead of leaving the page?
|
|
108
|
+
|
|
109
|
+
### 7. Touch target size (mobile)
|
|
110
|
+
|
|
111
|
+
Minimum 24x24 CSS pixels (WCAG 2.2 AA minimum). Recommended 44x44 (Apple HIG / Android touch target).
|
|
112
|
+
|
|
113
|
+
**Pattern:** Even when the visual icon is 16x16, give the button 44x44 hit area:
|
|
114
|
+
|
|
115
|
+
```css
|
|
116
|
+
button {
|
|
117
|
+
width: 24px; height: 24px; /* WCAG 2.2 AA minimum */
|
|
118
|
+
/* Or */
|
|
119
|
+
width: 44px; height: 44px; /* Recommended */
|
|
120
|
+
padding: 14px; /* Visual icon inside */
|
|
121
|
+
}
|
|
122
|
+
```
|
|
123
|
+
|
|
124
|
+
### 8. Heading hierarchy
|
|
125
|
+
|
|
126
|
+
H1 → H2 → H3 etc. Don't skip levels. Don't use heading tags for visual sizing — use semantic level + CSS for size.
|
|
127
|
+
|
|
128
|
+
```html
|
|
129
|
+
<!-- BAD -->
|
|
130
|
+
<h2>Section A</h2>
|
|
131
|
+
<h4>Subsection</h4> <!-- skipped h3 -->
|
|
132
|
+
|
|
133
|
+
<!-- GOOD -->
|
|
134
|
+
<h2>Section A</h2>
|
|
135
|
+
<h3>Subsection</h3>
|
|
136
|
+
```
|
|
137
|
+
|
|
138
|
+
Screen readers navigate by heading; broken hierarchy disorients.
|
|
139
|
+
|
|
140
|
+
### 9. Language attribute
|
|
141
|
+
|
|
142
|
+
Root `<html lang="en">` (or correct ISO code) for primary language. Sections in other language need `lang` attribute too.
|
|
143
|
+
|
|
144
|
+
```html
|
|
145
|
+
<html lang="en">
|
|
146
|
+
<p>Welcome.</p>
|
|
147
|
+
<p lang="pt-br">Bem-vindo.</p>
|
|
148
|
+
</html>
|
|
149
|
+
```
|
|
150
|
+
|
|
151
|
+
Screen readers switch pronunciation based on this.
|
|
152
|
+
|
|
153
|
+
### 10. Reduced motion respect
|
|
154
|
+
|
|
155
|
+
Honor `prefers-reduced-motion`:
|
|
156
|
+
|
|
157
|
+
```css
|
|
158
|
+
@media (prefers-reduced-motion: reduce) {
|
|
159
|
+
*, *::before, *::after {
|
|
160
|
+
animation-duration: 0.01ms !important;
|
|
161
|
+
transition-duration: 0.01ms !important;
|
|
162
|
+
}
|
|
163
|
+
}
|
|
164
|
+
```
|
|
165
|
+
|
|
166
|
+
Or in Tailwind:
|
|
167
|
+
```html
|
|
168
|
+
<div className="transition-all motion-reduce:transition-none">
|
|
169
|
+
```
|
|
170
|
+
|
|
171
|
+
Vestibular disorders trigger on parallax, large slide-ins, infinite scroll animations.
|
|
172
|
+
|
|
173
|
+
## Verification recipes
|
|
174
|
+
|
|
175
|
+
### Automated (CI)
|
|
176
|
+
|
|
177
|
+
```ts
|
|
178
|
+
// playwright + axe-core
|
|
179
|
+
import { test, expect } from '@playwright/test';
|
|
180
|
+
import AxeBuilder from '@axe-core/playwright';
|
|
181
|
+
|
|
182
|
+
test('homepage a11y', async ({ page }) => {
|
|
183
|
+
await page.goto('/');
|
|
184
|
+
const results = await new AxeBuilder({ page })
|
|
185
|
+
.withTags(['wcag2a', 'wcag2aa', 'wcag22a', 'wcag22aa'])
|
|
186
|
+
.analyze();
|
|
187
|
+
expect(results.violations).toEqual([]);
|
|
188
|
+
});
|
|
189
|
+
```
|
|
190
|
+
|
|
191
|
+
Run on every PR. Block merge on violations.
|
|
192
|
+
|
|
193
|
+
### Manual (PR review)
|
|
194
|
+
|
|
195
|
+
1. Open the changed page.
|
|
196
|
+
2. Tab through with keyboard only. Verify focus visible at every stop.
|
|
197
|
+
3. Run axe DevTools, fix violations.
|
|
198
|
+
4. Toggle prefers-reduced-motion in DevTools rendering panel. Verify animations stop.
|
|
199
|
+
5. Test with screen reader (VoiceOver on Mac, NVDA on Windows) on at least one critical flow.
|
|
200
|
+
|
|
201
|
+
### Spot checks
|
|
202
|
+
|
|
203
|
+
Color contrast: chrome devtools → element inspector → "Contrast" indicator next to text color. Click for actual ratio.
|
|
204
|
+
|
|
205
|
+
Touch target: Inspect element → check computed width/height. If < 24, flag.
|
|
206
|
+
|
|
207
|
+
## When the floor bends
|
|
208
|
+
|
|
209
|
+
- **Iframes you don't control** — your wrapper still has to be accessible, the iframe is best-effort.
|
|
210
|
+
- **Third-party widgets** (analytics dashboards, payment SDKs) — wrap with ARIA landmarks; report violations upstream.
|
|
211
|
+
- **Legacy code being patched** — bring touched components up to floor; leave untouched ones for separate accessibility-debt work.
|
|
212
|
+
|
|
213
|
+
In all bend cases, file a tracking issue. Don't pretend the floor was met.
|
|
214
|
+
|
|
215
|
+
## Common AI-generated UI violations
|
|
216
|
+
|
|
217
|
+
LLM-produced UI commonly fails on:
|
|
218
|
+
- `<div onClick>` instead of `<button>` (not keyboard-accessible).
|
|
219
|
+
- Icon-only buttons with no aria-label.
|
|
220
|
+
- `text-gray-400` on white (contrast 2.8:1 — fail).
|
|
221
|
+
- `outline: none` with no replacement focus state.
|
|
222
|
+
- Modals that trap focus only on success path, not on error.
|
|
223
|
+
- Auto-playing carousels with no pause control.
|
|
224
|
+
|
|
225
|
+
`/dw-code-review` runs axe-style checks on the diff for these.
|
|
@@ -0,0 +1,195 @@
|
|
|
1
|
+
# Curated defaults — 10 palettes + 10 font pairings + spacing scale
|
|
2
|
+
|
|
3
|
+
Use this reference when the project has **no design authority** (no `.dw/rules/` design section, no `DESIGN.md`, no Tailwind theme tokens, no component library config).
|
|
4
|
+
|
|
5
|
+
The values below cover ~90% of cases that need a starting point. Not opinionated branding — neutral, accessible, professional defaults.
|
|
6
|
+
|
|
7
|
+
## How to use
|
|
8
|
+
|
|
9
|
+
1. Pick ONE palette + ONE font pairing + the spacing scale.
|
|
10
|
+
2. Commit the choice to the project (`.dw/rules/<frontend>.md` design section OR a new `DESIGN.md`).
|
|
11
|
+
3. From there, the project HAS a design authority; downstream `dw-ui-discipline` invocations defer to that authority.
|
|
12
|
+
|
|
13
|
+
This is bootstrap, not destination. The goal is to escape "no authority" mode within the first feature.
|
|
14
|
+
|
|
15
|
+
## The 10 palettes
|
|
16
|
+
|
|
17
|
+
Each palette below: neutral scale (gray, slate, etc.) + 1 accent + semantic colors. All WCAG 2.2 AA compliant for body text.
|
|
18
|
+
|
|
19
|
+
### 1. Cool Stone
|
|
20
|
+
- Neutrals: Tailwind `slate` (50-950)
|
|
21
|
+
- Accent: `#3B82F6` (blue-500) — wait, no, see Anti-Slop. Use `#0066CC` instead.
|
|
22
|
+
- Semantic: success `#16A34A`, warning `#D97706`, danger `#DC2626`
|
|
23
|
+
- **Tone:** Calm, corporate, trustworthy. Default for SaaS dashboards.
|
|
24
|
+
|
|
25
|
+
### 2. Warm Sand
|
|
26
|
+
- Neutrals: Tailwind `stone` (50-950)
|
|
27
|
+
- Accent: `#CA8A04` (warm amber)
|
|
28
|
+
- Semantic: success `#16A34A`, warning `#EA580C`, danger `#DC2626`
|
|
29
|
+
- **Tone:** Approachable, hospitality-adjacent, organic.
|
|
30
|
+
|
|
31
|
+
### 3. Forest Pine
|
|
32
|
+
- Neutrals: Tailwind `gray` (50-950)
|
|
33
|
+
- Accent: `#15803D` (deep green)
|
|
34
|
+
- Semantic: success `#16A34A`, warning `#D97706`, danger `#B91C1C`
|
|
35
|
+
- **Tone:** Steady, financial, sustainable.
|
|
36
|
+
|
|
37
|
+
### 4. Plum Velvet
|
|
38
|
+
- Neutrals: Tailwind `zinc` (50-950)
|
|
39
|
+
- Accent: `#7C3AED` (violet-600)
|
|
40
|
+
- Semantic: success `#22C55E`, warning `#EAB308`, danger `#E11D48`
|
|
41
|
+
- **Tone:** Creative, premium, design-tool.
|
|
42
|
+
|
|
43
|
+
### 5. Coral Reef
|
|
44
|
+
- Neutrals: Tailwind `neutral` (50-950)
|
|
45
|
+
- Accent: `#E11D48` (rose-600)
|
|
46
|
+
- Semantic: success `#16A34A`, warning `#F59E0B`, danger `#B91C1C`
|
|
47
|
+
- **Tone:** Energetic, consumer, retail.
|
|
48
|
+
|
|
49
|
+
### 6. Steel Blue
|
|
50
|
+
- Neutrals: Tailwind `slate` (50-950)
|
|
51
|
+
- Accent: `#0F766E` (teal-700)
|
|
52
|
+
- Semantic: success `#16A34A`, warning `#D97706`, danger `#DC2626`
|
|
53
|
+
- **Tone:** Technical, infrastructure, devops.
|
|
54
|
+
|
|
55
|
+
### 7. Burnt Sienna
|
|
56
|
+
- Neutrals: Tailwind `stone` (50-950)
|
|
57
|
+
- Accent: `#C2410C` (orange-700)
|
|
58
|
+
- Semantic: success `#15803D`, warning `#A16207`, danger `#B91C1C`
|
|
59
|
+
- **Tone:** Bold, news, sports.
|
|
60
|
+
|
|
61
|
+
### 8. Ink and Paper
|
|
62
|
+
- Neutrals: Pure `#000` and `#FFF` with `#E5E5E5` divider
|
|
63
|
+
- Accent: `#000` (no accent — minimal)
|
|
64
|
+
- Semantic: success `#16A34A`, warning `#D97706`, danger `#DC2626`
|
|
65
|
+
- **Tone:** Editorial, brutalist, magazine. Pair with serif body.
|
|
66
|
+
|
|
67
|
+
### 9. Midnight Indigo
|
|
68
|
+
- Neutrals: Tailwind `slate` dark-mode-first (900-50)
|
|
69
|
+
- Accent: `#6366F1` (indigo-500)
|
|
70
|
+
- Semantic: success `#22C55E`, warning `#FACC15`, danger `#EF4444`
|
|
71
|
+
- **Tone:** Tech-forward, dark-mode-default, on-call tooling.
|
|
72
|
+
|
|
73
|
+
### 10. Sea Salt
|
|
74
|
+
- Neutrals: Tailwind `gray` cool (50-950)
|
|
75
|
+
- Accent: `#0891B2` (cyan-600)
|
|
76
|
+
- Semantic: success `#10B981`, warning `#F59E0B`, danger `#F43F5E`
|
|
77
|
+
- **Tone:** Fresh, healthcare, education.
|
|
78
|
+
|
|
79
|
+
## The 10 font pairings
|
|
80
|
+
|
|
81
|
+
Each pairing: heading font / body font. All available on Google Fonts. Variable fonts where possible.
|
|
82
|
+
|
|
83
|
+
| # | Headings | Body | Tone |
|
|
84
|
+
|---|----------|------|------|
|
|
85
|
+
| 1 | Inter | Inter | Modern SaaS default. Workhorse pairing. |
|
|
86
|
+
| 2 | Geist Sans | Geist Sans | Vercel-aesthetic; clean, geometric. |
|
|
87
|
+
| 3 | Söhne (or Manrope) | Söhne (or Manrope) | Editorial-modern; replaces Inter when Inter feels overused. |
|
|
88
|
+
| 4 | DM Serif Display | Inter | Editorial-meets-product. Strong headlines, neutral body. |
|
|
89
|
+
| 5 | Fraunces | Inter | Variable serif headlines, sans body. Premium feel. |
|
|
90
|
+
| 6 | Source Serif 4 | Source Sans 3 | Adobe pairing; balanced editorial. |
|
|
91
|
+
| 7 | Space Grotesk | Inter | Slightly quirky headlines, neutral body. Tech with personality. |
|
|
92
|
+
| 8 | IBM Plex Serif | IBM Plex Sans | Industrial, opinionated. Good for enterprise tooling. |
|
|
93
|
+
| 9 | Playfair Display | Manrope | High contrast pairing; hospitality, lifestyle. |
|
|
94
|
+
| 10 | JetBrains Mono | Inter | Code-first products; mono for headlines and accents. |
|
|
95
|
+
|
|
96
|
+
**Anti-default reminder:** Inter / Inter is fine. Inter / Inter as the ONLY pairing you ever pick is a tell.
|
|
97
|
+
|
|
98
|
+
## Spacing scale
|
|
99
|
+
|
|
100
|
+
Use a 4px-base scale with intentional jumps:
|
|
101
|
+
|
|
102
|
+
```
|
|
103
|
+
0: 0px
|
|
104
|
+
1: 4px (tight controls, icon padding)
|
|
105
|
+
2: 8px (compact spacing)
|
|
106
|
+
3: 12px (default gap in form fields)
|
|
107
|
+
4: 16px (default gap between blocks)
|
|
108
|
+
6: 24px (section padding)
|
|
109
|
+
8: 32px (large section spacing)
|
|
110
|
+
12: 48px (page header / hero padding)
|
|
111
|
+
16: 64px (between major sections)
|
|
112
|
+
24: 96px (hero / landing block separators)
|
|
113
|
+
32: 128px (rare; signature spacing)
|
|
114
|
+
```
|
|
115
|
+
|
|
116
|
+
**Skip these by default:** 5, 7, 9, 10, 11, 13, 14, 15. Picking exactly 4-6-8-12-16 reads more intentional than 1-2-3-4-5-6-...
|
|
117
|
+
|
|
118
|
+
## Border radius scale
|
|
119
|
+
|
|
120
|
+
Pick a "personality" once and use it consistently:
|
|
121
|
+
|
|
122
|
+
| Radius | Tone |
|
|
123
|
+
|--------|------|
|
|
124
|
+
| 0 (square) | Brutalist, editorial |
|
|
125
|
+
| 2px | Subtle modernist |
|
|
126
|
+
| 4px (Tailwind `rounded`) | Standard |
|
|
127
|
+
| 6px | Slightly friendly |
|
|
128
|
+
| 8px (Tailwind `rounded-lg`) | Default SaaS; **anti-default if used universally** |
|
|
129
|
+
| 12px | Softer, consumer |
|
|
130
|
+
| 16px+ | Rounded everything; friendly/youth-oriented |
|
|
131
|
+
| Full / 9999px | Pills, buttons, avatars only |
|
|
132
|
+
|
|
133
|
+
Don't mix more than 2 radii in one surface (e.g., 4px for inputs, 8px for cards). Three+ radii = visual noise.
|
|
134
|
+
|
|
135
|
+
## Type scale
|
|
136
|
+
|
|
137
|
+
For body=16px baseline:
|
|
138
|
+
|
|
139
|
+
```
|
|
140
|
+
xs: 12px (captions, helper text — minimum 11px)
|
|
141
|
+
sm: 14px (secondary, labels)
|
|
142
|
+
base: 16px (body)
|
|
143
|
+
lg: 18px (lead paragraphs)
|
|
144
|
+
xl: 20px (small headings)
|
|
145
|
+
2xl: 24px (subheadings)
|
|
146
|
+
3xl: 30px (section headings)
|
|
147
|
+
4xl: 36px (page titles)
|
|
148
|
+
5xl: 48px (hero, marketing)
|
|
149
|
+
6xl+: 60-96px (display, marketing only)
|
|
150
|
+
```
|
|
151
|
+
|
|
152
|
+
Line-height pairs:
|
|
153
|
+
- Body text: 1.5 to 1.6
|
|
154
|
+
- Headings: 1.1 to 1.25
|
|
155
|
+
- Buttons: 1 (tight)
|
|
156
|
+
|
|
157
|
+
## How to commit a choice
|
|
158
|
+
|
|
159
|
+
After picking a palette + pairing + spacing, write `.dw/rules/<frontend>.md` (or `DESIGN.md`) with:
|
|
160
|
+
|
|
161
|
+
```markdown
|
|
162
|
+
## Design System (bootstrap)
|
|
163
|
+
|
|
164
|
+
**Source:** Curated default — `dw-ui-discipline/references/curated-defaults.md`, picked Cool Stone + Inter/Inter + 4px-base scale on 2026-05-12.
|
|
165
|
+
|
|
166
|
+
### Colors
|
|
167
|
+
- Neutrals: Tailwind slate (50-950)
|
|
168
|
+
- Accent: #0066CC (links, primary buttons, focus rings)
|
|
169
|
+
- Success: #16A34A · Warning: #D97706 · Danger: #DC2626
|
|
170
|
+
|
|
171
|
+
### Typography
|
|
172
|
+
- Headings: Inter, weight 600-700
|
|
173
|
+
- Body: Inter, weight 400-500
|
|
174
|
+
- Mono: JetBrains Mono (code blocks only)
|
|
175
|
+
|
|
176
|
+
### Spacing
|
|
177
|
+
4px base scale: 4 / 8 / 12 / 16 / 24 / 32 / 48 / 64 / 96.
|
|
178
|
+
|
|
179
|
+
### Border radius
|
|
180
|
+
4px on inputs, 8px on cards, full on pills/avatars.
|
|
181
|
+
|
|
182
|
+
### Updates
|
|
183
|
+
This file is the canonical design source. To change a value, propose a PR
|
|
184
|
+
that updates this file FIRST, then propagates through code.
|
|
185
|
+
```
|
|
186
|
+
|
|
187
|
+
Once written, `dw-ui-discipline` reads this file instead of `curated-defaults.md`. The bootstrap step is done.
|
|
188
|
+
|
|
189
|
+
## What this catalog is NOT
|
|
190
|
+
|
|
191
|
+
- Not 161 palettes. Not 57 fonts. By design.
|
|
192
|
+
- Not a substitute for brand work — for a serious product, hire a designer.
|
|
193
|
+
- Not opinionated about industry-specific aesthetics (med-tech, gaming, kids' content). Those need real design pass.
|
|
194
|
+
|
|
195
|
+
The point is: have ONE intentional starting point so the agent isn't reaching for `#3B82F6` and `rounded-lg`. Project-specific design follows.
|