feat(design): every button on its family, the chip primitive, the lint rule (E28 S3b2)
The second half of the button sweep: the remaining hand-rolled buttons in
feature components, the design lab and the components/ui composites now
stand on Button, IconButton, Pressable, Chip or DragHandle.
- Chip + DismissibleChip (filter / token / tag / suggest / ghost, 24px
floor, 44 on touch) replace five chip geometries; FilterChipGroup
renders Chips; overflow lanes measure a mirror painted by chipClass.
- The Plex control row is IconButton's player rung (36, 20px glyph,
round, overlay; 44 on touch); the YT modal bar is on the sm rung with
pressed cycle toggles and names that survive a folded label.
- New variants: IconButton ghost-accent, danger-soft; Button warn on a
new state-warn utility. The .btn-{tone} recipes and btnCls are gone.
- Fixed on the way: membership rows (collection editor, Plex playlist
add) announce checked/mixed; a one-letter tag chip was 21px wide;
descriptionLinks moved out of lib/ (it renders components).
- local/button-primitive: a raw <button>/<FocusSafeButton> outside the
control-primitive files is a lint error (contract-tested, seen red).
This commit is contained in:
+15
-6
@@ -130,16 +130,24 @@ Also in force:
|
||||
- **One primitive per button family** (E28 S3b): a labelled action is `Button` (a rung from the ladder,
|
||||
plus `lg` 40 for a page's single hero call to action, and nothing else); a glyph is `IconButton` (a
|
||||
required `label`); a card, row, tile or menu row whose content is the control is `Pressable`; a filter or
|
||||
tag chip is the chip family; a sortable row's grip is `DragHandle`. On the always-dark player chrome both
|
||||
`Button` and `IconButton` use the `overlay` variant (white, a white layer), whatever the theme. A pressed
|
||||
toggle is `pressed`: the solid accent on a `Button`, the accent glyph on an `IconButton`. A hand-rolled
|
||||
`<button className="px-3 …">` is a violation. A text-less button must have an accessible name, and the
|
||||
type enforces it. [WCAG 4.1.2]
|
||||
tag chip is `Chip`; a sortable row's grip is `DragHandle`. On the always-dark player chrome both
|
||||
`Button` and `IconButton` use the `overlay` variant (white, a white layer), whatever the theme; the Plex
|
||||
control row is IconButton's `player` rung (36, a 20px glyph, round, 44 on touch). A pressed toggle is
|
||||
`pressed`: the solid accent on a `Button`, the accent glyph on an `IconButton`. A raw `<button>` outside
|
||||
`components/ui/` is a lint error. A text-less button must have an accessible name, and the type enforces
|
||||
it. [WCAG 4.1.2]
|
||||
- **The chip family** (`Chip`, E28 S3b): rounded-full, never under 24 (A3 grows it to 44 on touch).
|
||||
`filter` is a selectable option, solid accent when `pressed` (also the "+N" and "More…" triggers, lit
|
||||
while their popover is open); `token` is an applied narrowing, the accent tint, the whole chip removing
|
||||
it; `tag` is a user's tag, the solid accent; `suggest` is a suggestion not yet taken (dashed accent);
|
||||
`ghost` the quiet "add a tag" (dashed neutral). A chip whose label is not the control but carries its
|
||||
own × is `DismissibleChip`: two sibling controls at most, never a button in a button. An overflowing chip
|
||||
lane measures a hidden mirror painted with `chipClass`, so the mirror cannot drift from the chips.
|
||||
- **Unavailable with a reason** stays focusable: `aria-disabled` plus the reason in the label or tooltip,
|
||||
never native `disabled`, which drops it from the tab order with its explanation. [WCAG 2.1.1]
|
||||
- A choice between a few values is `SegmentedToggle`; a long list or a user's own list is `FilterSelect`.
|
||||
Never a native `<select>` (lint-enforced).
|
||||
- A filter chip goes through `FilterChipGroup`.
|
||||
- A single-select row of filter chips goes through `FilterChipGroup` (its options are `Chip`s).
|
||||
- A button that starts slow work shows `loading` (a spinner, `aria-busy`) and can't be pressed twice.
|
||||
[Nielsen #1]
|
||||
|
||||
@@ -313,4 +321,5 @@ Wherever there is text, the user can select it and copy it, and no click action
|
||||
| 2026-09-24 | C5 Plex player controls | The owner's lean set: no Stop / Restart / ±10 s buttons, Back by position, Next only with a next item, Resume + From the start on the card, touch double-tap ±10 s | Every control in one row (it ran off-screen below 1024); Back by a press counter; ±10 s keyboard-only | The row fits a portrait tablet; the decision to restart is made on the card; a tablet keeps the 10 s skip |
|
||||
| 2026-09-24 | Glass tuner | Retired; the schemes are the only colour choice | Keep it with ranges clamped to the rules | Free tuning is the drift the constitution exists to stop (owner) |
|
||||
| 2026-09-24 | Matrix toned down | Moss #86a05a at Midnight's lightness, near-neutral greys; every white-on-accent part → `--accent-fg` | The B2 lime #a3e635 | The owner found the lime neon and tiring; it was the loudest accent (L 0.85, C 0.21), and fixed white parts sat on it at 1.5:1 |
|
||||
| 2026-09-24 | Chip family | One `Chip` (filter / token / tag / suggest / ghost) + `DismissibleChip`; nothing under 24; the lint rule "no raw `<button>` outside ui/" | Five chip geometries in five files | The applied-filter row, the tag cells, the year picker and the saved-view editor each drew their own chip; a one-letter tag was 21px wide |
|
||||
| 2026-09-24 | Button families | `Button` / `IconButton` / `Pressable` / chips / `DragHandle`; `lg` 40 for a hero CTA; pills and a 48 Play on media (from C5) | Every button hand-painted | 268 hand-rolled buttons in 79 files drifted into as many looks; the ladder only holds if every button stands on it |
|
||||
|
||||
Reference in New Issue
Block a user