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

4.8 KiB
Raw Blame History

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 (h1h2h3); 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.