Tailwind's sm…2xl are cleared for M3's window size classes (medium 600, expanded 840, large 1200, extra-large 1600; resources/js/breakpoints.js for scripts), and its radius, shadow, text-size, weight, leading, tracking and easing scales are cleared like its palette, so only M3's utilities compile. The semantic inks are roles rather than opacities (M3 reserves 38% for disabled). state.css declares M3's state opacities as tokens, adds the dragged layer and a touch-target utility. Plan: docs/plans/material-3-alignment.md, steps 1, 2, 3 and 8. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01Qwx5USif3wFFmxtHg5U1g9
113 lines
3.2 KiB
CSS
113 lines
3.2 KiB
CSS
/*
|
||
* Interaction states, as M3 draws them.
|
||
*
|
||
* The opacities are M3's state tokens (md.sys.state.*): the content colour laid over an
|
||
* element at 8% on hover, 10% on focus and press, 16% while dragged; disabled content at 38%
|
||
* and a disabled container at 12%.
|
||
*
|
||
* `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.
|
||
*/
|
||
|
||
:root {
|
||
--md-sys-state-hover-state-layer-opacity: 0.08;
|
||
--md-sys-state-focus-state-layer-opacity: 0.1;
|
||
--md-sys-state-pressed-state-layer-opacity: 0.1;
|
||
--md-sys-state-dragged-state-layer-opacity: 0.16;
|
||
--md-sys-state-disabled-content-opacity: 0.38;
|
||
--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;
|
||
}
|