Layer the token files and keep their utilities apart
Plan step 33. Each token file now opens with the material layer statement and wraps its declarations in material.tokens (the font face in material.base), so an application's unlayered scheme outranks the package default whatever the selectors, and the foundation can import the files with no layer() on the import. The type-* and state utilities move to tokens/utilities.css, still imported by material.css, so no file the foundation imports carries a Tailwind directive. [x-cloak] moves beside the [hidden] rule in foundation/hidden.css, outside every layer; material.css imports it. 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
9942e98fdd
commit
5f899c7287
@@ -0,0 +1,23 @@
|
|||||||
|
/*
|
||||||
|
* The two rules that hide, outside every layer.
|
||||||
|
*
|
||||||
|
* A layered rule always loses to an unlayered one, and no rule without `!important` beats one with
|
||||||
|
* it, so these two sit outside the layers and carry `!important`: whatever `display` a component
|
||||||
|
* gives its root, `hidden` on it hides it, and an application can pass `hidden` to any component.
|
||||||
|
* `hidden="until-found"` is left to the browser, which keeps such content searchable.
|
||||||
|
* `[x-cloak]` hides what Alpine has not started yet; Alpine removes the attribute when it has.
|
||||||
|
*
|
||||||
|
* Only a layered `!important` could outrank these, and the package writes none. The file is
|
||||||
|
* apart from reset.css because material.css, which stays for applications importing it after
|
||||||
|
* Tailwind, needs `[x-cloak]` without the reset.
|
||||||
|
*/
|
||||||
|
|
||||||
|
@layer material.reset, material.tokens, material.base, material.layout, material.components, material.text, material.visibility;
|
||||||
|
|
||||||
|
[hidden]:where(:not([hidden='until-found'])) {
|
||||||
|
display: none !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
[x-cloak] {
|
||||||
|
display: none !important;
|
||||||
|
}
|
||||||
@@ -9,7 +9,8 @@
|
|||||||
* @source '../../vendor/nonameweb/livewire-material/src';
|
* @source '../../vendor/nonameweb/livewire-material/src';
|
||||||
*
|
*
|
||||||
* tokens/scheme.css is the package's own default (M3's baseline purple), so an application
|
* tokens/scheme.css is the package's own default (M3's baseline purple), so an application
|
||||||
* renders before it has a scheme; the application's file declares the same roles later and wins.
|
* renders before it has a scheme; the application's file declares the same roles, unlayered, and
|
||||||
|
* wins over the default in `material.tokens`.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
@import './tokens/scheme.css';
|
@import './tokens/scheme.css';
|
||||||
@@ -20,6 +21,8 @@
|
|||||||
@import './tokens/font.css';
|
@import './tokens/font.css';
|
||||||
@import './tokens/theme.css';
|
@import './tokens/theme.css';
|
||||||
@import './tokens/state.css';
|
@import './tokens/state.css';
|
||||||
|
@import './tokens/utilities.css';
|
||||||
|
@import './foundation/hidden.css';
|
||||||
@import './components/actions.css';
|
@import './components/actions.css';
|
||||||
@import './components/groups.css';
|
@import './components/groups.css';
|
||||||
@import './components/list.css';
|
@import './components/list.css';
|
||||||
|
|||||||
@@ -9,6 +9,10 @@
|
|||||||
* sheet. On a dark surface a shadow is nearly invisible, so a panel separates from the page
|
* sheet. On a dark surface a shadow is nearly invisible, so a panel separates from the page
|
||||||
* by its container tone instead. As utilities: shadow-elevation-1 … shadow-elevation-5.
|
* by its container tone instead. As utilities: shadow-elevation-1 … shadow-elevation-5.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
@layer material.reset, material.tokens, material.base, material.layout, material.components, material.text, material.visibility;
|
||||||
|
|
||||||
|
@layer material.tokens {
|
||||||
:root {
|
:root {
|
||||||
--md-sys-color-shadow: #000000;
|
--md-sys-color-shadow: #000000;
|
||||||
--md-sys-color-scrim: #000000;
|
--md-sys-color-scrim: #000000;
|
||||||
@@ -19,3 +23,4 @@
|
|||||||
--md-sys-elevation-4: 0 2px 3px 0 color-mix(in srgb, var(--md-sys-color-shadow) 30%, transparent), 0 6px 10px 4px color-mix(in srgb, var(--md-sys-color-shadow) 15%, transparent);
|
--md-sys-elevation-4: 0 2px 3px 0 color-mix(in srgb, var(--md-sys-color-shadow) 30%, transparent), 0 6px 10px 4px color-mix(in srgb, var(--md-sys-color-shadow) 15%, transparent);
|
||||||
--md-sys-elevation-5: 0 4px 4px 0 color-mix(in srgb, var(--md-sys-color-shadow) 30%, transparent), 0 8px 12px 6px color-mix(in srgb, var(--md-sys-color-shadow) 15%, transparent);
|
--md-sys-elevation-5: 0 4px 4px 0 color-mix(in srgb, var(--md-sys-color-shadow) 30%, transparent), 0 8px 12px 6px color-mix(in srgb, var(--md-sys-color-shadow) 15%, transparent);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|||||||
@@ -6,9 +6,14 @@
|
|||||||
* size pinned — 63 KB where the full font is 4 MB. Vite copies it into the application's
|
* size pinned — 63 KB where the full font is 4 MB. Vite copies it into the application's
|
||||||
* build from this relative url.
|
* build from this relative url.
|
||||||
*
|
*
|
||||||
* An application that wants another typeface overrides `--md-ref-typeface-brand` (and so
|
* The face sits in `material.base` (foundation/base.css imports it). An application that wants
|
||||||
* `font-sans`) after importing material.css.
|
* another typeface overrides `--md-ref-typeface-brand` in its own stylesheet, which outranks
|
||||||
|
* every package layer.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
@layer material.reset, material.tokens, material.base, material.layout, material.components, material.text, material.visibility;
|
||||||
|
|
||||||
|
@layer material.base {
|
||||||
@font-face {
|
@font-face {
|
||||||
font-family: 'Google Sans Flex';
|
font-family: 'Google Sans Flex';
|
||||||
src: url('../../fonts/google-sans-flex/GoogleSansFlex-Latin.woff2') format('woff2');
|
src: url('../../fonts/google-sans-flex/GoogleSansFlex-Latin.woff2') format('woff2');
|
||||||
@@ -16,3 +21,4 @@
|
|||||||
font-style: normal;
|
font-style: normal;
|
||||||
font-display: swap;
|
font-display: swap;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|||||||
@@ -40,6 +40,10 @@
|
|||||||
* these tokens turns instant with no per-component check; anything that animates without them
|
* these tokens turns instant with no per-component check; anything that animates without them
|
||||||
* is a bug.
|
* is a bug.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
@layer material.reset, material.tokens, material.base, material.layout, material.components, material.text, material.visibility;
|
||||||
|
|
||||||
|
@layer material.tokens {
|
||||||
:root {
|
:root {
|
||||||
/* damping 0.6, stiffness 800; settles in 360ms; peaks at 1.095 at 139ms; sampled over 350ms */
|
/* damping 0.6, stiffness 800; settles in 360ms; peaks at 1.095 at 139ms; sampled over 350ms */
|
||||||
--md-sys-motion-spatial-fast: linear(0, 0.0195, 0.0716, 0.1471, 0.2381, 0.3378, 0.4404, 0.5416, 0.6378, 0.7265, 0.806, 0.8754, 0.9342, 0.9826, 1.0211, 1.0503, 1.0713, 1.0849, 1.0924, 1.0948, 1.0931, 1.0882, 1.0812, 1.0726, 1.0632, 1.0534, 1.0438, 1.0347, 1.0263, 1.0187, 1.0121, 1.0064, 1.0018, 0.9981, 0.9953, 0.9933, 0.992, 0.9913, 0.991, 0.9912, 0.9916, 0.9923, 0.9931, 0.994, 0.9949, 0.9958, 0.9967, 0.9975, 1);
|
--md-sys-motion-spatial-fast: linear(0, 0.0195, 0.0716, 0.1471, 0.2381, 0.3378, 0.4404, 0.5416, 0.6378, 0.7265, 0.806, 0.8754, 0.9342, 0.9826, 1.0211, 1.0503, 1.0713, 1.0849, 1.0924, 1.0948, 1.0931, 1.0882, 1.0812, 1.0726, 1.0632, 1.0534, 1.0438, 1.0347, 1.0263, 1.0187, 1.0121, 1.0064, 1.0018, 0.9981, 0.9953, 0.9933, 0.992, 0.9913, 0.991, 0.9912, 0.9916, 0.9923, 0.9931, 0.994, 0.9949, 0.9958, 0.9967, 0.9975, 1);
|
||||||
@@ -110,3 +114,4 @@
|
|||||||
--md-sys-motion-duration-long: 0ms;
|
--md-sys-motion-duration-long: 0ms;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|||||||
@@ -11,8 +11,15 @@
|
|||||||
* data-contrast — which the head script writes from the visitor's choice, or from the
|
* data-contrast — which the head script writes from the visitor's choice, or from the
|
||||||
* operating system's contrast setting while that choice is `system`. No media query
|
* operating system's contrast setting while that choice is `system`. No media query
|
||||||
* decides here, as none decides the theme.
|
* decides here, as none decides the theme.
|
||||||
|
*
|
||||||
|
* This is the package's default scheme, so the generated blocks are wrapped in
|
||||||
|
* `material.tokens` behind the layer statement (keep both when regenerating into this file): an
|
||||||
|
* application's own scheme, written unlayered, outranks it whatever the selectors.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
@layer material.reset, material.tokens, material.base, material.layout, material.components, material.text, material.visibility;
|
||||||
|
|
||||||
|
@layer material.tokens {
|
||||||
:root,
|
:root,
|
||||||
[data-theme='light'] {
|
[data-theme='light'] {
|
||||||
color-scheme: light;
|
color-scheme: light;
|
||||||
@@ -439,3 +446,4 @@
|
|||||||
--md-sys-color-inverse-warning: #312100;
|
--md-sys-color-inverse-warning: #312100;
|
||||||
--md-sys-color-inverse-info: #002252;
|
--md-sys-color-inverse-info: #002252;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|||||||
@@ -7,6 +7,10 @@
|
|||||||
*
|
*
|
||||||
* As utilities: rounded-corner-xs … rounded-corner-full.
|
* As utilities: rounded-corner-xs … rounded-corner-full.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
@layer material.reset, material.tokens, material.base, material.layout, material.components, material.text, material.visibility;
|
||||||
|
|
||||||
|
@layer material.tokens {
|
||||||
:root {
|
:root {
|
||||||
--md-sys-shape-corner-none: 0px;
|
--md-sys-shape-corner-none: 0px;
|
||||||
--md-sys-shape-corner-xs: 4px;
|
--md-sys-shape-corner-xs: 4px;
|
||||||
@@ -19,3 +23,4 @@
|
|||||||
--md-sys-shape-corner-xxl: 48px;
|
--md-sys-shape-corner-xxl: 48px;
|
||||||
--md-sys-shape-corner-full: 9999px;
|
--md-sys-shape-corner-full: 9999px;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|||||||
@@ -5,21 +5,14 @@
|
|||||||
* element at 8% on hover, 10% on focus and press, 16% while dragged; disabled content at 38%
|
* element at 8% on hover, 10% on focus and press, 16% while dragged; disabled content at 38%
|
||||||
* and a disabled container at 12%.
|
* and a disabled container at 12%.
|
||||||
*
|
*
|
||||||
* `state-layer` puts M3's state layer on an element. Hover only where the pointer can hover,
|
* The classes that draw them are foundation/interaction.css (`md-state-layer`, `md-focus-ring`,
|
||||||
* because a touch screen keeps the last hover after a tap; `data-dragged` on the element draws
|
* `md-touch-target`, `md-link`), and utilities.css for the components still written in Tailwind.
|
||||||
* the dragged layer. The layer is a ::before, so the element becomes `position: relative` and
|
* The tokens sit in `material.tokens`, so an application's own unlayered declaration wins.
|
||||||
* `isolation: isolate`; never pass `static` or a z-index to it.
|
|
||||||
*
|
|
||||||
* `touch-target` extends an element's pointer target to M3's 48×48px minimum without changing
|
|
||||||
* what is drawn: a ::after centred on it, at least 48px each way. It is `::after`-based, so a
|
|
||||||
* component that already draws with ::after wraps its control in an element carrying it.
|
|
||||||
*
|
|
||||||
* `focus-ring` is M3's focus indicator — 3px in secondary, 2px out, drawn only for keyboard
|
|
||||||
* focus. The site gives no thickness or offset; the values are @material/web's focus ring
|
|
||||||
* tokens (Apache-2.0, © Google LLC). `link` is a link in running text: underlined in the
|
|
||||||
* colour of the words around it.
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
@layer material.reset, material.tokens, material.base, material.layout, material.components, material.text, material.visibility;
|
||||||
|
|
||||||
|
@layer material.tokens {
|
||||||
:root {
|
:root {
|
||||||
--md-sys-state-hover-state-layer-opacity: 0.08;
|
--md-sys-state-hover-state-layer-opacity: 0.08;
|
||||||
--md-sys-state-focus-state-layer-opacity: 0.1;
|
--md-sys-state-focus-state-layer-opacity: 0.1;
|
||||||
@@ -28,85 +21,4 @@
|
|||||||
--md-sys-state-disabled-content-opacity: 0.38;
|
--md-sys-state-disabled-content-opacity: 0.38;
|
||||||
--md-sys-state-disabled-container-opacity: 0.12;
|
--md-sys-state-disabled-container-opacity: 0.12;
|
||||||
}
|
}
|
||||||
|
|
||||||
@utility state-layer {
|
|
||||||
position: relative;
|
|
||||||
isolation: isolate;
|
|
||||||
|
|
||||||
&::before {
|
|
||||||
content: '';
|
|
||||||
position: absolute;
|
|
||||||
inset: 0;
|
|
||||||
z-index: -1;
|
|
||||||
border-radius: inherit;
|
|
||||||
background-color: currentColor;
|
|
||||||
opacity: 0;
|
|
||||||
pointer-events: none;
|
|
||||||
transition: opacity var(--md-sys-motion-effects-fast-duration) var(--md-sys-motion-effects-fast);
|
|
||||||
}
|
|
||||||
|
|
||||||
@media (hover: hover) {
|
|
||||||
&:hover::before {
|
|
||||||
opacity: var(--md-sys-state-hover-state-layer-opacity);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
&:focus-visible::before {
|
|
||||||
opacity: var(--md-sys-state-focus-state-layer-opacity);
|
|
||||||
}
|
|
||||||
|
|
||||||
&:active::before {
|
|
||||||
opacity: var(--md-sys-state-pressed-state-layer-opacity);
|
|
||||||
}
|
|
||||||
|
|
||||||
&[data-dragged]::before {
|
|
||||||
opacity: var(--md-sys-state-dragged-state-layer-opacity);
|
|
||||||
}
|
|
||||||
|
|
||||||
&:disabled::before,
|
|
||||||
&[aria-disabled='true']::before {
|
|
||||||
display: none;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@utility touch-target {
|
|
||||||
position: relative;
|
|
||||||
|
|
||||||
&::after {
|
|
||||||
content: '';
|
|
||||||
position: absolute;
|
|
||||||
top: 50%;
|
|
||||||
left: 50%;
|
|
||||||
width: 100%;
|
|
||||||
height: 100%;
|
|
||||||
min-width: 3rem;
|
|
||||||
min-height: 3rem;
|
|
||||||
transform: translate(-50%, -50%);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@utility focus-ring {
|
|
||||||
outline: none;
|
|
||||||
|
|
||||||
&:focus-visible {
|
|
||||||
outline: 3px solid var(--md-sys-color-secondary);
|
|
||||||
outline-offset: 2px;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@utility link {
|
|
||||||
cursor: pointer;
|
|
||||||
text-decoration-line: underline;
|
|
||||||
text-decoration-thickness: from-font;
|
|
||||||
text-underline-offset: 0.15em;
|
|
||||||
border-radius: var(--md-sys-shape-corner-xs);
|
|
||||||
|
|
||||||
&:focus-visible {
|
|
||||||
outline: 3px solid var(--md-sys-color-secondary);
|
|
||||||
outline-offset: 2px;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
[x-cloak] {
|
|
||||||
display: none !important;
|
|
||||||
}
|
}
|
||||||
|
|||||||
+11
-186
@@ -4,20 +4,24 @@
|
|||||||
* Sizes, line heights, weights and tracking are androidx Compose Material 3's own token values
|
* Sizes, line heights, weights and tracking are androidx Compose Material 3's own token values
|
||||||
* (tokens/TypeScaleTokens.kt, Apache-2.0, © Google LLC, androidx-main @ 1608250), converted as
|
* (tokens/TypeScaleTokens.kt, Apache-2.0, © Google LLC, androidx-main @ 1608250), converted as
|
||||||
* M3's units table says: rem = sp / 16, tracking in rem as well (docs/reference/m3/styles.md
|
* M3's units table says: rem = sp / 16, tracking in rem as well (docs/reference/m3/styles.md
|
||||||
* § Typography). A style is used through its utility, never by hand-assembling `text-*`,
|
* § Typography). A style is used whole, through its class, never by hand-assembling a size, a
|
||||||
* `leading-*` and `tracking-*`:
|
* line height and a tracking:
|
||||||
*
|
*
|
||||||
* <h2 class="type-title-lg">…</h2>
|
* <h2 class="md-type-title-lg">…</h2>
|
||||||
* <p class="type-emphasized-headline-md tabular-nums">…</p>
|
* <p class="md-type-emphasized-headline-md md-tabular">…</p>
|
||||||
|
*
|
||||||
|
* The `md-type-*` classes are text.css; the `type-*` utilities of the components still written in
|
||||||
|
* Tailwind are utilities.css, with the same declarations.
|
||||||
*
|
*
|
||||||
* The brand typeface is Google Sans Flex (font.css). Emphasized styles are one weight step
|
* The brand typeface is Google Sans Flex (font.css). Emphasized styles are one weight step
|
||||||
* heavier and fully rounded ("ROND" 100) — the axis that typeface exists for, verified by
|
* heavier and fully rounded ("ROND" 100) — the axis that typeface exists for, verified by
|
||||||
* `npm run check:font` — and they carry their own tracking, because M3 widens four of them and
|
* `npm run check:font` — and they carry their own tracking, because M3 widens four of them and
|
||||||
* takes Display Large's negative tracking back to zero.
|
* takes Display Large's negative tracking back to zero.
|
||||||
*
|
|
||||||
* M3 asks for emphasis one element at a time, and `font-variation-settings` inherits, so every
|
|
||||||
* regular utility resets it: body copy inside an emphasized heading reads as itself again.
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
@layer material.reset, material.tokens, material.base, material.layout, material.components, material.text, material.visibility;
|
||||||
|
|
||||||
|
@layer material.tokens {
|
||||||
:root {
|
:root {
|
||||||
--md-ref-typeface-brand: 'Google Sans Flex', ui-sans-serif, system-ui, sans-serif, 'Apple Color Emoji', 'Segoe UI Emoji', 'Segoe UI Symbol', 'Noto Color Emoji';
|
--md-ref-typeface-brand: 'Google Sans Flex', ui-sans-serif, system-ui, sans-serif, 'Apple Color Emoji', 'Segoe UI Emoji', 'Segoe UI Symbol', 'Noto Color Emoji';
|
||||||
--md-ref-typeface-plain: var(--md-ref-typeface-brand);
|
--md-ref-typeface-plain: var(--md-ref-typeface-brand);
|
||||||
@@ -86,183 +90,4 @@
|
|||||||
--md-sys-typescale-emphasized-label-sm: var(--md-ref-typeface-weight-bold) 0.6875rem/1rem var(--md-ref-typeface-plain);
|
--md-sys-typescale-emphasized-label-sm: var(--md-ref-typeface-weight-bold) 0.6875rem/1rem var(--md-ref-typeface-plain);
|
||||||
--md-sys-typescale-emphasized-label-sm-tracking: 0.03125rem;
|
--md-sys-typescale-emphasized-label-sm-tracking: 0.03125rem;
|
||||||
}
|
}
|
||||||
|
|
||||||
@utility type-display-lg {
|
|
||||||
font: var(--md-sys-typescale-display-lg);
|
|
||||||
letter-spacing: var(--md-sys-typescale-display-lg-tracking);
|
|
||||||
font-variation-settings: normal;
|
|
||||||
}
|
|
||||||
|
|
||||||
@utility type-emphasized-display-lg {
|
|
||||||
font: var(--md-sys-typescale-emphasized-display-lg);
|
|
||||||
letter-spacing: var(--md-sys-typescale-emphasized-display-lg-tracking);
|
|
||||||
font-variation-settings: "ROND" 100;
|
|
||||||
}
|
|
||||||
|
|
||||||
@utility type-display-md {
|
|
||||||
font: var(--md-sys-typescale-display-md);
|
|
||||||
letter-spacing: var(--md-sys-typescale-display-md-tracking);
|
|
||||||
font-variation-settings: normal;
|
|
||||||
}
|
|
||||||
|
|
||||||
@utility type-emphasized-display-md {
|
|
||||||
font: var(--md-sys-typescale-emphasized-display-md);
|
|
||||||
letter-spacing: var(--md-sys-typescale-emphasized-display-md-tracking);
|
|
||||||
font-variation-settings: "ROND" 100;
|
|
||||||
}
|
|
||||||
|
|
||||||
@utility type-display-sm {
|
|
||||||
font: var(--md-sys-typescale-display-sm);
|
|
||||||
letter-spacing: var(--md-sys-typescale-display-sm-tracking);
|
|
||||||
font-variation-settings: normal;
|
|
||||||
}
|
|
||||||
|
|
||||||
@utility type-emphasized-display-sm {
|
|
||||||
font: var(--md-sys-typescale-emphasized-display-sm);
|
|
||||||
letter-spacing: var(--md-sys-typescale-emphasized-display-sm-tracking);
|
|
||||||
font-variation-settings: "ROND" 100;
|
|
||||||
}
|
|
||||||
|
|
||||||
@utility type-headline-lg {
|
|
||||||
font: var(--md-sys-typescale-headline-lg);
|
|
||||||
letter-spacing: var(--md-sys-typescale-headline-lg-tracking);
|
|
||||||
font-variation-settings: normal;
|
|
||||||
}
|
|
||||||
|
|
||||||
@utility type-emphasized-headline-lg {
|
|
||||||
font: var(--md-sys-typescale-emphasized-headline-lg);
|
|
||||||
letter-spacing: var(--md-sys-typescale-emphasized-headline-lg-tracking);
|
|
||||||
font-variation-settings: "ROND" 100;
|
|
||||||
}
|
|
||||||
|
|
||||||
@utility type-headline-md {
|
|
||||||
font: var(--md-sys-typescale-headline-md);
|
|
||||||
letter-spacing: var(--md-sys-typescale-headline-md-tracking);
|
|
||||||
font-variation-settings: normal;
|
|
||||||
}
|
|
||||||
|
|
||||||
@utility type-emphasized-headline-md {
|
|
||||||
font: var(--md-sys-typescale-emphasized-headline-md);
|
|
||||||
letter-spacing: var(--md-sys-typescale-emphasized-headline-md-tracking);
|
|
||||||
font-variation-settings: "ROND" 100;
|
|
||||||
}
|
|
||||||
|
|
||||||
@utility type-headline-sm {
|
|
||||||
font: var(--md-sys-typescale-headline-sm);
|
|
||||||
letter-spacing: var(--md-sys-typescale-headline-sm-tracking);
|
|
||||||
font-variation-settings: normal;
|
|
||||||
}
|
|
||||||
|
|
||||||
@utility type-emphasized-headline-sm {
|
|
||||||
font: var(--md-sys-typescale-emphasized-headline-sm);
|
|
||||||
letter-spacing: var(--md-sys-typescale-emphasized-headline-sm-tracking);
|
|
||||||
font-variation-settings: "ROND" 100;
|
|
||||||
}
|
|
||||||
|
|
||||||
@utility type-title-lg {
|
|
||||||
font: var(--md-sys-typescale-title-lg);
|
|
||||||
letter-spacing: var(--md-sys-typescale-title-lg-tracking);
|
|
||||||
font-variation-settings: normal;
|
|
||||||
}
|
|
||||||
|
|
||||||
@utility type-emphasized-title-lg {
|
|
||||||
font: var(--md-sys-typescale-emphasized-title-lg);
|
|
||||||
letter-spacing: var(--md-sys-typescale-emphasized-title-lg-tracking);
|
|
||||||
font-variation-settings: "ROND" 100;
|
|
||||||
}
|
|
||||||
|
|
||||||
@utility type-title-md {
|
|
||||||
font: var(--md-sys-typescale-title-md);
|
|
||||||
letter-spacing: var(--md-sys-typescale-title-md-tracking);
|
|
||||||
font-variation-settings: normal;
|
|
||||||
}
|
|
||||||
|
|
||||||
@utility type-emphasized-title-md {
|
|
||||||
font: var(--md-sys-typescale-emphasized-title-md);
|
|
||||||
letter-spacing: var(--md-sys-typescale-emphasized-title-md-tracking);
|
|
||||||
font-variation-settings: "ROND" 100;
|
|
||||||
}
|
|
||||||
|
|
||||||
@utility type-title-sm {
|
|
||||||
font: var(--md-sys-typescale-title-sm);
|
|
||||||
letter-spacing: var(--md-sys-typescale-title-sm-tracking);
|
|
||||||
font-variation-settings: normal;
|
|
||||||
}
|
|
||||||
|
|
||||||
@utility type-emphasized-title-sm {
|
|
||||||
font: var(--md-sys-typescale-emphasized-title-sm);
|
|
||||||
letter-spacing: var(--md-sys-typescale-emphasized-title-sm-tracking);
|
|
||||||
font-variation-settings: "ROND" 100;
|
|
||||||
}
|
|
||||||
|
|
||||||
@utility type-body-lg {
|
|
||||||
font: var(--md-sys-typescale-body-lg);
|
|
||||||
letter-spacing: var(--md-sys-typescale-body-lg-tracking);
|
|
||||||
font-variation-settings: normal;
|
|
||||||
}
|
|
||||||
|
|
||||||
@utility type-emphasized-body-lg {
|
|
||||||
font: var(--md-sys-typescale-emphasized-body-lg);
|
|
||||||
letter-spacing: var(--md-sys-typescale-emphasized-body-lg-tracking);
|
|
||||||
font-variation-settings: "ROND" 100;
|
|
||||||
}
|
|
||||||
|
|
||||||
@utility type-body-md {
|
|
||||||
font: var(--md-sys-typescale-body-md);
|
|
||||||
letter-spacing: var(--md-sys-typescale-body-md-tracking);
|
|
||||||
font-variation-settings: normal;
|
|
||||||
}
|
|
||||||
|
|
||||||
@utility type-emphasized-body-md {
|
|
||||||
font: var(--md-sys-typescale-emphasized-body-md);
|
|
||||||
letter-spacing: var(--md-sys-typescale-emphasized-body-md-tracking);
|
|
||||||
font-variation-settings: "ROND" 100;
|
|
||||||
}
|
|
||||||
|
|
||||||
@utility type-body-sm {
|
|
||||||
font: var(--md-sys-typescale-body-sm);
|
|
||||||
letter-spacing: var(--md-sys-typescale-body-sm-tracking);
|
|
||||||
font-variation-settings: normal;
|
|
||||||
}
|
|
||||||
|
|
||||||
@utility type-emphasized-body-sm {
|
|
||||||
font: var(--md-sys-typescale-emphasized-body-sm);
|
|
||||||
letter-spacing: var(--md-sys-typescale-emphasized-body-sm-tracking);
|
|
||||||
font-variation-settings: "ROND" 100;
|
|
||||||
}
|
|
||||||
|
|
||||||
@utility type-label-lg {
|
|
||||||
font: var(--md-sys-typescale-label-lg);
|
|
||||||
letter-spacing: var(--md-sys-typescale-label-lg-tracking);
|
|
||||||
font-variation-settings: normal;
|
|
||||||
}
|
|
||||||
|
|
||||||
@utility type-emphasized-label-lg {
|
|
||||||
font: var(--md-sys-typescale-emphasized-label-lg);
|
|
||||||
letter-spacing: var(--md-sys-typescale-emphasized-label-lg-tracking);
|
|
||||||
font-variation-settings: "ROND" 100;
|
|
||||||
}
|
|
||||||
|
|
||||||
@utility type-label-md {
|
|
||||||
font: var(--md-sys-typescale-label-md);
|
|
||||||
letter-spacing: var(--md-sys-typescale-label-md-tracking);
|
|
||||||
font-variation-settings: normal;
|
|
||||||
}
|
|
||||||
|
|
||||||
@utility type-emphasized-label-md {
|
|
||||||
font: var(--md-sys-typescale-emphasized-label-md);
|
|
||||||
letter-spacing: var(--md-sys-typescale-emphasized-label-md-tracking);
|
|
||||||
font-variation-settings: "ROND" 100;
|
|
||||||
}
|
|
||||||
|
|
||||||
@utility type-label-sm {
|
|
||||||
font: var(--md-sys-typescale-label-sm);
|
|
||||||
letter-spacing: var(--md-sys-typescale-label-sm-tracking);
|
|
||||||
font-variation-settings: normal;
|
|
||||||
}
|
|
||||||
|
|
||||||
@utility type-emphasized-label-sm {
|
|
||||||
font: var(--md-sys-typescale-emphasized-label-sm);
|
|
||||||
letter-spacing: var(--md-sys-typescale-emphasized-label-sm-tracking);
|
|
||||||
font-variation-settings: "ROND" 100;
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,286 @@
|
|||||||
|
/*
|
||||||
|
* The token utilities, for the components still written in Tailwind.
|
||||||
|
*
|
||||||
|
* Tailwind's side of tokens/state.css and tokens/type.css, kept apart so that the token files the
|
||||||
|
* foundation imports carry no Tailwind directive. material.css imports this file after Tailwind;
|
||||||
|
* it goes when the last component leaves Tailwind. New markup uses the plain-CSS classes instead,
|
||||||
|
* which carry the same declarations: `md-state-layer`, `md-focus-ring`, `md-touch-target` and
|
||||||
|
* `md-link` (foundation/interaction.css), and `md-type-*` (text.css).
|
||||||
|
*
|
||||||
|
* `state-layer` puts M3's state layer on an element. Hover only where the pointer can hover,
|
||||||
|
* because a touch screen keeps the last hover after a tap; `data-dragged` on the element draws
|
||||||
|
* the dragged layer. The layer is a ::before, so the element becomes `position: relative` and
|
||||||
|
* `isolation: isolate`; never pass `static` or a z-index to it.
|
||||||
|
*
|
||||||
|
* `touch-target` extends an element's pointer target to M3's 48×48px minimum without changing
|
||||||
|
* what is drawn: a ::after centred on it, at least 48px each way. It is `::after`-based, so a
|
||||||
|
* component that already draws with ::after wraps its control in an element carrying it.
|
||||||
|
*
|
||||||
|
* `focus-ring` is M3's focus indicator — 3px in secondary, 2px out, drawn only for keyboard
|
||||||
|
* focus. The site gives no thickness or offset; the values are @material/web's focus ring
|
||||||
|
* tokens (Apache-2.0, © Google LLC). `link` is a link in running text: underlined in the
|
||||||
|
* colour of the words around it.
|
||||||
|
*
|
||||||
|
* `type-*` is one of M3's 30 type styles (tokens/type.css): size, line height, weight and
|
||||||
|
* tracking together. M3 asks for emphasis one element at a time, and `font-variation-settings`
|
||||||
|
* inherits, so every regular utility resets it: body copy inside an emphasized heading reads as
|
||||||
|
* itself again.
|
||||||
|
*/
|
||||||
|
|
||||||
|
@utility state-layer {
|
||||||
|
position: relative;
|
||||||
|
isolation: isolate;
|
||||||
|
|
||||||
|
&::before {
|
||||||
|
content: '';
|
||||||
|
position: absolute;
|
||||||
|
inset: 0;
|
||||||
|
z-index: -1;
|
||||||
|
border-radius: inherit;
|
||||||
|
background-color: currentColor;
|
||||||
|
opacity: 0;
|
||||||
|
pointer-events: none;
|
||||||
|
transition: opacity var(--md-sys-motion-effects-fast-duration) var(--md-sys-motion-effects-fast);
|
||||||
|
}
|
||||||
|
|
||||||
|
@media (hover: hover) {
|
||||||
|
&:hover::before {
|
||||||
|
opacity: var(--md-sys-state-hover-state-layer-opacity);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
&:focus-visible::before {
|
||||||
|
opacity: var(--md-sys-state-focus-state-layer-opacity);
|
||||||
|
}
|
||||||
|
|
||||||
|
&:active::before {
|
||||||
|
opacity: var(--md-sys-state-pressed-state-layer-opacity);
|
||||||
|
}
|
||||||
|
|
||||||
|
&[data-dragged]::before {
|
||||||
|
opacity: var(--md-sys-state-dragged-state-layer-opacity);
|
||||||
|
}
|
||||||
|
|
||||||
|
&:disabled::before,
|
||||||
|
&[aria-disabled='true']::before {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@utility touch-target {
|
||||||
|
position: relative;
|
||||||
|
|
||||||
|
&::after {
|
||||||
|
content: '';
|
||||||
|
position: absolute;
|
||||||
|
top: 50%;
|
||||||
|
left: 50%;
|
||||||
|
width: 100%;
|
||||||
|
height: 100%;
|
||||||
|
min-width: 3rem;
|
||||||
|
min-height: 3rem;
|
||||||
|
transform: translate(-50%, -50%);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@utility focus-ring {
|
||||||
|
outline: none;
|
||||||
|
|
||||||
|
&:focus-visible {
|
||||||
|
outline: 3px solid var(--md-sys-color-secondary);
|
||||||
|
outline-offset: 2px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@utility link {
|
||||||
|
cursor: pointer;
|
||||||
|
text-decoration-line: underline;
|
||||||
|
text-decoration-thickness: from-font;
|
||||||
|
text-underline-offset: 0.15em;
|
||||||
|
border-radius: var(--md-sys-shape-corner-xs);
|
||||||
|
|
||||||
|
&:focus-visible {
|
||||||
|
outline: 3px solid var(--md-sys-color-secondary);
|
||||||
|
outline-offset: 2px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@utility type-display-lg {
|
||||||
|
font: var(--md-sys-typescale-display-lg);
|
||||||
|
letter-spacing: var(--md-sys-typescale-display-lg-tracking);
|
||||||
|
font-variation-settings: normal;
|
||||||
|
}
|
||||||
|
|
||||||
|
@utility type-emphasized-display-lg {
|
||||||
|
font: var(--md-sys-typescale-emphasized-display-lg);
|
||||||
|
letter-spacing: var(--md-sys-typescale-emphasized-display-lg-tracking);
|
||||||
|
font-variation-settings: "ROND" 100;
|
||||||
|
}
|
||||||
|
|
||||||
|
@utility type-display-md {
|
||||||
|
font: var(--md-sys-typescale-display-md);
|
||||||
|
letter-spacing: var(--md-sys-typescale-display-md-tracking);
|
||||||
|
font-variation-settings: normal;
|
||||||
|
}
|
||||||
|
|
||||||
|
@utility type-emphasized-display-md {
|
||||||
|
font: var(--md-sys-typescale-emphasized-display-md);
|
||||||
|
letter-spacing: var(--md-sys-typescale-emphasized-display-md-tracking);
|
||||||
|
font-variation-settings: "ROND" 100;
|
||||||
|
}
|
||||||
|
|
||||||
|
@utility type-display-sm {
|
||||||
|
font: var(--md-sys-typescale-display-sm);
|
||||||
|
letter-spacing: var(--md-sys-typescale-display-sm-tracking);
|
||||||
|
font-variation-settings: normal;
|
||||||
|
}
|
||||||
|
|
||||||
|
@utility type-emphasized-display-sm {
|
||||||
|
font: var(--md-sys-typescale-emphasized-display-sm);
|
||||||
|
letter-spacing: var(--md-sys-typescale-emphasized-display-sm-tracking);
|
||||||
|
font-variation-settings: "ROND" 100;
|
||||||
|
}
|
||||||
|
|
||||||
|
@utility type-headline-lg {
|
||||||
|
font: var(--md-sys-typescale-headline-lg);
|
||||||
|
letter-spacing: var(--md-sys-typescale-headline-lg-tracking);
|
||||||
|
font-variation-settings: normal;
|
||||||
|
}
|
||||||
|
|
||||||
|
@utility type-emphasized-headline-lg {
|
||||||
|
font: var(--md-sys-typescale-emphasized-headline-lg);
|
||||||
|
letter-spacing: var(--md-sys-typescale-emphasized-headline-lg-tracking);
|
||||||
|
font-variation-settings: "ROND" 100;
|
||||||
|
}
|
||||||
|
|
||||||
|
@utility type-headline-md {
|
||||||
|
font: var(--md-sys-typescale-headline-md);
|
||||||
|
letter-spacing: var(--md-sys-typescale-headline-md-tracking);
|
||||||
|
font-variation-settings: normal;
|
||||||
|
}
|
||||||
|
|
||||||
|
@utility type-emphasized-headline-md {
|
||||||
|
font: var(--md-sys-typescale-emphasized-headline-md);
|
||||||
|
letter-spacing: var(--md-sys-typescale-emphasized-headline-md-tracking);
|
||||||
|
font-variation-settings: "ROND" 100;
|
||||||
|
}
|
||||||
|
|
||||||
|
@utility type-headline-sm {
|
||||||
|
font: var(--md-sys-typescale-headline-sm);
|
||||||
|
letter-spacing: var(--md-sys-typescale-headline-sm-tracking);
|
||||||
|
font-variation-settings: normal;
|
||||||
|
}
|
||||||
|
|
||||||
|
@utility type-emphasized-headline-sm {
|
||||||
|
font: var(--md-sys-typescale-emphasized-headline-sm);
|
||||||
|
letter-spacing: var(--md-sys-typescale-emphasized-headline-sm-tracking);
|
||||||
|
font-variation-settings: "ROND" 100;
|
||||||
|
}
|
||||||
|
|
||||||
|
@utility type-title-lg {
|
||||||
|
font: var(--md-sys-typescale-title-lg);
|
||||||
|
letter-spacing: var(--md-sys-typescale-title-lg-tracking);
|
||||||
|
font-variation-settings: normal;
|
||||||
|
}
|
||||||
|
|
||||||
|
@utility type-emphasized-title-lg {
|
||||||
|
font: var(--md-sys-typescale-emphasized-title-lg);
|
||||||
|
letter-spacing: var(--md-sys-typescale-emphasized-title-lg-tracking);
|
||||||
|
font-variation-settings: "ROND" 100;
|
||||||
|
}
|
||||||
|
|
||||||
|
@utility type-title-md {
|
||||||
|
font: var(--md-sys-typescale-title-md);
|
||||||
|
letter-spacing: var(--md-sys-typescale-title-md-tracking);
|
||||||
|
font-variation-settings: normal;
|
||||||
|
}
|
||||||
|
|
||||||
|
@utility type-emphasized-title-md {
|
||||||
|
font: var(--md-sys-typescale-emphasized-title-md);
|
||||||
|
letter-spacing: var(--md-sys-typescale-emphasized-title-md-tracking);
|
||||||
|
font-variation-settings: "ROND" 100;
|
||||||
|
}
|
||||||
|
|
||||||
|
@utility type-title-sm {
|
||||||
|
font: var(--md-sys-typescale-title-sm);
|
||||||
|
letter-spacing: var(--md-sys-typescale-title-sm-tracking);
|
||||||
|
font-variation-settings: normal;
|
||||||
|
}
|
||||||
|
|
||||||
|
@utility type-emphasized-title-sm {
|
||||||
|
font: var(--md-sys-typescale-emphasized-title-sm);
|
||||||
|
letter-spacing: var(--md-sys-typescale-emphasized-title-sm-tracking);
|
||||||
|
font-variation-settings: "ROND" 100;
|
||||||
|
}
|
||||||
|
|
||||||
|
@utility type-body-lg {
|
||||||
|
font: var(--md-sys-typescale-body-lg);
|
||||||
|
letter-spacing: var(--md-sys-typescale-body-lg-tracking);
|
||||||
|
font-variation-settings: normal;
|
||||||
|
}
|
||||||
|
|
||||||
|
@utility type-emphasized-body-lg {
|
||||||
|
font: var(--md-sys-typescale-emphasized-body-lg);
|
||||||
|
letter-spacing: var(--md-sys-typescale-emphasized-body-lg-tracking);
|
||||||
|
font-variation-settings: "ROND" 100;
|
||||||
|
}
|
||||||
|
|
||||||
|
@utility type-body-md {
|
||||||
|
font: var(--md-sys-typescale-body-md);
|
||||||
|
letter-spacing: var(--md-sys-typescale-body-md-tracking);
|
||||||
|
font-variation-settings: normal;
|
||||||
|
}
|
||||||
|
|
||||||
|
@utility type-emphasized-body-md {
|
||||||
|
font: var(--md-sys-typescale-emphasized-body-md);
|
||||||
|
letter-spacing: var(--md-sys-typescale-emphasized-body-md-tracking);
|
||||||
|
font-variation-settings: "ROND" 100;
|
||||||
|
}
|
||||||
|
|
||||||
|
@utility type-body-sm {
|
||||||
|
font: var(--md-sys-typescale-body-sm);
|
||||||
|
letter-spacing: var(--md-sys-typescale-body-sm-tracking);
|
||||||
|
font-variation-settings: normal;
|
||||||
|
}
|
||||||
|
|
||||||
|
@utility type-emphasized-body-sm {
|
||||||
|
font: var(--md-sys-typescale-emphasized-body-sm);
|
||||||
|
letter-spacing: var(--md-sys-typescale-emphasized-body-sm-tracking);
|
||||||
|
font-variation-settings: "ROND" 100;
|
||||||
|
}
|
||||||
|
|
||||||
|
@utility type-label-lg {
|
||||||
|
font: var(--md-sys-typescale-label-lg);
|
||||||
|
letter-spacing: var(--md-sys-typescale-label-lg-tracking);
|
||||||
|
font-variation-settings: normal;
|
||||||
|
}
|
||||||
|
|
||||||
|
@utility type-emphasized-label-lg {
|
||||||
|
font: var(--md-sys-typescale-emphasized-label-lg);
|
||||||
|
letter-spacing: var(--md-sys-typescale-emphasized-label-lg-tracking);
|
||||||
|
font-variation-settings: "ROND" 100;
|
||||||
|
}
|
||||||
|
|
||||||
|
@utility type-label-md {
|
||||||
|
font: var(--md-sys-typescale-label-md);
|
||||||
|
letter-spacing: var(--md-sys-typescale-label-md-tracking);
|
||||||
|
font-variation-settings: normal;
|
||||||
|
}
|
||||||
|
|
||||||
|
@utility type-emphasized-label-md {
|
||||||
|
font: var(--md-sys-typescale-emphasized-label-md);
|
||||||
|
letter-spacing: var(--md-sys-typescale-emphasized-label-md-tracking);
|
||||||
|
font-variation-settings: "ROND" 100;
|
||||||
|
}
|
||||||
|
|
||||||
|
@utility type-label-sm {
|
||||||
|
font: var(--md-sys-typescale-label-sm);
|
||||||
|
letter-spacing: var(--md-sys-typescale-label-sm-tracking);
|
||||||
|
font-variation-settings: normal;
|
||||||
|
}
|
||||||
|
|
||||||
|
@utility type-emphasized-label-sm {
|
||||||
|
font: var(--md-sys-typescale-emphasized-label-sm);
|
||||||
|
letter-spacing: var(--md-sys-typescale-emphasized-label-sm-tracking);
|
||||||
|
font-variation-settings: "ROND" 100;
|
||||||
|
}
|
||||||
@@ -37,13 +37,14 @@ function typeStyles(): array
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The body of every `@utility type-…` block of type.css, keyed by utility name.
|
* The body of every `@utility type-…` block, keyed by utility name. The utilities live in
|
||||||
|
* tokens/utilities.css, apart from the tokens, so the foundation imports no Tailwind directive.
|
||||||
*
|
*
|
||||||
* @return array<string, string>
|
* @return array<string, string>
|
||||||
*/
|
*/
|
||||||
function typeUtilities(): array
|
function typeUtilities(): array
|
||||||
{
|
{
|
||||||
preg_match_all('/@utility (type-[\w-]+) \{\n(.*?)\n\}/s', File::get(packageCss('tokens/type.css')), $matches, PREG_SET_ORDER);
|
preg_match_all('/@utility (type-[\w-]+) \{\n(.*?)\n\}/s', File::get(packageCss('tokens/utilities.css')), $matches, PREG_SET_ORDER);
|
||||||
|
|
||||||
return array_combine(array_column($matches, 1), array_column($matches, 2));
|
return array_combine(array_column($matches, 1), array_column($matches, 2));
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user