2.0.0 took Tailwind out of the stack, but the texts Boost copies into every application still taught its utilities: the core guideline said "built on Tailwind CSS", the always-on material-3 guideline wrote every rule as `bg-primary`, `type-*`, `rounded-corner-*`, `state-layer` and `medium:`, and both skills' tables and examples did the same. None of those classes exists in 2.0's stylesheets, so an agent following the guideline wrote markup that compiled to nothing. Found moving ReStride onto 2.0: its CLAUDE.md, and SealShare's, carry these texts. The guidelines and skills now teach what 2.0 has: component and layout component props (`gap="space200"`, `hide-from="medium"`), the `md-type-*`, `md-ink-*` and interaction classes, and `--md-sys-*` tokens in the application's own CSS, with breakpoints as range media queries. UPGRADE.md §1, §2 and §4 describe the finished move instead of the in-between state, and header comments that pointed at the removed tokens/utilities.css and tailwind.css, or called a component "still Tailwind", say what is true now. BoostVocabularyTest runs DesignGuard over the code in every shipped guideline and skill (fenced Blade and CSS, and each inline class list), so a text that teaches a class the stylesheets do not define fails the suite; it finds 268 violations in the texts as 2.0.0 shipped them. The guard's own table of what it reports is exempt. BoostResourcesTest now asks the design skill for each breakpoint's prop value and media query instead of the removed `medium:` variants. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
112 lines
4.0 KiB
CSS
112 lines
4.0 KiB
CSS
/*
|
||
* The interaction classes every interactive component shares, and an application's own control
|
||
* can use: M3's state layer, its focus indicator, its minimum target, and a link in running text.
|
||
*
|
||
* `md-state-layer` lays the content colour over an element at M3's state opacities
|
||
* (tokens/state.css): hover 8%, focus and press 10%, dragged 16%. Hover only where the pointer
|
||
* can hover, because a touch screen keeps the last hover after a tap; `data-md-dragged` on the
|
||
* element draws the dragged layer; a disabled element has none. The layer is a ::before, so the
|
||
* element becomes `position: relative` and `isolation: isolate`.
|
||
*
|
||
* `md-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).
|
||
*
|
||
* `md-touch-target` extends an element's pointer target to M3's 48×48 minimum without changing
|
||
* what is drawn: a ::after centred on it, at least `space600` (48px) each way. M3 gives the web
|
||
* target as "48 × 48 CSS pixels", so the size is px and does not grow with the text. It is
|
||
* `::after`-based, so a component that already draws with ::after wraps its control in an element
|
||
* carrying it.
|
||
*
|
||
* `md-link` is a link in running text: underlined in the colour of the words around it, because
|
||
* M3 never lets colour alone mark a link (docs/reference/m3/styles.md § Typography); give it
|
||
* `md-ink-primary` where it should also read as primary.
|
||
*
|
||
* They replace 1.x's `state-layer`, `focus-ring`, `touch-target` and `link` utilities, but for two
|
||
* changes: the dragged hook is `data-md-dragged` where the utility read `data-dragged`, and
|
||
* `md-touch-target` is px where the utility read 3rem. In `material.base`, so a component's own
|
||
* rules, the text classes and an application's rules all outrank them.
|
||
*/
|
||
|
||
@layer material.reset, material.tokens, material.base, material.layout, material.components, material.text, material.visibility;
|
||
|
||
@layer material.base {
|
||
.md-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-md-dragged]::before {
|
||
opacity: var(--md-sys-state-dragged-state-layer-opacity);
|
||
}
|
||
|
||
&:disabled::before,
|
||
&[aria-disabled='true']::before {
|
||
display: none;
|
||
}
|
||
}
|
||
|
||
.md-focus-ring {
|
||
outline: none;
|
||
|
||
&:focus-visible {
|
||
outline: 3px solid var(--md-sys-color-secondary);
|
||
outline-offset: 2px;
|
||
}
|
||
}
|
||
|
||
.md-touch-target {
|
||
position: relative;
|
||
|
||
&::after {
|
||
content: '';
|
||
position: absolute;
|
||
top: 50%;
|
||
left: 50%;
|
||
width: 100%;
|
||
height: 100%;
|
||
min-width: var(--md-sys-measurement-space600);
|
||
min-height: var(--md-sys-measurement-space600);
|
||
transform: translate(-50%, -50%);
|
||
}
|
||
}
|
||
|
||
.md-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;
|
||
}
|
||
}
|
||
}
|