Plan step 36 (containment group): <x-drawer>'s class lists move into resources/css/components/drawer.css, keyed on data-md-drawer (with data-md-open, data-md-standard) and data-md-drawer-scrim/-sheet (data-md-side)/-head/-head-row/-heading/-title/-subtitle/-close/-body/ -actions. The modal sheet slides in on the emphasized-decelerate easing and out on emphasized-accelerate (an asymmetric CSS transition expressed by giving the open-state selector its own transition-duration/-timing-function, which the "after-change style" rule picks up); the sheet stays x-show-driven, with @starting-style + transition-behavior: allow-discrete taking the place of x-transition's enter/leave classes, matching resources/css/components/search.css's already-rewritten scrim/view. A standard sheet drops the scrim and trap from 840px and only fades in place (an in-flow box does not travel); data-md-drawer-collapsed (from the view's `wide` Alpine state) takes it out of the layout while closed there. <x-drawer pane> is removed: step 35's <x-list-detail> is M3's form of that job (the plan's decision, docs/plans/material-3-alignment.md "Decisions"). Removed the prop, its CSS classes and its tests (OverlayTest's two pane-only tests deleted, the others' pane cases dropped); pointed each mention at <x-list-detail> in the material-3 guideline, the material-3-design and livewire-material-development skills, and added a line to UPGRADE.md's 2.0.0 notes. No other living file named `<x-drawer pane>` (grepped views, tests, README, boost, workbench excluding build output); docs/plans and docs/audits keep their history unchanged. Imported from the Containment block of components.css, importing button.css and divider.css for what the view renders. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01Qwx5USif3wFFmxtHg5U1g9
59 lines
7.8 KiB
PHP
59 lines
7.8 KiB
PHP
@verbatim
|
||
## Material 3
|
||
|
||
Every view in this application is Material 3 Expressive (m3.material.io), through `nonameweb/livewire-material`. These rules decide what to write; the `material-3-design` skill carries the tables, the numbers and Google's source pages behind each one — activate it before designing a screen.
|
||
|
||
### Colour
|
||
- A colour is always a role: `bg-primary`, `text-on-surface-variant`, `border-outline-variant`. Never a hex, an arbitrary value, a palette tone or an opacity; Tailwind's palette does not compile.
|
||
- Pair a role only with its `on-` partner: `bg-primary text-on-primary`, `bg-secondary-container text-on-secondary-container`. That pair is the one whose contrast is guaranteed at every contrast level; mixing pairs (`bg-primary-container text-on-surface`) is not.
|
||
- `primary` is the one key action on a screen (a filled button; the FAB in `primary-container`). `secondary-container` is the quiet fill (tonal buttons, selected navigation, selected chips). `tertiary` is a contrasting accent, used rarely. `error`, `success`, `warning`, `info` mean state and nothing else: the `-container` for a tinted panel, the role itself for its text and icon.
|
||
- Ink is `text-on-surface`; lower emphasis is `text-on-surface-variant` (`text-body`, `text-meta`); decoration is `text-outline` (`text-quiet`). Never dim ink with an opacity: 38% means disabled.
|
||
- `border-outline` is a boundary that must be read (a text field, the edge of a target). `border-outline-variant` (`border-divider`, `border-structure`, `border-chrome`) is a divider or a card edge. Never `outline` on a divider.
|
||
- Fixed and dim roles (`primary-fixed`, `surface-dim`, …) are for a colour that must not change with the theme; if unsure, don't. Inverse roles only on an inverse surface (the snackbar).
|
||
- A link is `text-primary` and underlined (`link`); colour alone signals nothing.
|
||
- Contrast: 4.5:1 for text, 3:1 for large text, icons and grouped controls; disabled is exempt. Three contrast levels exist (`<html data-contrast>`: standard, medium, high) and every role changes with them — which is why only roles are allowed.
|
||
|
||
### Surfaces and elevation
|
||
- The page is `bg-surface`. Panels separate by tone first: `surface-container-lowest` … `surface-container-highest` is a hierarchy of emphasis, not of height. Navigation chrome is `surface-container`; a dialog, a menu, the search bar are `surface-container-high`; a modal sheet is `surface-container-low`; a filled card is `surface-container-highest`. A region keeps its role at every width.
|
||
- Shadows (`shadow-elevation-1…5`) are for what floats or lifts: 1 for elevated cards, buttons and modal sheets; 2 for menus, the navigation bar, a scrolled app bar; 3 for the FAB, dialogs, pickers and search; one level more on hover; nothing rests above 3. Fewer shadows carry more meaning.
|
||
- A scrim is `bg-scrim/32`.
|
||
|
||
### Shape
|
||
- Corners come from the scale `rounded-corner-{none|xs|sm|md|lg|lg-increased|xl|xl-increased|xxl|full}`; Tailwind's `rounded-*` does not compile.
|
||
- By family: `full` buttons, icon buttons, chips' avatars, badges, switches, sliders, the search bar, navigation indicators; `xs` text fields, menus, snackbars, plain tooltips; `sm` chips; `md` cards, rich tooltips; `lg` the FAB and a side sheet's inner corners; `xl` dialogs, bottom sheets, the search view, pickers, carousel items; `xxl` large hero containers.
|
||
- Nested shapes: inner radius = outer radius − padding; never the same radius inside and out.
|
||
- A press squares a round shape (the components do it; nothing morphs on hover). The 35 `<x-shape>`s are decoration, never meaning, used sparingly.
|
||
|
||
### Type
|
||
- Every text element carries one `type-*` style: `display` for hero figures and short marketing lines; `headline` for page and section titles; `title` for card, dialog and list-section titles; `body` for paragraphs (`body-lg` for reading); `label` inside components (buttons, chips, tabs, captions). Never `text-sm`, `font-medium`, `leading-*`, `tracking-*` — they do not compile.
|
||
- `type-emphasized-*` is opt-in: a selected item, a primary action, a headline, a badge — not decoration.
|
||
- 40–60 characters per line; `tabular-nums` on figures that change; text must scale to 200% without loss (containers grow, rows wrap, no fixed heights on text, no ellipsis without a way to read the rest).
|
||
|
||
### Motion
|
||
- Position, size and shape move on the spatial springs (they overshoot): `transition-transform duration-(--md-sys-motion-spatial-default-duration) ease-spatial-default` — `fast` for small elements, `slow` for large ones. Colour and opacity move on the effects springs (`ease-effects-*`), which never overshoot. Always pair an easing with its duration.
|
||
- Entering decelerates, a permanent exit accelerates, a temporary exit (a sheet, a drawer) takes the emphasized curve; exits are shorter than entrances.
|
||
- Everything that moves goes through these tokens, so reduced motion makes it instant; a literal duration is a bug.
|
||
|
||
### States and targets
|
||
- Interactive elements carry `state-layer focus-ring`: hover 8%, focus 10%, pressed 10%, dragged 16% (`data-dragged`) of the content colour; disabled is `disabled:text-on-surface/38 disabled:bg-on-surface/12` and has no hover. Every state shows two indicators: colour plus a shape, an outline, an icon or a word.
|
||
- Every target is at least 48×48px with 8px between targets (`touch-target` on anything drawn smaller); a denser layout is an opt-in prop, never a default.
|
||
- Keyboard: Tab between components, arrows within one, Enter and Space activate, Escape dismisses; a dialog takes focus and gives it back to what opened it.
|
||
|
||
### Layout and breakpoints
|
||
- Widths are M3's window size classes, the only variants that compile: compact below 600px (the default), `medium:` 600, `expanded:` 840, `large:` 1200, `extra-large:` 1600, and `max-medium:` … for "below". In scripts, `from()` and `upTo()` from `resources/js/breakpoints.js`.
|
||
- What changes per class: compact — navigation bar, one pane, full-screen dialogs, a bottom sheet for choices; medium — collapsed rail, one pane; expanded — rail (collapsible), two panes, menus and basic dialogs; large and extra-large — the rail expanded, two panes, a third only at extra-large as a side sheet. `<x-scaffold>` does this; content lives in panes (`<x-pane>`, `<x-list-detail>` for a list's second pane), never beside the rail by hand.
|
||
- Margins are 16px below `medium` and 24px from it; spacing sits on the 4px grid, as padding and gaps on the parent, with margins only between layout regions. A fixed pane is 360px (expanded) or 412px (large); a side sheet at most 400px.
|
||
- Write logical properties (`ps-*`, `me-*`, `start-*`, `text-start`); directional icons mirror in RTL; charts and media controls stay LTR. Keep controls inside the safe area (`--material-safe-*`).
|
||
|
||
### Accessibility
|
||
- Native elements first (`<button>`, `<dialog>`, `<input>`), then ARIA. One `main`, one `banner`, one `contentinfo`; every repeated `nav` labelled, without the word "navigation".
|
||
- Headings in order from a single H1; the level is structure, the `type-*` style is appearance.
|
||
- An icon-only control has an accessible name that does not include its role; decorative icons are hidden; an error is announced and tied to its field (`aria-describedby`); a toast uses a polite live region and never takes focus. A single-key shortcut needs a modifier or a focused component.
|
||
|
||
### Icons
|
||
- `<x-icon name="…">` is a Material Symbol Rounded: `filled` means active or selected, `optical="20"` when drawn at 20px or less, one weight per group, the size and colour of the text beside it.
|
||
|
||
### Don'ts
|
||
- No icon in a snackbar; no disabled FAB (hide it); no horizontal radio rows; no hover morph on cards; no `outline` on dividers; no hex colours; no Tailwind breakpoints or scales; no segmented buttons, navigation drawer or bottom app bar — use `<x-button-group connected>`, the expanded rail and `<x-toolbar>`.
|
||
@endverbatim
|