Smooth the page's text in the foundation, not per surface
The showcase and the error pages set grayscale font smoothing on themselves, but the foundation did not, so an application that dropped Tailwind's antialiased class rendered heavier text on macOS than the package's own pages, silently. base.css now sets it on the page; the showcase's and error page's copies go, and the guard tells a leftover antialiased class to go too. Decided with the user (plan step 46). Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Opus 5
parent
6614b32fd3
commit
f5f040516e
+2
-1
@@ -138,7 +138,8 @@ component the views render, opening with the layer statement every package style
|
|||||||
either: layout components (`<x-scaffold>`, `<x-pane>`, `<x-stack>`, `<x-row>`, `<x-grid>`, the
|
either: layout components (`<x-scaffold>`, `<x-pane>`, `<x-stack>`, `<x-row>`, `<x-grid>`, the
|
||||||
canonical layouts) take M3's spacing tokens and breakpoints as props, a small set of `md-type-*`
|
canonical layouts) take M3's spacing tokens and breakpoints as props, a small set of `md-type-*`
|
||||||
and `md-ink-*` classes covers text on plain elements, and `--md-sys-*` custom properties serve the
|
and `md-ink-*` classes covers text on plain elements, and `--md-sys-*` custom properties serve the
|
||||||
rest of an application's own stylesheet.
|
rest of an application's own stylesheet. The foundation smooths text in grayscale, as Tailwind's
|
||||||
|
`antialiased` class did: drop the class.
|
||||||
|
|
||||||
### 7. New in 2.0.0
|
### 7. New in 2.0.0
|
||||||
|
|
||||||
|
|||||||
@@ -90,7 +90,7 @@ Scheme::resolveProfileUsing(fn (): ?string => Setting::get('color_profile'));
|
|||||||
|
|
||||||
## Tokens
|
## Tokens
|
||||||
|
|
||||||
2.0.0's vocabulary is plain CSS, without Tailwind. `resources/css/foundation.css` is the one required import, first in the entry, followed by the stylesheets of the components the views render (see Setup; 1.x's `material.css` shortcut is gone). It declares the layer order `material.reset, material.tokens, material.base, material.layout, material.components, material.text, material.visibility`, so an application's unlayered CSS beats every package rule, and `hidden` or `x-cloak` hides any element. It brings the reset, every `--md-sys-*` token (spacing included: `--md-sys-measurement-space25` … `space900`, 2–72px), and `md-state-layer`, `md-focus-ring`, `md-touch-target`, `md-link`. Text on plain elements takes the fixed text classes of `resources/css/text.css` and nothing else: `md-type-{display|headline|title|body|label}-{lg|md|sm}` and `md-type-emphasized-…`; `md-ink` (on-surface), `md-ink-variant`, `md-ink-quiet`, `md-ink-primary`, `md-ink-error`, `md-ink-success`, `md-ink-warning`, `md-ink-info`, `md-ink-inverse`; `md-text-start|center|end`, `md-truncate`, `md-line-clamp-2|3`, `md-nowrap`, `md-tabular`, `md-visually-hidden`. Every component is plain CSS now; the Tailwind names below stay for the showcase and an application's own views, until Tailwind itself leaves the package.
|
2.0.0's vocabulary is plain CSS, without Tailwind. `resources/css/foundation.css` is the one required import, first in the entry, followed by the stylesheets of the components the views render (see Setup; 1.x's `material.css` shortcut is gone). It declares the layer order `material.reset, material.tokens, material.base, material.layout, material.components, material.text, material.visibility`, so an application's unlayered CSS beats every package rule, and `hidden` or `x-cloak` hides any element. It brings the reset, the page's `surface` and `on-surface` in the brand typeface smoothed in grayscale (drop Tailwind's `antialiased`), every `--md-sys-*` token (spacing included: `--md-sys-measurement-space25` … `space900`, 2–72px), and `md-state-layer`, `md-focus-ring`, `md-touch-target`, `md-link`. Text on plain elements takes the fixed text classes of `resources/css/text.css` and nothing else: `md-type-{display|headline|title|body|label}-{lg|md|sm}` and `md-type-emphasized-…`; `md-ink` (on-surface), `md-ink-variant`, `md-ink-quiet`, `md-ink-primary`, `md-ink-error`, `md-ink-success`, `md-ink-warning`, `md-ink-info`, `md-ink-inverse`; `md-text-start|center|end`, `md-truncate`, `md-line-clamp-2|3`, `md-nowrap`, `md-tabular`, `md-visually-hidden`. Every component is plain CSS now; the Tailwind names below stay for the showcase and an application's own views, until Tailwind itself leaves the package.
|
||||||
|
|
||||||
Tailwind's default palette is cleared: every colour class names an M3 role. `text-red-600`, `bg-base-200` or `text-gray-500` compile to nothing. The rules behind the names below — which role, surface container, corner, type style, elevation level, motion spring, state and window size class to use, and M3's don'ts — are the `material-3` guideline (always on) and the `material-3-design` skill (the tables and Google's source pages); activate that skill before designing a screen.
|
Tailwind's default palette is cleared: every colour class names an M3 role. `text-red-600`, `bg-base-200` or `text-gray-500` compile to nothing. The rules behind the names below — which role, surface container, corner, type style, elevation level, motion spring, state and window size class to use, and M3's don'ts — are the `material-3` guideline (always on) and the `material-3-design` skill (the tables and Google's source pages); activate that skill before designing a screen.
|
||||||
|
|
||||||
|
|||||||
@@ -48,7 +48,6 @@
|
|||||||
min-height: 100dvh;
|
min-height: 100dvh;
|
||||||
background-color: var(--md-sys-color-surface);
|
background-color: var(--md-sys-color-surface);
|
||||||
color: var(--md-sys-color-on-surface);
|
color: var(--md-sys-color-on-surface);
|
||||||
-webkit-font-smoothing: antialiased;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
[data-md-error-page] {
|
[data-md-error-page] {
|
||||||
|
|||||||
@@ -8,6 +8,11 @@
|
|||||||
* `--md-ref-typeface-brand` (tokens/type.css), Google Sans Flex from tokens/font.css, whose
|
* `--md-ref-typeface-brand` (tokens/type.css), Google Sans Flex from tokens/font.css, whose
|
||||||
* `@font-face` this file imports into the same layer.
|
* `@font-face` this file imports into the same layer.
|
||||||
*
|
*
|
||||||
|
* Text is smoothed in grayscale where a platform offers the choice (macOS browsers): Google Sans
|
||||||
|
* Flex is drawn for it, and subpixel smoothing thickens its strokes on light text over a dark
|
||||||
|
* surface. Every surface the package draws — the showcase, the error pages — is set this way,
|
||||||
|
* and so is an application, which drops Tailwind's `antialiased` class with nothing to replace.
|
||||||
|
*
|
||||||
* In `material.base`, above the reset and below every component and text class.
|
* In `material.base`, above the reset and below every component and text class.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
@@ -20,5 +25,7 @@
|
|||||||
background-color: var(--md-sys-color-surface);
|
background-color: var(--md-sys-color-surface);
|
||||||
color: var(--md-sys-color-on-surface);
|
color: var(--md-sys-color-on-surface);
|
||||||
font-family: var(--md-ref-typeface-brand);
|
font-family: var(--md-ref-typeface-brand);
|
||||||
|
-webkit-font-smoothing: antialiased;
|
||||||
|
-moz-osx-font-smoothing: grayscale;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -28,11 +28,6 @@
|
|||||||
@layer material.reset, material.tokens, material.base, material.layout, material.components, material.text, material.visibility;
|
@layer material.reset, material.tokens, material.base, material.layout, material.components, material.text, material.visibility;
|
||||||
|
|
||||||
@layer material.components {
|
@layer material.components {
|
||||||
[data-md-showcase] {
|
|
||||||
-webkit-font-smoothing: antialiased;
|
|
||||||
-moz-osx-font-smoothing: grayscale;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* The rail's wordmark: `md-type-title-lg md-truncate md-focus-ring` cover the type, the
|
/* The rail's wordmark: `md-type-title-lg md-truncate md-focus-ring` cover the type, the
|
||||||
ellipsis and the ring; `display: block` gives the truncated text a width to ellipsize
|
ellipsis and the ring; `display: block` gives the truncated text a width to ellipsize
|
||||||
within, and the corner rounds the ring to match the state layer every other rail control
|
within, and the corner rounds the ring to match the state layer every other rail control
|
||||||
|
|||||||
@@ -161,8 +161,9 @@ class DesignGuard
|
|||||||
['/^(?:cursor-[\w-]+|pointer-events-(?:none|auto)|select-(?:none|text|all|auto)|touch-[\w-]+|resize(?:-[xy]|-none)?|appearance-(?:none|auto)|scroll-(?:smooth|auto)|-?scroll-[mp][trblxyse]?-[\w.]+|snap-[\w-]+)$/', 'Tailwind interactivity utility `%s` compiles to nothing — write the rule in your own CSS'],
|
['/^(?:cursor-[\w-]+|pointer-events-(?:none|auto)|select-(?:none|text|all|auto)|touch-[\w-]+|resize(?:-[xy]|-none)?|appearance-(?:none|auto)|scroll-(?:smooth|auto)|-?scroll-[mp][trblxyse]?-[\w.]+|snap-[\w-]+)$/', 'Tailwind interactivity utility `%s` compiles to nothing — write the rule in your own CSS'],
|
||||||
['/^(?:aspect-(?:auto|square|video|\d+\/\d+)|object-(?:contain|cover|fill|none|scale-down|top|bottom|center|left|right|left-top|left-bottom|right-top|right-bottom))$/', 'Tailwind media utility `%s` compiles to nothing — write `aspect-ratio`/`object-fit` in your own CSS'],
|
['/^(?:aspect-(?:auto|square|video|\d+\/\d+)|object-(?:contain|cover|fill|none|scale-down|top|bottom|center|left|right|left-top|left-bottom|right-top|right-bottom))$/', 'Tailwind media utility `%s` compiles to nothing — write `aspect-ratio`/`object-fit` in your own CSS'],
|
||||||
['/^font-(?:sans|serif)$/', 'Tailwind\'s `%s` compiles to nothing — the foundation already sets the brand typeface; any other `font-family` is your own CSS'],
|
['/^font-(?:sans|serif)$/', 'Tailwind\'s `%s` compiles to nothing — the foundation already sets the brand typeface; any other `font-family` is your own CSS'],
|
||||||
|
['/^antialiased$/', 'Tailwind\'s `%s` compiles to nothing — the foundation already smooths text in grayscale (base.css); drop it'],
|
||||||
['/^(?:underline|no-underline)$/', 'Tailwind\'s `%s` compiles to nothing — `md-link` draws a link (interaction.css); any other decoration is your own CSS'],
|
['/^(?:underline|no-underline)$/', 'Tailwind\'s `%s` compiles to nothing — `md-link` draws a link (interaction.css); any other decoration is your own CSS'],
|
||||||
['/^(?:uppercase|lowercase|capitalize|normal-case|italic|not-italic|overline|line-through|underline-offset-\w+|decoration-(?:\d+|solid|double|dotted|dashed|wavy|auto|from-font|clone|slice)|font-mono|antialiased|subpixel-antialiased|whitespace-(?:normal|pre|pre-line|pre-wrap|break-spaces)|break-(?:words|all|keep|normal)|wrap-(?:break-word|anywhere|normal)|text-(?:wrap|balance|pretty|ellipsis|clip|justify)|line-clamp-(?:\d+|none)|not-sr-only|list-(?:disc|decimal|none|inside|outside)|align-(?:baseline|top|middle|bottom|text-top|text-bottom|sub|super)|indent-[\w.]+|hyphens-(?:none|manual|auto)|(?:normal|lining|oldstyle|proportional)-nums|ordinal|slashed-zero|(?:diagonal|stacked)-fractions)$/', 'Tailwind text utility `%s` compiles to nothing — write the rule in your own CSS'],
|
['/^(?:uppercase|lowercase|capitalize|normal-case|italic|not-italic|overline|line-through|underline-offset-\w+|decoration-(?:\d+|solid|double|dotted|dashed|wavy|auto|from-font|clone|slice)|font-mono|subpixel-antialiased|whitespace-(?:normal|pre|pre-line|pre-wrap|break-spaces)|break-(?:words|all|keep|normal)|wrap-(?:break-word|anywhere|normal)|text-(?:wrap|balance|pretty|ellipsis|clip|justify)|line-clamp-(?:\d+|none)|not-sr-only|list-(?:disc|decimal|none|inside|outside)|align-(?:baseline|top|middle|bottom|text-top|text-bottom|sub|super)|indent-[\w.]+|hyphens-(?:none|manual|auto)|(?:normal|lining|oldstyle|proportional)-nums|ordinal|slashed-zero|(?:diagonal|stacked)-fractions)$/', 'Tailwind text utility `%s` compiles to nothing — write the rule in your own CSS'],
|
||||||
['/^bg-(?:(?:gradient-to|linear-to)-[a-z]+|radial|conic|cover|contain|auto|center|top|bottom|left|right|no-repeat|repeat(?:-[xy])?|fixed|local|scroll|none|clip-[a-z]+|origin-[a-z]+)$/', 'Tailwind background utility `%s` compiles to nothing — write the rule in your own CSS'],
|
['/^bg-(?:(?:gradient-to|linear-to)-[a-z]+|radial|conic|cover|contain|auto|center|top|bottom|left|right|no-repeat|repeat(?:-[xy])?|fixed|local|scroll|none|clip-[a-z]+|origin-[a-z]+)$/', 'Tailwind background utility `%s` compiles to nothing — write the rule in your own CSS'],
|
||||||
];
|
];
|
||||||
|
|
||||||
|
|||||||
@@ -372,6 +372,7 @@ it('reports position, border, effect, interactivity and text utilities with the
|
|||||||
'tailwind/utilities.blade.php:3 Tailwind text utility `font-mono` compiles to nothing — write the rule in your own CSS',
|
'tailwind/utilities.blade.php:3 Tailwind text utility `font-mono` compiles to nothing — write the rule in your own CSS',
|
||||||
'tailwind/utilities.blade.php:3 Tailwind text utility `list-disc` compiles to nothing — write the rule in your own CSS',
|
'tailwind/utilities.blade.php:3 Tailwind text utility `list-disc` compiles to nothing — write the rule in your own CSS',
|
||||||
'tailwind/utilities.blade.php:3 Tailwind text utility `uppercase` compiles to nothing — write the rule in your own CSS',
|
'tailwind/utilities.blade.php:3 Tailwind text utility `uppercase` compiles to nothing — write the rule in your own CSS',
|
||||||
|
"tailwind/utilities.blade.php:3 Tailwind's `antialiased` compiles to nothing — the foundation already smooths text in grayscale (base.css); drop it",
|
||||||
"tailwind/utilities.blade.php:3 Tailwind's `font-sans` compiles to nothing — the foundation already sets the brand typeface; any other `font-family` is your own CSS",
|
"tailwind/utilities.blade.php:3 Tailwind's `font-sans` compiles to nothing — the foundation already sets the brand typeface; any other `font-family` is your own CSS",
|
||||||
"tailwind/utilities.blade.php:3 Tailwind's `text-end` compiles to nothing — use `md-text-end` (text.css)",
|
"tailwind/utilities.blade.php:3 Tailwind's `text-end` compiles to nothing — use `md-text-end` (text.css)",
|
||||||
"tailwind/utilities.blade.php:3 Tailwind's `underline` compiles to nothing — `md-link` draws a link (interaction.css); any other decoration is your own CSS",
|
"tailwind/utilities.blade.php:3 Tailwind's `underline` compiles to nothing — `md-link` draws a link (interaction.css); any other decoration is your own CSS",
|
||||||
|
|||||||
@@ -21,7 +21,7 @@ it('serves the bundle as long-cached CSS at the hash of its own content', functi
|
|||||||
->assertHeader('Cache-Control', 'immutable, max-age=31536000, public');
|
->assertHeader('Cache-Control', 'immutable, max-age=31536000, public');
|
||||||
|
|
||||||
expect($response->getContent())
|
expect($response->getContent())
|
||||||
->toContain('[data-md-showcase]')
|
->toContain('[data-md-showcase-brand]')
|
||||||
->toContain('[data-md-pane]')
|
->toContain('[data-md-pane]')
|
||||||
->toContain('@layer material.reset, material.tokens');
|
->toContain('@layer material.reset, material.tokens');
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -212,6 +212,16 @@ it('brings every foundation file and text.css into the foundation, and nothing e
|
|||||||
->and(array_values(preg_grep('/^components\//', $foundation)))->toBe([]);
|
->and(array_values(preg_grep('/^components\//', $foundation)))->toBe([]);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it('paints the page in surface and on-surface, in the brand typeface, smoothed in grayscale', function () {
|
||||||
|
// An application drops Tailwind's `antialiased` with nothing to replace it: the showcase and the
|
||||||
|
// error pages, which set it themselves before, read it from here too.
|
||||||
|
$base = (string) preg_replace('~/\*.*?\*/~s', '', (string) file_get_contents(stylesheetPath('foundation/base.css')));
|
||||||
|
|
||||||
|
expect($base)->toMatch('/html \{\s*background-color: var\(--md-sys-color-surface\);\s*color: var\(--md-sys-color-on-surface\);\s*font-family: var\(--md-ref-typeface-brand\);\s*-webkit-font-smoothing: antialiased;\s*-moz-osx-font-smoothing: grayscale;\s*\}/')
|
||||||
|
->and((string) file_get_contents(stylesheetPath('showcase.css')).file_get_contents(stylesheetPath('components/error-page.css')))
|
||||||
|
->not->toContain('font-smoothing');
|
||||||
|
});
|
||||||
|
|
||||||
it('leaves no stylesheet under resources/css/ outside all.css or showcase.css', function () {
|
it('leaves no stylesheet under resources/css/ outside all.css or showcase.css', function () {
|
||||||
// The full tree now that Tailwind is gone (plan step 39): every .css file on disk, not just the
|
// The full tree now that Tailwind is gone (plan step 39): every .css file on disk, not just the
|
||||||
// ones a bundler happens to reach — a stray or orphaned file would show up here even though
|
// ones a bundler happens to reach — a stray or orphaned file would show up here even though
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
<div class="relative inset-0 -top-2 z-10 overflow-hidden shrink-0 col-start-2 justify-self-end container">
|
<div class="relative inset-0 -top-2 z-10 overflow-hidden shrink-0 col-start-2 justify-self-end container">
|
||||||
<span class="border border-t-2 rounded shadow outline-none ring-2 transition opacity-50 -rotate-45 cursor-pointer select-none"></span>
|
<span class="border border-t-2 rounded shadow outline-none ring-2 transition opacity-50 -rotate-45 cursor-pointer select-none"></span>
|
||||||
<span class="aspect-video object-cover font-mono font-sans underline uppercase text-end list-disc table bg-clip-text"></span>
|
<span class="aspect-video object-cover font-mono font-sans antialiased underline uppercase text-end list-disc table bg-clip-text"></span>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
Reference in New Issue
Block a user