Retire forbidAbsolutes() and forbidOpacityInk() from the design guard
Plan step 41 review (the user, 2026-09-15): without Tailwind, bg-white and text-on-surface/60 compile to nothing like any other utility, so family (i) now reports every colour utility on an M3 role, a 1.x ink name (text-meta, border-divider), white, black or current, with or without an opacity, each with its 2.0.0 replacement (an md-ink-* class, <x-divider>, <x-surface level>, md-state-layer or the role's var()). Check (iii) reads named colours anywhere in a declaration's value (border: 1px solid white), hex codes only in values (an id like #add no longer matches), and masks strings and url() contents first. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01Qwx5USif3wFFmxtHg5U1g9
This commit is contained in:
co-authored by
Claude Opus 5
parent
c047fefd8b
commit
6dc996afdf
@@ -24,6 +24,7 @@ it('finds what compiles to nothing', function () {
|
||||
expect(fixtureRelative($violations))->toBe([
|
||||
'app/Status.php:14 colour the theme does not declare `text-red-500`',
|
||||
"views/page.blade.php:2 Tailwind spacing utility `p-4` compiles to nothing — use a layout component's `gap`/`padding` prop (`<x-stack gap>`, `<x-surface padding>`), or `var(--md-sys-measurement-space*)` in your own CSS",
|
||||
'views/page.blade.php:6 Tailwind colour utility `text-tertiary` compiles to nothing — use `var(--md-sys-color-tertiary)` in your own CSS',
|
||||
'views/page.blade.php:8 Tailwind sizing utility `size-4` compiles to nothing — M3 keeps no size scale; write the literal length in your own CSS, or use `<x-pane width>`/`<x-grid min-item>` where it fits',
|
||||
'views/page.blade.php:3 unknown Material Symbol `o-home`',
|
||||
'views/page.blade.php:4 unknown Material Symbol `not_a_symbol`',
|
||||
@@ -150,6 +151,12 @@ it('sends an easing and a duration to the motion tokens', function () {
|
||||
|
||||
it('finds a colour written as a value', function () {
|
||||
expect(fixtureRelative(DesignGuard::scan(realpath(GUARD_FIXTURES.'/colour'))->violations()))->toBe([
|
||||
'colour/badge.blade.php:3 Tailwind colour utility `bg-white` compiles to nothing — M3 paints with roles, never white or black: `<x-surface level="surface-container-lowest">` or `var(--md-sys-color-surface-container-lowest)` for a white surface, an `on-` role (`md-ink`, `var(--md-sys-color-on-primary)`) for ink',
|
||||
'colour/badge.blade.php:3 Tailwind colour utility `text-black` compiles to nothing — M3 paints with roles, never white or black: `<x-surface level="surface-container-lowest">` or `var(--md-sys-color-surface-container-lowest)` for a white surface, an `on-` role (`md-ink`, `var(--md-sys-color-on-primary)`) for ink',
|
||||
'colour/badge.blade.php:3 Tailwind colour utility `border-white` compiles to nothing — M3 paints with roles, never white or black: `<x-surface level="surface-container-lowest">` or `var(--md-sys-color-surface-container-lowest)` for a white surface, an `on-` role (`md-ink`, `var(--md-sys-color-on-primary)`) for ink',
|
||||
"colour/badge.blade.php:4 Tailwind colour utility `text-on-surface/60` compiles to nothing — M3's quieter text is a role, not a faded one: `md-ink-variant` or `md-ink-quiet` (text.css)",
|
||||
"colour/badge.blade.php:4 Tailwind colour utility `bg-on-surface/12` compiles to nothing — M3's hover, focus and press overlays are `md-state-layer`; any other tint is `color-mix(in srgb, var(--md-sys-color-on-surface) <n>%, transparent)` in your own CSS",
|
||||
"colour/badge.blade.php:4 Tailwind colour utility `border-outline/38` compiles to nothing — M3's hover, focus and press overlays are `md-state-layer`; any other tint is `color-mix(in srgb, var(--md-sys-color-outline) <n>%, transparent)` in your own CSS",
|
||||
'colour/badge.blade.php:1 arbitrary colour `bg-[#1d7afc]`, use an M3 role',
|
||||
'colour/badge.blade.php:1 arbitrary colour `text-[rgb(0_0_0)]`, use an M3 role',
|
||||
'colour/badge.blade.php:1 arbitrary colour `border-[hsl(210_80%_50%)]`, use an M3 role',
|
||||
@@ -158,14 +165,27 @@ it('finds a colour written as a value', function () {
|
||||
]);
|
||||
});
|
||||
|
||||
it('sends 1.x ink names, the state-layer opacities and every other role to their 2.0.0 replacement', function () {
|
||||
$violations = fixtureRelative(DesignGuard::scan(realpath(GUARD_FIXTURES.'/tailwind/inks.blade.php'))->violations());
|
||||
|
||||
expect($violations)->toBe([
|
||||
'tailwind/inks.blade.php:1 Tailwind colour utility `text-meta` compiles to nothing — use `md-ink-variant` (text.css)',
|
||||
'tailwind/inks.blade.php:1 Tailwind colour utility `text-quiet` compiles to nothing — use `md-ink-quiet` (text.css)',
|
||||
'tailwind/inks.blade.php:1 Tailwind colour utility `border-divider` compiles to nothing — a line is `<x-divider>` or `<x-surface outlined>`, not a border utility',
|
||||
'tailwind/inks.blade.php:2 Tailwind colour utility `text-on-primary-container` compiles to nothing — use `var(--md-sys-color-on-primary-container)` in your own CSS',
|
||||
'tailwind/inks.blade.php:2 Tailwind colour utility `bg-background` compiles to nothing — use `<x-surface level="surface">`',
|
||||
'tailwind/inks.blade.php:2 Tailwind colour utility `text-current` compiles to nothing — write `currentColor` in your own CSS',
|
||||
]);
|
||||
});
|
||||
|
||||
it('names the md-ink-*, divider/surface or token replacement for a dead M3 role utility', function () {
|
||||
$violations = fixtureRelative(DesignGuard::scan(realpath(GUARD_FIXTURES.'/tailwind/roles.blade.php'))->violations());
|
||||
|
||||
expect($violations)->toBe([
|
||||
'tailwind/roles.blade.php:1 Tailwind ink role `text-on-surface-variant` compiles to nothing — use `md-ink-variant` (text.css)',
|
||||
'tailwind/roles.blade.php:1 Tailwind line role `border-outline-variant` compiles to nothing — use `<x-divider>` or `<x-surface outlined>` for a line, not a border utility',
|
||||
'tailwind/roles.blade.php:2 Tailwind surface role `bg-surface-container` compiles to nothing — use `<x-surface level="surface-container">`',
|
||||
'tailwind/roles.blade.php:2 Tailwind role utility `bg-primary` compiles to nothing — use `var(--md-sys-color-*)` in your own CSS',
|
||||
'tailwind/roles.blade.php:1 Tailwind colour utility `text-on-surface-variant` compiles to nothing — use `md-ink-variant` (text.css)',
|
||||
'tailwind/roles.blade.php:1 Tailwind colour utility `border-outline-variant` compiles to nothing — a line is `<x-divider>` or `<x-surface outlined>`, not a border utility',
|
||||
'tailwind/roles.blade.php:2 Tailwind colour utility `bg-surface-container` compiles to nothing — use `<x-surface level="surface-container">`',
|
||||
'tailwind/roles.blade.php:2 Tailwind colour utility `bg-primary` compiles to nothing — use `var(--md-sys-color-primary)` in your own CSS',
|
||||
]);
|
||||
});
|
||||
|
||||
@@ -258,38 +278,6 @@ it('reports an arbitrary [] value once, whatever utility it modifies, and strips
|
||||
]);
|
||||
});
|
||||
|
||||
it('bans the two absolutes when asked', function () {
|
||||
$violations = fixtureRelative(DesignGuard::scan(realpath(GUARD_FIXTURES.'/colour'))->forbidAbsolutes()->violations());
|
||||
|
||||
expect($violations)->toContain(
|
||||
'colour/badge.blade.php:3 absolute colour `bg-white`, use an M3 role',
|
||||
'colour/badge.blade.php:3 absolute colour `text-black`, use an M3 role',
|
||||
'colour/badge.blade.php:3 absolute colour `border-white`, use an M3 role',
|
||||
);
|
||||
});
|
||||
|
||||
it('leaves the two absolutes alone by default', function () {
|
||||
$violations = fixtureRelative(DesignGuard::scan(realpath(GUARD_FIXTURES.'/colour'))->violations());
|
||||
|
||||
expect($violations)->not->toContain('colour/badge.blade.php:3 absolute colour `bg-white`, use an M3 role');
|
||||
});
|
||||
|
||||
it('bans opacity as emphasis on ink when asked', function () {
|
||||
$violations = fixtureRelative(DesignGuard::scan(realpath(GUARD_FIXTURES.'/colour'))->forbidOpacityInk()->violations());
|
||||
|
||||
expect($violations)->toContain(
|
||||
'colour/badge.blade.php:4 opacity on ink `text-on-surface/60`, use a role (`text-on-surface-variant`, `text-outline`)',
|
||||
'colour/badge.blade.php:4 opacity on ink `bg-on-surface/12`, use a role (`text-on-surface-variant`, `text-outline`)',
|
||||
'colour/badge.blade.php:4 opacity on ink `border-outline/38`, use a role (`text-on-surface-variant`, `text-outline`)',
|
||||
);
|
||||
});
|
||||
|
||||
it('leaves opacity on ink alone by default, as the package\'s own disabled styles use it', function () {
|
||||
$violations = fixtureRelative(DesignGuard::scan(realpath(GUARD_FIXTURES.'/colour'))->violations());
|
||||
|
||||
expect($violations)->not->toContain('colour/badge.blade.php:4 opacity on ink `text-on-surface/60`, use a role (`text-on-surface-variant`, `text-outline`)');
|
||||
});
|
||||
|
||||
it('bans the roles an application leaves out', function () {
|
||||
$violations = fixtureRelative(DesignGuard::scan(realpath(GUARD_FIXTURES.'/views'))
|
||||
->forbidColours(['tertiary'])
|
||||
@@ -414,6 +402,8 @@ it('finds every literal design value and off-scale media query in the applicatio
|
||||
'app-css/app.css:3 literal colour `#ff0000` — use `var(--md-sys-color-*)`',
|
||||
'app-css/app.css:4 literal colour `rgb(0, 0, 0)` — use `var(--md-sys-color-*)`',
|
||||
'app-css/app.css:6 literal colour `rgba(0, 0, 0, 0.2)` — use `var(--md-sys-color-*)`',
|
||||
'app-css/app.css:24 literal colour `white` — use `var(--md-sys-color-*)`',
|
||||
'app-css/app.css:25 literal colour `#fff` — use `var(--md-sys-color-*)`',
|
||||
'app-css/app.css:5 literal radius `border-radius: 12px` — use `var(--md-sys-shape-corner-*)`',
|
||||
'app-css/app.css:6 literal shadow `box-shadow: 0 2px 4px rgba(0, 0, 0, 0.2)` — use `var(--md-sys-elevation-*)`',
|
||||
'app-css/app.css:7 literal font size `font-size: 14px` — use `var(--md-sys-typescale-*)`, which sets size, line height and weight together',
|
||||
@@ -422,7 +412,7 @@ it('finds every literal design value and off-scale media query in the applicatio
|
||||
'app-css/app.css:10 literal letter spacing `letter-spacing: 0.02em` — use `var(--md-sys-typescale-*-tracking)`',
|
||||
'app-css/app.css:11 literal easing in `transition: opacity 200ms ease-in-out` — use `var(--md-sys-motion-spatial-*)`/`var(--md-sys-motion-effects-*)`, paired with its `-duration`',
|
||||
'app-css/app.css:11 literal duration in `transition: opacity 200ms ease-in-out` — use `var(--md-sys-motion-…-duration)`, paired with its easing',
|
||||
"app-css/app.css:21 media query width `700px` is not one of M3's breakpoints — use 600, 840, 1200 or 1600px (medium, expanded, large, extra-large)",
|
||||
"app-css/app.css:34 media query width `700px` is not one of M3's breakpoints — use 600, 840, 1200 or 1600px (medium, expanded, large, extra-large)",
|
||||
]);
|
||||
});
|
||||
|
||||
|
||||
Reference in New Issue
Block a user