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
287 lines
9.1 KiB
CSS
287 lines
9.1 KiB
CSS
/*
|
||
* 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;
|
||
}
|