tests / feature (8.4) (push) Successful in 2m0s
tests / feature (8.5) (push) Successful in 2m0s
tests / browser (chrome, chromium) (push) Failing after 8m3s
tests / browser (firefox, firefox) (push) Failing after 12m58s
tests / browser (safari, webkit) (push) Failing after 13m8s
Tailwind left the stack in 2.0.0, but the package still carried about 330 mentions of it. What the guard's Tailwind detection protected — a class that compiles to nothing — is now protected by a check that does not care where a dead class came from. DesignGuard: about 500 lines of Tailwind tables, scales, palettes and "2.0.0 replacement" hints give way to one check — a class a view or PHP file writes that neither the application's stylesheets nor the package's own declare. It catches a utility of any framework, a typo and a class whose rules were deleted alike, so it also found two classes ReStride draws nothing with. A stylesheet has to be in reach for it: the `.css` files among the scanned paths, or what the `missingStylesheets()` entry imports. The class reader no longer mistakes an array index for a class list (`$block['base']`), and it reads the array a class helper is given, where it read nothing before. The package's own three Tailwind self-guards go with it. Only their one unique check stays, as a test of its own: every `matchMedia` width in resources/js is an M3 breakpoint. The pagination views are `material.blade.php` and `simple-material.blade.php`; only Laravel's and Livewire's default theme names ever made them `tailwind`. The provider sets `Paginator`'s default views and switches `livewire.pagination_theme` to `material` when it is still Livewire's own default, so no application can forget the config; a theme an application chose, and a component's own `$paginationTheme` or `paginationView()`, still win. The rest is prose: the layer-order guidance for an application that still builds Tailwind, the Tailwind wording in the README, the Boost guidelines and the development skill, and about 25 "this used to be a Tailwind utility" comments, along with every "plan step NN" pointer into a gitignored folder. The reset keeps its credit, and NOTICE now carries it too. Feature suite 1159 passed, Chrome browser suite 299 passed. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
209 lines
8.2 KiB
CSS
209 lines
8.2 KiB
CSS
/*
|
|
* <x-scaffold>: M3's scaffold — bars, then rails, then panes (docs/reference/m3/foundations.md
|
|
* § Layout → Scaffold) — as a column: an optional `banner` full width, a row below it holding the
|
|
* adaptive navigation rail and the content region, the bottom navigation bar on a compact window,
|
|
* and the snackbar host.
|
|
*
|
|
* `--material-margin` is M3's window margin, which the content region pads itself with and an
|
|
* application's own rules can read: 16px below `medium`, 24px from it
|
|
* (docs/reference/m3/foundations-supplement.md § Breakpoints), the same two spacing tokens
|
|
* layout/pane.css draws its own margin from. `--md-layout-margin: 0px` on the region tells a pane
|
|
* or canonical layout inside that the margin is already drawn.
|
|
*
|
|
* `[data-md-skip-link]` hides the way `md-visually-hidden` does at rest (text.css) — duplicated
|
|
* here rather than shared, because a class cannot be un-applied on `:focus` — and reveals itself
|
|
* fixed at the window's leading corner, clear of a safe area an application sets, in M3's pill
|
|
* shape and label-large type, with the elevation-3 shadow every temporary surface above the page
|
|
* takes.
|
|
*
|
|
* `[data-md-scaffold-row]` is flex from `medium` only (the width the rail joins the layout at
|
|
* instead of sliding over it as a modal) but always takes the remaining height, whichever it is;
|
|
* `[data-md-scaffold-content]` — the rail's sibling — is always a flex column, so the page's own
|
|
* bar, the FAB wrapper and `<main>` stack regardless of the row's own display.
|
|
*
|
|
* `[data-md-scaffold-actions]`'s column layout comes from a container style query on
|
|
* `--md-navigation-rail-value: collapsed`: the actions row is always inside a rail, never the rail
|
|
* element itself, so it reads that property with `@container style()` like any other application
|
|
* content does (`resources/css/components/navigation-rail.css`), rather than copying the rail's
|
|
* own conditions.
|
|
*
|
|
* `[data-md-scaffold-bar]` pins the navigation bar to the window's bottom edge below `medium`, at
|
|
* z-index 30: over the page, under the rail's scrim (40) and the snackbar (50, toast.css). While a
|
|
* bar is there, the scaffold's root publishes `--material-bottom-bar` below `medium` — the bar's
|
|
* 64px or, tall, 80px (`NavigationBarTokens.ContainerHeight` and `TallContainerHeight`, the bar's
|
|
* own dimensions rather than the spacing scale), the bottom safe area and `--material-bottom-extra`
|
|
* — which everything the bar would otherwise cover reads: the FAB (below), the snackbar host
|
|
* (toast.css), a placed toolbar (toolbar.css) and the content region's bottom padding. Without a
|
|
* bar, or from `medium`, the scaffold publishes nothing and each reader falls back to 0px. A bar that has slid
|
|
* away on scroll drops its own height from the variable (navigation-bar.css); that rule wins
|
|
* because `material.components` comes after this file's `material.layout` in the cascade.
|
|
*
|
|
* The content region's `<main>` is matched as the content wrapper's own child, so a `<main>` an
|
|
* application nests inside the page takes none of the region's padding or clipping.
|
|
*
|
|
* Imports the stylesheets of every component this view renders: the adaptive rail and its item and
|
|
* section, the navigation bar and its item, and the snackbar host.
|
|
*
|
|
* In `material.layout`.
|
|
*/
|
|
|
|
@layer material.reset, material.tokens, material.base, material.layout, material.components, material.text, material.visibility;
|
|
|
|
@import './visibility.css';
|
|
@import '../components/navigation-rail.css';
|
|
@import '../components/navigation-rail-item.css';
|
|
@import '../components/navigation-rail-section.css';
|
|
@import '../components/navigation-bar.css';
|
|
@import '../components/navigation-bar-item.css';
|
|
@import '../components/toast.css';
|
|
|
|
@layer material.layout {
|
|
[data-md-scaffold] {
|
|
--material-margin: var(--md-sys-measurement-space200);
|
|
|
|
display: flex;
|
|
min-block-size: 100dvh;
|
|
flex-direction: column;
|
|
background-color: var(--md-sys-color-surface);
|
|
color: var(--md-sys-color-on-surface);
|
|
|
|
@media (width >= 600px) {
|
|
--material-margin: var(--md-sys-measurement-space300);
|
|
}
|
|
}
|
|
|
|
[data-md-skip-link] {
|
|
position: absolute;
|
|
inline-size: 1px;
|
|
block-size: 1px;
|
|
padding: 0;
|
|
margin: -1px;
|
|
overflow: hidden;
|
|
clip-path: inset(50%);
|
|
white-space: nowrap;
|
|
border-width: 0;
|
|
|
|
&:focus {
|
|
position: fixed;
|
|
z-index: 60;
|
|
inset-inline-start: var(--md-sys-measurement-space200);
|
|
top: calc(var(--material-safe-top, env(safe-area-inset-top)) + var(--md-sys-measurement-space200));
|
|
inline-size: auto;
|
|
block-size: auto;
|
|
padding: var(--md-sys-measurement-space100) var(--md-sys-measurement-space200);
|
|
margin: 0;
|
|
overflow: visible;
|
|
clip-path: none;
|
|
white-space: normal;
|
|
border-radius: var(--md-sys-shape-corner-full);
|
|
background-color: var(--md-sys-color-inverse-surface);
|
|
color: var(--md-sys-color-inverse-on-surface);
|
|
font: var(--md-sys-typescale-label-lg);
|
|
letter-spacing: var(--md-sys-typescale-label-lg-tracking);
|
|
font-variation-settings: normal;
|
|
box-shadow: var(--md-sys-elevation-3);
|
|
outline: none;
|
|
}
|
|
}
|
|
|
|
[data-md-scaffold-banner] {
|
|
flex-shrink: 0;
|
|
}
|
|
|
|
[data-md-scaffold-row] {
|
|
flex: 1 1 0%;
|
|
|
|
@media (width >= 600px) {
|
|
display: flex;
|
|
}
|
|
}
|
|
|
|
[data-md-scaffold-content] {
|
|
display: flex;
|
|
min-inline-size: 0;
|
|
flex: 1 1 0%;
|
|
flex-direction: column;
|
|
}
|
|
|
|
[data-md-scaffold-actions] {
|
|
display: flex;
|
|
align-items: center;
|
|
gap: var(--md-sys-measurement-space50);
|
|
padding-block-start: var(--md-sys-measurement-space100);
|
|
padding-inline: 20px;
|
|
|
|
@container style(--md-navigation-rail-value: collapsed) {
|
|
flex-direction: column;
|
|
}
|
|
}
|
|
|
|
[data-md-scaffold-content] > main {
|
|
--md-layout-margin: 0px;
|
|
|
|
min-inline-size: 0;
|
|
flex: 1 1 0%;
|
|
padding-inline: var(--material-margin);
|
|
outline: none;
|
|
|
|
@media (width < 840px) {
|
|
overflow-x: clip;
|
|
}
|
|
|
|
@media (width < 600px) {
|
|
padding-block-end: var(--material-bottom-bar);
|
|
}
|
|
}
|
|
|
|
[data-md-scaffold-bar] {
|
|
position: fixed;
|
|
z-index: 30;
|
|
inset-inline: 0;
|
|
inset-block-end: 0;
|
|
|
|
@media (width >= 600px) {
|
|
display: none;
|
|
}
|
|
}
|
|
|
|
[data-md-scaffold]:has(> [data-md-scaffold-bar] [data-md-navigation-bar]:not([data-md-tall])) {
|
|
@media (width < 600px) {
|
|
--material-bottom-bar: calc(64px + var(--material-safe-bottom, env(safe-area-inset-bottom)) + var(--material-bottom-extra, 0px));
|
|
}
|
|
}
|
|
|
|
[data-md-scaffold]:has(> [data-md-scaffold-bar] [data-md-navigation-bar][data-md-tall]) {
|
|
@media (width < 600px) {
|
|
--material-bottom-bar: calc(80px + var(--material-safe-bottom, env(safe-area-inset-bottom)) + var(--material-bottom-extra, 0px));
|
|
}
|
|
}
|
|
|
|
[data-md-scaffold-fab] {
|
|
--md-scaffold-fab-margin: var(--md-sys-measurement-space200);
|
|
|
|
position: fixed;
|
|
z-index: 30;
|
|
inset-inline-end: max(
|
|
var(--md-scaffold-fab-margin),
|
|
var(--material-safe-right, env(safe-area-inset-right))
|
|
);
|
|
inset-block-end: calc(
|
|
max(var(--material-bottom-bar, 0px), var(--material-safe-bottom, env(safe-area-inset-bottom)))
|
|
+ var(--md-scaffold-fab-margin)
|
|
+ var(--material-snackbar-height, 0px)
|
|
+ min(var(--material-snackbar-height, 0px), var(--md-sys-measurement-space200))
|
|
);
|
|
transition: inset-block-end var(--md-sys-motion-spatial-default-duration) var(--md-sys-motion-spatial-default);
|
|
|
|
@media (width >= 600px) {
|
|
--md-scaffold-fab-margin: var(--md-sys-measurement-space300);
|
|
}
|
|
}
|
|
|
|
[data-md-scaffold-fab]:is([dir='rtl'], [dir='rtl'] *) {
|
|
inset-inline-end: max(
|
|
var(--md-scaffold-fab-margin),
|
|
var(--material-safe-left, env(safe-area-inset-left))
|
|
);
|
|
}
|
|
}
|