addons-cm/.claude/skills/odoo-web-design/references/finish-checklist.md

96 lines
4.8 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# The finish pass
What separates "it works" from "it looks designed". Go through this per screen, not per file.
## 1. Every interactive element has all its states
For each button, link, card, input, filter chip:
| State | Must be | Common miss |
| --- | --- | --- |
| default | on the token scale | — |
| `:hover` | inside `@media (hover: hover)` | sticks after tap on touch |
| `:focus-visible` | visible ring, 3:1 contrast | removed via `outline: none` |
| `:active` | perceptible press | missing entirely |
| `:disabled` | dimmed **and** `cursor: not-allowed`, still 4.5:1 if it carries text | unreadable grey |
| loading | spinner + `aria-busy`, size unchanged | layout jumps |
The element must not resize between states — animate `box-shadow`, `background`, `transform`, never
`padding`, `border-width` or `font-size`.
## 2. Vertical rhythm and spacing
- All spacing from `--ac-space-*`. A `margin: 13px` anywhere is a defect.
- Space belongs to **one** side consistently (block-end margins, or `gap` — pick one per container).
Prefer `gap` in flex/grid; it doesn't collapse and doesn't need `:last-child` cleanups.
- Related things sit closer than unrelated things. If the label is as far from its input as from the
previous field, the form reads as noise.
- Cards in a grid must be equal height (`align-items: stretch` + the price pinned with `margin-top: auto`).
## 3. Typography
- One scale (`--ac-text-*`), max 3 weights, max 2 sizes per card.
- Headings are structural (`h1``h2``h3`); size comes from a class, never from picking `h4` because
it looks right.
- `max-width: 65ch` on paragraphs of real prose.
- Numbers in tables: `font-variant-numeric: tabular-nums` and right-aligned so columns line up.
- Long product names truncate predictably: `text-overflow: ellipsis` with `title` attribute, or
`-webkit-line-clamp: 2` with a fixed `min-height` so cards don't stagger.
## 4. Colour
- Semantic, not decorative: success/danger/warning always the same hue for the same meaning.
- Status never colour-only — icon or text alongside (colour blindness, and grayscale printing).
- Max ~2 accent colours per screen. Everything else is surface, border, text.
- Check the rendered contrast, including: placeholder text, disabled buttons, badges on coloured
backgrounds, white text on `--warning` (this one almost always fails).
## 5. The states people forget
Every list, grid and total needs four designs, not one:
1. **Loading** — skeletons matched to the real layout (not a centred spinner that collapses the page).
2. **Empty** — heading, one sentence explaining why it's empty, and the button that fixes it.
"No products found" alone is a dead end; offer "Clear filters".
3. **Error** — what failed, in the user's language, and what to do now. Never a raw traceback or code.
4. **Partial / stale** — an order past its cutoff, an out-of-stock line, a price that changed. Say it
inline, next to the affected row, not only in a toast that disappears.
## 6. Feedback and motion
- Any action taken by the user gets a response within 100 ms — disable the button, show the spinner,
optimistic-update the quantity. Silence reads as "broken", and users double-submit.
- Toasts: `aria-live="polite"`, dismissible, never the only place an error is shown.
- Motion is 150250 ms and eases out. Anything above 400 ms feels slow; anything that moves the page
under the cursor is a bug.
- Everything animated respects `prefers-reduced-motion`.
## 7. Content and copy
- Sentence case for buttons and labels; imperative verbs ("Add to cart", not "Adding products").
- Prices always formatted server-side with the currency and locale (`i18nManager.formatCurrency`),
never string-concatenated in the template.
- Dates: locale-formatted, and relative only when the absolute date is also available (`title`).
- Nothing user-visible is a hardcoded English literal — templates get translatable text, JS gets
`window.i18nManager.get(key)`.
## 8. Cross-cutting checks before "done"
```
[ ] 320 px: no horizontal scroll on any page
[ ] 200 % zoom: nothing clipped or overlapping
[ ] Tab through the whole flow: visible focus, logical order, no trap
[ ] All actions reachable without a mouse, Esc closes overlays
[ ] No hex outside base/variables.css
[ ] No inline style="" in views/*.xml
[ ] No new !important (except the reduced-motion reset)
[ ] Every <img> has alt and width/height
[ ] Every icon-only control has aria-label
[ ] Empty / loading / error states exist for each list
[ ] es, eu and ca render without overflow (German-length strings break tight buttons)
[ ] pre-commit run --all-files is clean
[ ] Lighthouse a11y ≥ 95 on shop, cart, checkout
```
The last three matter as much as the rest: a layout tuned only against Spanish copy usually breaks in
Basque, and a11y regressions land silently.