[DOC] skills: update odoo-javascript skill documentation

This commit is contained in:
GitHub Copilot 2026-08-15 13:00:56 +02:00
parent 158933e96e
commit 162ba0b570
6 changed files with 875 additions and 1 deletions

View file

@ -0,0 +1,96 @@
# 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.