Take Tailwind out of the package, and its detection out of the guard
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>
This commit is contained in:
Andreas Reinhold / reini
2026-09-17 21:07:39 +02:00
co-authored by Claude Opus 5
parent 247c596c3a
commit fb7007c976
88 changed files with 649 additions and 1521 deletions
+1 -1
View File
@@ -1,7 +1,7 @@
@verbatim
## Livewire Material
This application uses `nonameweb/livewire-material`: Material 3 Expressive components for Laravel and Livewire, in plain CSS. It replaces UI kits such as maryUI, daisyUI and Flux, and Tailwind CSS, in this application.
This application uses `nonameweb/livewire-material`: Material 3 Expressive components for Laravel and Livewire, in plain CSS. No utility classes Tailwind, daisyUI or any other belong here: a class your CSS does not declare does nothing, and `DesignGuard` fails it.
- Components are anonymous Blade components, unprefixed unless `config/livewire-material.php` sets a `prefix`. Before writing or changing a view that uses them, activate the `livewire-material-development` skill for the props, slots and traps of each component.
- The CSS entry imports `foundation.css` first, then the stylesheet of each component the views render (or `all.css` for all of them). A component whose stylesheet is not imported renders unstyled; `DesignGuard::missingStylesheets()` names each missing `@import`.
@@ -3,7 +3,7 @@
Every view in this application is Material 3 Expressive (m3.material.io), through `nonameweb/livewire-material`. These rules decide what to write; the `material-3-design` skill carries the tables, the numbers and Google's source pages behind each one — activate it before designing a screen.
The library is plain CSS on M3's tokens, and there are no utility classes: a Tailwind class, one of the library's 1.x utilities (bg-primary, type-body-md, medium:hidden) or a daisyUI class compiles to nothing, and so does a maryUI tag. A view is written three ways:
The library is plain CSS on M3's tokens. No utility classes Tailwind, daisyUI or any other belong here: a class your CSS does not declare does nothing, and `DesignGuard` fails it. A view is written three ways:
- Components and their props: `<x-button variant="filled">`, and the layout components `<x-row>`, `<x-stack>`, `<x-grid>`, `<x-feed>`, `<x-surface>` and `<x-pane>`, whose `gap` and `padding` take a spacing token (`space200`) and whose `hide-below`, `hide-from` and `stack-below` take a window size class.
- A fixed set of classes for text and interaction on plain elements: `md-type-*`, `md-ink-*`, `md-text-*`, `md-truncate`, `md-tabular`, `md-visually-hidden`, `md-state-layer`, `md-focus-ring`, `md-touch-target` and `md-link`.
- The application's own CSS, named by the application, whose values are `--md-sys-*` custom properties.
@@ -90,7 +90,7 @@ Scheme::resolveProfileUsing(fn (): ?string => Setting::get('color_profile'));
## Tokens
2.0.0's vocabulary is plain CSS. There are no utility classes: a Tailwind class, or one of 1.x's own colour, type, shape, elevation, motion or breakpoint utilities, compiles to nothing, and the design guard names the replacement for each (see Testing the design). `resources/css/foundation.css` is the one required import, first in the entry, followed by the stylesheets of the components the views render (see Setup; 1.x's `material.css` shortcut is gone). It declares the layer order `material.reset, material.tokens, material.base, material.layout, material.components, material.text, material.visibility`, so an application's unlayered CSS beats every package rule, and `hidden` or `x-cloak` hides any element. It brings the reset, the page's `surface` and `on-surface` in the brand typeface smoothed in grayscale (drop Tailwind's `antialiased`), every `--md-sys-*` token, and the classes below. An application's views reach for four things, in this order:
2.0.0's vocabulary is plain CSS. There are no utility classes: one of 1.x's own colour, type, shape, elevation, motion or breakpoint utilities, or any other class no stylesheet declares, compiles to nothing, and the design guard fails on it (see Testing the design). `resources/css/foundation.css` is the one required import, first in the entry, followed by the stylesheets of the components the views render (see Setup; 1.x's `material.css` shortcut is gone). It declares the layer order `material.reset, material.tokens, material.base, material.layout, material.components, material.text, material.visibility`, so an application's unlayered CSS beats every package rule, and `hidden` or `x-cloak` hides any element. It brings the reset, the page's `surface` and `on-surface` in the brand typeface smoothed in grayscale, every `--md-sys-*` token, and the classes below. An application's views reach for four things, in this order:
- **A component's own props** — `color`, `variant`, `size`, `dense` — before anything else.
- **Layout components** for arrangement and spacing: `<x-row>`, `<x-stack>`, `<x-grid>`, `<x-feed>`, `<x-surface>` inside `<x-pane>`s (see Layout), with `gap` and `padding` as spacing tokens (`space25``space900`, 272px) and `hide-below`, `hide-from` and `stack-below` for the window size classes. Nothing arranges by class.
@@ -1164,7 +1164,7 @@ A data table: write plain `<thead>`, `<tr>`, `<th>`, `<td>` inside `<x-table>`;
{{ $shares->links() }}
```
Pagination: `$paginator->links()` (Laravel and Livewire, full and simple/cursor) is drawn in M3 — current page in secondary-container, "Page 2 of 7" on a phone. Turn off with `config('livewire-material.pagination')` = `false`; published `vendor/pagination` or `vendor/livewire` views still win.
Pagination: `$paginator->links()` (Laravel and Livewire, full and simple/cursor) is drawn in M3 — current page in secondary-container, "Page 2 of 7" on a phone. Turn off with `config('livewire-material.pagination')` = `false`; published `vendor/pagination` or `vendor/livewire` views still win. The provider also sets `livewire.pagination_theme` to `material` whenever it still reads as Livewire's own default (`tailwind`); an application's own theme, or a component's `$paginationTheme` property or `paginationView()` method, still wins.
## Testing the design
@@ -1180,13 +1180,13 @@ it('uses only what compiles', function () {
});
```
It reads every path it is given and fails with `path:line` on unknown symbol names, Blade directives written inside a component tag (where they do not compile), and every Tailwind utility or variant — none compiles in a Tailwind-free application — each match printed beside its own 2.0.0 replacement (a layout component and prop, an `md-*` class, a `var(--md-sys-…)` token, or your own CSS), so run the check and read its output rather than a table here. A class the application's own stylesheets declare is exempt, and so is every `md-*` class.
It reads every path it is given and fails with `path:line` on unknown symbol names, Blade directives written inside a component tag (where they do not compile), and a class no stylesheet declares — not your own CSS, not the package's `md-*` — whatever it came from: a leftover utility, a typo, a class whose rule was deleted. Without a `.css` file among the scanned paths or a `missingStylesheets()` entry to supply your import graph, it has no declared class to compare against and reports every one of them.
In the `.css` files it is given (`material-scheme.css` skipped) it fails on a literal colour, radius, shadow, font, font size, weight, line height, letter spacing, easing or duration, and on a media query width off 600/840/1200/1600px; a `var()`, or a `calc()`/`min()`/`max()`/`clamp()` built on one, is fine.
Markdown mail components — whatever lies under `config('mail.markdown.paths')`, `resources/views/vendor/mail` by default — are drawn by the mail theme, not by your CSS entry, and its classes (`table`, `button`, `panel`, `break-all`) share Tailwind's names. So the guard skips the class checks there (it still reads their icon names, the directives in their component tags and your own bans), and a mail theme stylesheet under that path, which has to write literal values, is neither checked for literals nor a source of exempt classes.
Markdown mail components — whatever lies under `config('mail.markdown.paths')`, `resources/views/vendor/mail` by default — are drawn by the mail theme, not by your CSS entry. So the guard skips the class check there (it still reads their icon names, the directives in their component tags and your own bans), and a mail theme stylesheet under that path, which has to write literal values, is neither checked for literals nor a source of declared classes.
`missingStylesheets($cssEntry)` follows the entry's relative `@import`s through every package file's own imports (`split-button.css` counts `button.css` and `menu.css` too; `tailwindcss` or a font URL is skipped) and checks them against the package tags a scanned view renders (plain, prefixed or `<x-livewire-material::…>`), `->links()`, and a row a view of yours writes by hand (`data-md-list-row` on anything but `<x-card>`, which needs `components/list-item.css`; the package's own views are not read for it); each missing stylesheet names its `@import` line once, and a tag the application shadows with its own component is reported instead — the application's component wins in Blade. It reads imports only: leave `resource_path('css')` out of `scan()` until the stylesheets are on tokens. `unusedStylesheets($cssEntry)` is the other way round: a package stylesheet the entry imports directly that no scanned view needs — no tag, `->links()` or row written by hand — even through a needed stylesheet's own imports, named at its `@import` line to remove (an entry importing `all.css` is left alone). `forbidColours([...])` fails wherever a left-out role (with its `on-` and container roles) is still written: `var(--md-sys-color-…)` in CSS or an inline `style`, its `md-ink-*` class, or a component's `color`/`tone` prop. `forbid($pattern, $reason)` adds a pattern of your own.
`missingStylesheets($cssEntry)` follows the entry's relative `@import`s through every package file's own imports (`split-button.css` counts `button.css` and `menu.css` too; a package name or a font URL is skipped) and checks them against the package tags a scanned view renders (plain, prefixed or `<x-livewire-material::…>`), `->links()`, and a row a view of yours writes by hand (`data-md-list-row` on anything but `<x-card>`, which needs `components/list-item.css`; the package's own views are not read for it); each missing stylesheet names its `@import` line once, and a tag the application shadows with its own component is reported instead — the application's component wins in Blade. It reads imports only: leave `resource_path('css')` out of `scan()` until the stylesheets are on tokens, as long as this entry is what `missingStylesheets()` reads — its import graph is still what supplies the declared classes above. `unusedStylesheets($cssEntry)` is the other way round: a package stylesheet the entry imports directly that no scanned view needs — no tag, `->links()` or row written by hand — even through a needed stylesheet's own imports, named at its `@import` line to remove (an entry importing `all.css` is left alone). `forbidColours([...])` fails wherever a left-out role (with its `on-` and container roles) is still written: `var(--md-sys-color-…)` in CSS or an inline `style`, its `md-ink-*` class, or a component's `color`/`tone` prop. `forbid($pattern, $reason)` adds a pattern of your own.
## Conventions
+3 -3
View File
@@ -1,9 +1,9 @@
/*
* Livewire Material for an application that wants everything: the foundation, every layout
* stylesheet and every component stylesheet, each imported once. The blocks below are the same
* groups `components.css` and `layout.css` used before this file replaced both of them (plan step
* 37) one block per group, so a stylesheet still lands in a predictable place plus the
* Layout block those two files didn't share.
* groups `components.css` and `layout.css` used before this file replaced both of them one
* block per group, so a stylesheet still lands in a predictable place plus the Layout block
* those two files didn't share.
*
* This is not the recommended way to bring the package's CSS in: importing `all.css` pulls in
* every component's rules whether an application's views render them or not. The recommended path
+4 -4
View File
@@ -20,10 +20,10 @@
* The page carries this file itself: `src/Support/ErrorPage.php` inlines it, with its imports, into
* every error page (`Stylesheets::bundle()`) beside the application's Vite tags when there is a
* build (`layoutStyles()`), inside the whole fallback stylesheet when there is none
* (`fallbackStyles()`, plan step 40) so an application imports nothing for its error pages
* (plan step 46). The body is still matched only when it holds the layout
* (`body:has(> [data-md-error-page])`): an application that imports `all.css` has this file in
* its bundle beside every other page, where a bare `body` rule would restyle them all.
* (`fallbackStyles()`) so an application imports nothing for its error pages. The body is still
* matched only when it holds the layout (`body:has(> [data-md-error-page])`): an application that
* imports `all.css` has this file in its bundle beside every other page, where a bare `body` rule
* would restyle them all.
*
* The page's font is the foundation's, `--md-ref-typeface-brand` on `html` (foundation/base.css),
* as the old `font-sans` was; only the fallback, which has no `@font-face`, uses a system stack.
+5 -8
View File
@@ -78,14 +78,11 @@
* A bar that has slid off the bottom of the window is no longer there to clear, so the offset
* everything pinned to the bottom reads drops to the bottom safe area and whatever the
* application has docked on the bar a `fab` button, the snackbar and the page's own bottom
* padding all follow it down and come back up with it. Layered now, unlike before this
* rewrite: <x-scaffold> used to publish --material-bottom-bar with a Tailwind utility, which
* no rule in any layer could outrank regardless of specificity; now scaffold.css publishes it
* itself in `material.layout` (layout/scaffold.css), a layer this file's own
* `material.components` always outranks by declaration order alone the same reason
* toolbar.css's and fab.css's overrides only have to beat another `material.components` rule,
* not chase a Tailwind utility out of the cascade. Keyed on `data-md-scaffold`, the hook the
* scaffold renders on its root, not `data-app-shell`, which that rewrite also retired.
* padding all follow it down and come back up with it. `<x-scaffold>` publishes
* `--material-bottom-bar` itself, in `material.layout` (layout/scaffold.css), a layer this
* file's own `material.components` always outranks by declaration order alone the same
* reason toolbar.css's and fab.css's overrides only have to beat another `material.components`
* rule. Keyed on `data-md-scaffold`, the hook the scaffold renders on its root.
*/
[data-md-scaffold]:has([data-md-navigation-bar][data-md-hide-on-scroll][data-md-hidden]) {
--material-bottom-bar: calc(var(--material-safe-bottom, env(safe-area-inset-bottom)) + var(--material-bottom-extra, 0px));
+4 -3
View File
@@ -1,7 +1,8 @@
/*
* The paginators, Laravel's and Livewire's, drawn in M3 (resources/views/pagination/**): the package
* puts its views in front of the frameworks' `tailwind` and `simple-tailwind` ones, whose names they
* keep.
* The paginators, Laravel's and Livewire's, drawn in M3 (resources/views/pagination/**): named
* `material`/`simple-material`, put in front of the frameworks' own namespaces and set as
* Laravel's default view (`Paginator::defaultView()`/`defaultSimpleView()`) and, where Livewire
* still reads its own default, as its `pagination_theme`.
*
* The numbered paginator is a row: on its start, what the page holds in body-small on-surface-variant
* "2130 of 95", or "Page 3 of 10" below `medium` (600px), where the page numbers give way and only
-4
View File
@@ -24,10 +24,6 @@
* therefore outranks every package rule, whatever the selector an application's broad selector
* (`button { }`) restyles the components too. foundation/hidden.css keeps its two `!important`
* rules outside the layers, so `hidden` and `x-cloak` hide an element whatever sets its display.
*
* An application still building Tailwind keeps it in a separate entry and opens both entries with
* `@layer properties, theme, base, material, components, utilities;`, so the `material` layers sit
* above Tailwind's preflight and below its utilities.
*/
@layer material.reset, material.tokens, material.base, material.layout, material.components, material.text, material.visibility;
+1 -1
View File
@@ -11,7 +11,7 @@
* Text is smoothed in grayscale where a platform offers the choice (macOS browsers): Google Sans
* Flex is drawn for it, and subpixel smoothing thickens its strokes on light text over a dark
* surface. Every surface the package draws the showcase, the error pages is set this way,
* and so is an application, which drops Tailwind's `antialiased` class with nothing to replace.
* and so is an application, with no class of its own needed.
*
* In `material.base`, above the reset and below every component and text class.
*/
+4 -4
View File
@@ -2,10 +2,10 @@
* The reset: what a browser draws before any stylesheet, taken back to a clean start.
*
* Rule for rule the reset the components were built on, Tailwind CSS 4's preflight (MIT,
* © Tailwind Labs, after modern-normalize), so a component looks the same whether an application
* still builds Tailwind or not: every box `border-box` with a `0 solid` border and no margin or
* padding, headings and lists unstyled, form controls inheriting font, colour and tracking with no
* background or radius, media as blocks that never overflow their parent. Three differences:
* © Tailwind Labs, after modern-normalize): every box `border-box` with a `0 solid` border and no
* margin or padding, headings and lists unstyled, form controls inheriting font, colour and
* tracking with no background or radius, media as blocks that never overflow their parent. Three
* differences:
*
* - no typeface here: foundation/base.css sets `--md-ref-typeface-brand` on <html>;
* - a placeholder is `on-surface-variant`, the colour of M3's text field placeholder (androidx
+1 -1
View File
@@ -21,7 +21,7 @@
* way it goes, so it mirrors in a right-to-left document (§ Layout Bidirectionality / RTL).
*
* In `material.layout`; `hide-below`/`hide-from` come from visibility.css. Imports app-bar.css and
* button.css for the pane's own top app bar and its back button (plan step 36 carry-over).
* button.css for the pane's own top app bar and its back button.
*/
@layer material.reset, material.tokens, material.base, material.layout, material.components, material.text, material.visibility;
+7 -10
View File
@@ -2,9 +2,7 @@
* <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. Plan step 36 (navigation group) moves in everything the view drew with
* Tailwind; `data-md-scaffold-fab` and the content region's `--md-layout-margin` are step 35's,
* unchanged below.
* 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
@@ -23,11 +21,11 @@
* `[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 is `rail-collapsed:flex-col`, the one Tailwind
* variant scaffold.blade.php still used (`resources/css/tailwind.css`, removed with this rule): the
* actions row is always inside a rail, never the rail element itself, so it reads
* `--md-navigation-rail-value` 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-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
@@ -38,8 +36,7 @@
* (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`, where before this
* rewrite the variable was a Tailwind utility and the override had to sit outside every layer.
* 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.
+2 -2
View File
@@ -1,7 +1,7 @@
/*
* The showcase's own chrome: what its pages draw beyond the layout components, the `md-*` text
* classes and the shared interaction classes (plan step 38) the rail's wordmark, the search box
* and its results, a keyboard key in running text, an example's card and its code sample, and the
* classes and the shared interaction classes the rail's wordmark, the search box and its
* results, a keyboard key in running text, an example's card and its code sample, and the
* foundation pages' specimens: a colour swatch, a type-scale row, a corner swatch, an elevation
* tile, a motion track and its dot, an icon search result and the Layout page's breakpoint cards.
*
@@ -1,8 +1,9 @@
{{-- Laravel's paginator (`$items->links()` outside Livewire), drawn in M3 as Livewire's is
(resources/views/pagination/livewire/tailwind.blade.php): links instead of actions, the current
page in secondary-container, "Page 2 of 7" below 600px. The package puts this in front of
`pagination::tailwind` (config `livewire-material.pagination`); the name is Laravel's, the drawing
resources/css/components/pagination.css. --}}
(resources/views/pagination/livewire/material.blade.php): links instead of actions, the
current page in secondary-container, "Page 2 of 7" below 600px. The name is `material`; the
provider replaces Laravel's own default with
`Paginator::defaultView('pagination::material')` (config `livewire-material.pagination`). The
drawing is resources/css/components/pagination.css. --}}
@if ($paginator->hasPages())
<nav role="navigation" aria-label="{{ __('Pagination Navigation') }}" data-md-pagination>
@@ -1,5 +1,6 @@
{{-- Laravel's simple and cursor paginator, drawn in M3: previous and next as outlined buttons
(the package puts this in front of `pagination::simple-tailwind`). --}}
{{-- Laravel's simple and cursor paginator, drawn in M3: previous and next as outlined buttons.
The name is `simple-material`; the provider replaces Laravel's own default with
`Paginator::defaultSimpleView('pagination::simple-material')`. --}}
@if ($paginator->hasPages())
<nav role="navigation" aria-label="{{ __('Pagination Navigation') }}" data-md-pagination>
@@ -1,7 +1,7 @@
{{-- Livewire's paginator, drawn in M3. The package puts this in front of Livewire's own
`livewire::tailwind` (config `livewire-material.pagination`), whose gray and blue classes do
not exist in an M3 theme. The file keeps Livewire's view name; nothing in it is Tailwind the
drawing is resources/css/components/pagination.css.
{{-- Livewire's paginator, drawn in M3. The name is `material`; Livewire resolves
`livewire::` . config('livewire.pagination_theme') to find it, and the provider sets that
config to `material` (config `livewire-material.pagination`) while it still reads as
Livewire's own default. The drawing is resources/css/components/pagination.css.
The wiring is Livewire's, unchanged: `previousPage`, `nextPage` and `gotoPage` with the page
name, and the scroll back to the top of whatever `scrollTo` names. A page number is drawn as a
@@ -1,5 +1,7 @@
{{-- Livewire's simple and cursor paginator, drawn in M3: previous and next as outlined buttons
(the package puts this in front of `livewire::simple-tailwind`). --}}
{{-- Livewire's simple and cursor paginator, drawn in M3: previous and next as outlined buttons.
The name is `simple-material`; Livewire resolves `livewire::simple-` . config
('livewire.pagination_theme') to find it, which the provider sets to `material` while it
still reads as Livewire's own default. --}}
@php
if (! isset($scrollTo)) {
@@ -1,6 +1,6 @@
{{-- The live breakpoint readout: this window's width, and the M3 breakpoint it falls in, read
from the same numbers resources/js/breakpoints.js compares against. Shared by the Layout
section's Overview and its three canonical layout pages (plan step 38). --}}
section's Overview and its three canonical layout pages. --}}
<x-livewire-material::surface
level="surface-container-low"
@@ -1,6 +1,6 @@
{{-- The feed canonical layout on a page of its own (plan step 38): the same working demo the
Layout section's Overview linked from its own navigation, built on the real <x-feed>, with
the live breakpoint readout the Overview page has. --}}
{{-- The feed canonical layout on a page of its own: the same working demo the Layout section's
Overview linked from its own navigation, built on the real <x-feed>, with the live
breakpoint readout the Overview page has. --}}
@extends('livewire-material::showcase.layout')
@@ -1,6 +1,6 @@
{{-- The list-detail canonical layout on a page of its own (plan step 38): the same working demo
the Layout section's Overview linked from its own navigation, built on the real
<x-list-detail>, with the live breakpoint readout the Overview page has. --}}
{{-- The list-detail canonical layout on a page of its own: the same working demo the Layout
section's Overview linked from its own navigation, built on the real <x-list-detail>, with
the live breakpoint readout the Overview page has. --}}
@extends('livewire-material::showcase.layout')
@@ -1,5 +1,5 @@
{{-- The supporting-pane canonical layout on a page of its own (plan step 38): the same working
demo the Layout section's Overview linked from its own navigation, built on the real
{{-- The supporting-pane canonical layout on a page of its own: the same working demo the
Layout section's Overview linked from its own navigation, built on the real
<x-supporting-pane>, with the live breakpoint readout the Overview page has. --}}
@extends('livewire-material::showcase.layout')
@@ -3,8 +3,8 @@
describing them.
Then the layout components, and the way on to the three canonical layouts list-detail,
supporting pane, feed each on a page of its own (plan step 38), reached through the
section navigation below. --}}
supporting pane, feed each on a page of its own, reached through the section navigation
below. --}}
@php
$examples = [