Document the design guard's 2.0.0 API in the README and development skill
Plan step 41: short updates only (the full docs rewrite is Phase H) -- missingStylesheets(), the family-table replacements now named (a layout component and prop, an md-* class, or a var(--md-sys-*) token instead of a dead Tailwind utility), and a note that forbidAbsolutes()/forbidOpacityInk() matter mainly to an application still migrating off Tailwind. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01Qwx5USif3wFFmxtHg5U1g9
This commit is contained in:
co-authored by
Claude Sonnet 5
parent
09f4edd31d
commit
6147221b89
@@ -144,14 +144,17 @@ use NoNameWeb\LivewireMaterial\Testing\DesignGuard;
|
||||
|
||||
it('uses only what compiles', function () {
|
||||
expect(DesignGuard::scan([resource_path('views'), resource_path('js'), app_path()])
|
||||
->missingStylesheets(resource_path('css/app.css'))
|
||||
->forbidColours(['tertiary'])
|
||||
->violations())->toBe([]);
|
||||
});
|
||||
```
|
||||
|
||||
The guard fails on maryUI tags, daisyUI classes, colours the theme does not declare, unknown Material Symbol names and Blade directives written inside component tags. It also fails on everything 2.0 cleared, and every line names the replacement: Tailwind's breakpoint prefixes (`sm:` and `md:` → `medium:`, `lg:` → `expanded:`, `xl:` → `large:`, `2xl:` → `extra-large:`, `max-` likewise), its radius (`rounded-lg` → `rounded-corner-lg`), shadow (`shadow-md` → `shadow-elevation-2`), text size, weight, leading and tracking (`text-sm`, `leading-6`, `tracking-wide` → a `type-*` style, `font-medium` → a `type-emphasized-*` style), easing and duration (`ease-in-out` → `ease-standard`, `duration-300` → a `duration-(--md-sys-motion-…-duration)` with the easing it pairs with), and a colour written as a value rather than a role (`bg-[#1d7afc]`, `text-[rgb(…)]`, `border-[color-mix(…)]`).
|
||||
The guard fails on maryUI tags, daisyUI classes, colours the theme does not declare, unknown Material Symbol names and Blade directives written inside component tags. It also fails on every Tailwind utility or variant still sitting in a view, PHP or JS file — a breakpoint prefix, a radius, shadow, type size/weight/leading/tracking, easing or duration, a flex/grid/spacing/sizing/display utility, a text-layout utility, an M3 role utility (`text-on-surface-variant`, `bg-primary`), a pseudo-class variant, or an arbitrary `[…]` value — none of which compile any more, since the application carries no Tailwind: every line names its 2.0.0 replacement, a layout component and prop (`flex gap-4` → `<x-row gap="space200">`), an `md-*` class (`truncate` → `md-truncate`), or a token for the application's own CSS (`rounded-lg` → `var(--md-sys-shape-corner-lg)`). A class the application's own stylesheets declare is exempt, and so is every `md-*` class.
|
||||
|
||||
Two checks are opt-in: `forbidAbsolutes()` also fails on `bg-white` and `text-black` (M3's white is `surface-container-lowest`), and `forbidOpacityInk()` on opacity used as emphasis (`text-on-surface/60` → `text-on-surface-variant` or `text-outline`). M3 reserves 38 % on content and 12 % on a container for the disabled state, which is what the package's own components use them for, so neither is on by default.
|
||||
`missingStylesheets($cssEntry)` checks the CSS entry's `@import` graph (followed through every package file's own imports) against the package tags a view actually renders — unprefixed, under the configured prefix, or `<x-livewire-material::…>` — and `->links()`; each missing one names the exact `@import` line to add, and a tag the application shadows with its own component of the same name is reported instead. It also turns on a check of the application's own CSS (the entry and what it imports outside the package, plus any `.css` file among the scanned paths), which reports a literal colour, radius, shadow, font size, weight, line height, letter spacing, easing, duration or off-scale media query with its token or breakpoint — a value inside `var(--md-sys-…)` or `calc()` is always fine, and the generated `material-scheme.css` is skipped.
|
||||
|
||||
Two checks are opt-in, and matter mainly to an application still migrating off Tailwind: `forbidAbsolutes()` also fails on `bg-white` and `text-black` (M3's white is `surface-container-lowest`), and `forbidOpacityInk()` on opacity used as emphasis (`text-on-surface/60` → `text-on-surface-variant` or `text-outline`). M3 reserves 38 % on content and 12 % on a container for the disabled state, which is what the package's own components use them for, so neither is on by default.
|
||||
|
||||
## AI agents
|
||||
|
||||
|
||||
@@ -1111,30 +1111,42 @@ use NoNameWeb\LivewireMaterial\Testing\DesignGuard;
|
||||
|
||||
it('uses only what compiles', function () {
|
||||
expect(DesignGuard::scan([resource_path('views'), resource_path('js'), app_path()])
|
||||
->missingStylesheets(resource_path('css/app.css'))
|
||||
->forbidColours(['tertiary']) // roles this application's rules leave out
|
||||
->forbidAbsolutes() // opt-in: `bg-white`, `text-black`
|
||||
->forbidOpacityInk() // opt-in: `text-on-surface/60`
|
||||
->forbidAbsolutes() // opt-in, migration only: `bg-white`, `text-black`
|
||||
->forbidOpacityInk() // opt-in, migration only: `text-on-surface/60`
|
||||
->violations())->toBe([]);
|
||||
});
|
||||
```
|
||||
|
||||
It fails on maryUI tags, daisyUI classes, colours the theme does not declare, unknown symbol names and Blade directives written inside a component tag (where they do not compile), with `path:line` for each.
|
||||
|
||||
It also fails on every value the theme cleared, and names the replacement on the same line:
|
||||
It also fails on every Tailwind utility or variant, which compile to nothing in a Tailwind-free application, each with its 2.0.0 replacement — a layout component and prop, an `md-*` class, or a token for the application's own CSS. A class the application's own stylesheets declare is exempt, and so is every `md-*` class:
|
||||
|
||||
| Written | Use |
|
||||
| --- | --- |
|
||||
| `sm:`, `md:` (and `max-sm:`, `max-md:`) | `medium:` (`max-medium:`) |
|
||||
| `lg:`, `xl:`, `2xl:` | `expanded:`, `large:`, `extra-large:` |
|
||||
| `rounded-lg`, `rounded-t-2xl`, `rounded-full` | `rounded-corner-lg`, `rounded-t-corner-xxl`, `rounded-corner-full` |
|
||||
| `shadow-sm`, `shadow-md` … `shadow-2xl` | `shadow-elevation-1` … `shadow-elevation-5` |
|
||||
| `text-sm`, `leading-6`, `tracking-wide` | a `type-*` style, which sets the three together |
|
||||
| `font-medium`, `font-bold` | a `type-emphasized-*` style |
|
||||
| `ease-in-out`, `ease-linear` | `ease-standard`, or an `ease-spatial-*`/`ease-effects-*` |
|
||||
| `duration-300` | `duration-(--md-sys-motion-…-duration)`, paired with its easing |
|
||||
| `bg-[#1d7afc]`, `text-[rgb(…)]`, `border-[color-mix(…)]` | an M3 role |
|
||||
| `sm:`, `md:`, `lg:`, `xl:`, `2xl:` (and `max-`), `hover:`, `dark:` … | a layout component's `hide-below`/`hide-from`/`stack-below` prop, `:has()`/`aria-*`/`data-md-*`, or a plain `@media`/state rule |
|
||||
| `flex`, `grid`, `gap-4`, `grid-cols-*`, `items-center` … | `<x-row>`, `<x-grid>` or `<x-stack>` and their `gap`/`align`/`justify`/`columns` props |
|
||||
| `p-4`, `mt-2`, `space-y-4` | a layout component's `gap`/`padding` prop, or `var(--md-sys-measurement-space*)` |
|
||||
| `w-full`, `h-screen`, `min-w-0` | a literal length in your own CSS — M3 keeps no size scale |
|
||||
| `hidden` | a layout component's `hide-below`/`hide-from` prop, or `[hidden]` |
|
||||
| `block`, `inline-block`, `invisible` | a plain `display` rule in your own CSS |
|
||||
| `text-center`, `truncate`, `sr-only`, `whitespace-nowrap`, `line-clamp-2`, `tabular-nums` | `md-text-center`, `md-truncate`, `md-visually-hidden`, `md-nowrap`, `md-line-clamp-2`, `md-tabular` |
|
||||
| `text-on-surface-variant`, `text-primary` … | `md-ink-variant`, `md-ink-primary` … |
|
||||
| `border-outline-variant` | `<x-divider>` or `<x-surface outlined>` |
|
||||
| `bg-surface-container` | `<x-surface level="surface-container">` |
|
||||
| `bg-primary`, `border-error` … | `var(--md-sys-color-*)` |
|
||||
| `rounded-lg`, `rounded-t-2xl`, `rounded-full` | `var(--md-sys-shape-corner-lg)`, or `<x-surface corner="lg">` |
|
||||
| `shadow-sm`, `shadow-md` … `shadow-2xl` | `var(--md-sys-elevation-1)` … `var(--md-sys-elevation-5)` |
|
||||
| `text-sm`, `leading-6`, `tracking-wide` | one of the `md-type-*` classes, which set size, line height and tracking together |
|
||||
| `font-medium`, `font-bold` | one of the `md-type-emphasized-*` classes |
|
||||
| `ease-in-out`, `ease-linear` | `var(--md-sys-motion-spatial-*)`/`var(--md-sys-motion-effects-*)`, paired with its `-duration` |
|
||||
| `duration-300` | `var(--md-sys-motion-…-duration)`, paired with its easing |
|
||||
| `bg-[#1d7afc]`, `text-[rgb(…)]`, `w-[320px]` | an M3 role, or the literal value in your own CSS |
|
||||
|
||||
`forbidAbsolutes()` adds `white` and `black` (M3's white is `surface-container-lowest`, its ink an `on-` role) and `forbidOpacityInk()` adds opacity as emphasis (`text-on-surface/60` → `text-on-surface-variant` or `text-outline`). Both are off by default: M3 reserves 38 % on content and 12 % on a container for the disabled state, and the package's own components are written with those two opacities.
|
||||
`missingStylesheets($cssEntry)` follows the entry's `@import` graph through every package file's own imports (`split-button.css` counts `button.css` and `menu.css` too) and checks it against the package tags a scanned view renders (plain, prefixed or `<x-livewire-material::…>`) and `->links()`; a missing one names the exact `@import` line to add, and a tag the application shadows with its own component of the same name is reported instead — the application's component wins in Blade. It also turns on a check of the application's own CSS (the entry and what it imports outside the package, plus any `.css` file among the scanned paths, `material-scheme.css` excluded): a literal colour, radius, shadow, font size, weight, line height, letter spacing, easing, duration or a media query off M3's 600/840/1200/1600px scale, each with its token or breakpoint — a value inside `var(--md-sys-…)` or `calc()` is always fine.
|
||||
|
||||
`forbidAbsolutes()` adds `white` and `black` (M3's white is `surface-container-lowest`, its ink an `on-` role) and `forbidOpacityInk()` adds opacity as emphasis (`text-on-surface/60` → `text-on-surface-variant` or `text-outline`). Both are off by default and matter mainly to an application still migrating off Tailwind: M3 reserves 38 % on content and 12 % on a container for the disabled state, and the package's own components are written with those two opacities.
|
||||
|
||||
## Conventions
|
||||
|
||||
|
||||
Reference in New Issue
Block a user