Write the showcase examples without showcase-only hooks

Plan step 38 review: the component sections' code samples, which an
application copies, carried 60 data-md-showcase-* hooks that only
showcase.css draws (a sized loading indicator, the plain badge's own
colours, a bordered bar frame, the navigation demos' frames, a table's
scroll wrapper...), so a copied sample did nothing in the application.
They now write what an application has: <x-surface outlined corner>
for a frame and a line, <x-row> for the FAB menu's corner, and an
inline style from the tokens for a size, a scroll box or a colour,
as the Containment batch already did. The side sheet demo takes
align="stretch", which holds in both of <x-row stack-below>'s modes,
instead of a hook that undid align="start" once stacked. The menu
icon colours go through icon-class with two unlayered application-like
classes, which the sample's comment names, and the fields' and date
picker's widths are inline styles now that style reaches their roots.
The radio hint said "from sm"; it is medium.

showcase.css keeps only the frame and the foundation specimens; its
header describes the file instead of the batches that wrote it. The
tests reject a showcase hook or a class outside md-* and the named
application classes in any example, a showcase.css selector outside
its own hooks, and a hook no showcase view renders.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Qwx5USif3wFFmxtHg5U1g9
This commit is contained in:
Andreas Reinhold / reini
2026-09-15 06:21:18 +02:00
co-authored by Claude Opus 5
parent cd47aa4b0f
commit ebdcdb82b5
15 changed files with 152 additions and 374 deletions
@@ -2,7 +2,7 @@
$examples = [
'Top app bars' => <<<'BLADE'
<x-stack gap="space200" style="width: 100%;">
<div data-md-showcase-bar-frame>
<x-surface corner="lg" outlined style="overflow: hidden;">
<x-app-bar title="Shares" :sticky="false">
<x-slot:navigation><x-button icon="menu" tooltip="Open navigation" /></x-slot:navigation>
<x-slot:actions>
@@ -10,10 +10,10 @@
<x-button icon="filter_list" tooltip="Filter" />
</x-slot:actions>
</x-app-bar>
</div>
</x-surface>
{{-- Resize the window: two icon buttons below 600px, four from there, the rest in "More options". --}}
<div data-md-showcase-bar-frame>
<x-surface corner="lg" outlined style="overflow: hidden;">
<x-app-bar title="holiday-photos" :sticky="false" :actions="[
['label' => 'Share', 'icon' => 'share'],
['label' => 'Download', 'icon' => 'download'],
@@ -23,37 +23,37 @@
]">
<x-slot:navigation><x-button icon="arrow_back" tooltip="Back" /></x-slot:navigation>
</x-app-bar>
</div>
</x-surface>
<div data-md-showcase-bar-frame>
<x-surface corner="lg" outlined style="overflow: hidden;">
<x-app-bar variant="center" title="holiday-photos.zip" subtitle="248 MB · expires in 3 days" :sticky="false">
<x-slot:navigation><x-button icon="arrow_back" tooltip="Back" /></x-slot:navigation>
<x-slot:actions><x-button icon="share" tooltip="Share" /></x-slot:actions>
</x-app-bar>
</div>
</x-surface>
<div data-md-showcase-bar-frame>
<x-surface corner="lg" outlined style="overflow: hidden;">
<x-app-bar variant="medium" title="Recipients" subtitle="3 people" :sticky="false">
<x-slot:navigation><x-button icon="arrow_back" tooltip="Back" /></x-slot:navigation>
<x-slot:actions><x-button icon="person_add" tooltip="Add recipient" /></x-slot:actions>
</x-app-bar>
</div>
</x-surface>
<div data-md-showcase-bar-frame>
<x-surface corner="lg" outlined style="overflow: hidden;">
<x-app-bar variant="large" title="Settings" :sticky="false">
<x-slot:navigation><x-button icon="arrow_back" tooltip="Back" /></x-slot:navigation>
</x-app-bar>
</div>
</x-surface>
<div data-md-showcase-bar-frame="visible">
<x-surface corner="lg" outlined>
<x-app-bar variant="search" :sticky="false" style="border-radius: var(--md-sys-shape-corner-lg);">
<x-slot:navigation><x-button icon="menu" tooltip="Open navigation" /></x-slot:navigation>
<x-search placeholder="Search shares" docked />
<x-slot:actions>
<span data-md-showcase-avatar class="md-type-label-lg">AR</span>
<span class="md-type-label-lg" style="display: grid; place-items: center; width: 32px; height: 32px; border-radius: var(--md-sys-shape-corner-full); background-color: var(--md-sys-color-primary-container); color: var(--md-sys-color-on-primary-container);">AR</span>
</x-slot:actions>
</x-app-bar>
</div>
</x-surface>
</x-stack>
BLADE,
'Toolbars' => <<<'BLADE'
@@ -78,16 +78,16 @@
<x-button icon="zoom_in" tooltip-right="Zoom in" />
</x-toolbar>
<div data-md-showcase-bar-frame>
<x-surface corner="lg" outlined style="width: 100%; overflow: hidden;">
<x-toolbar variant="docked" label="Selection">
<x-button icon="download" tooltip="Download" />
<x-button icon="share" tooltip="Share" />
<x-button icon="drive_file_move" tooltip="Move" />
<x-button icon="delete" tooltip="Delete" />
</x-toolbar>
</div>
</x-surface>
<div data-md-showcase-bar-frame>
<x-surface corner="lg" outlined style="width: 100%; overflow: hidden;">
<x-toolbar variant="docked" label="Editing">
<x-button icon="check_box" tooltip="Select" />
<x-button icon="brush" tooltip="Draw" />
@@ -95,10 +95,10 @@
<x-button icon="image" tooltip="Add image" />
<x-slot:fab><x-fab icon="add" tooltip="New note" color="secondary" /></x-slot:fab>
</x-toolbar>
</div>
</x-surface>
{{-- M3's docked toolbar on a large screen: rounded from 840px, its groups of controls divided. Narrower, it is the square docked bar. --}}
<div data-md-showcase-bar-frame="rounded">
<x-surface level="surface" corner="lg" padding="space200" style="width: 100%;">
<x-toolbar variant="docked" rounded label="Text formatting">
<x-button icon="undo" tooltip="Undo" />
<x-button icon="redo" tooltip="Redo" />
@@ -108,7 +108,7 @@
<x-divider vertical />
<x-button icon="link" tooltip="Insert link" />
</x-toolbar>
</div>
</x-surface>
</x-row>
BLADE,
'Primary tabs' => <<<'BLADE'
@@ -134,7 +134,7 @@
<x-tab name="billing">Plan and invoices.</x-tab>
</x-tabs>
<div data-md-showcase-tabs-narrow>
<div style="max-width: 384px;">
<x-tabs scrollable :tabs="collect(['January', 'February', 'March', 'April', 'May', 'June', 'July'])->map(fn ($month) => ['name' => strtolower($month), 'label' => $month])->all()">
<x-tab name="january">January's shares.</x-tab>
</x-tabs>
@@ -60,8 +60,8 @@
'Loading indicator' => <<<'BLADE'
<x-loading />
<x-loading contained />
<x-loading data-md-showcase-loading="lg" label="Uploading" />
<x-loading contained data-md-showcase-loading="sm" />
<x-loading label="Uploading" style="width: 96px; height: 96px; color: var(--md-sys-color-tertiary);" />
<x-loading contained style="width: 32px; height: 32px;" />
BLADE,
'Button groups: standard (press a button) and connected' => <<<'BLADE'
<x-button-group label="Standard" size="md">
@@ -161,13 +161,13 @@
<x-fab icon="add" label="New share" size="lg" color="tertiary" collapse-on-scroll />
BLADE,
'FAB menu' => <<<'BLADE'
<div data-md-showcase-fab-menu-demo>
<x-row justify="end" align="end" style="width: 100%; height: 288px;">
<x-fab-menu label="New">
<x-fab-menu-item label="Upload files" icon="upload_file" />
<x-fab-menu-item label="Upload a folder" icon="drive_folder_upload" />
<x-fab-menu-item label="Paste text" icon="content_paste" />
</x-fab-menu>
</div>
</x-row>
BLADE,
];
@endphp
@@ -13,7 +13,7 @@
['Heart', 'heart', 'background-color: var(--md-sys-color-inverse-surface); color: var(--md-sys-color-inverse-primary);'],
] as [$name, $shape, $colours])
<x-carousel-item :label="$name">
<div data-md-showcase-carousel-swatch style="{{ $colours }}">
<div style="display: grid; place-items: center; width: 100%; height: 100%; {{ $colours }}">
<x-shape :name="$shape" size="144" />
</div>
</x-carousel-item>
@@ -30,7 +30,7 @@
['Ghost', 'ghostish', 'background-color: var(--md-sys-color-primary); color: var(--md-sys-color-on-primary);'],
] as [$name, $shape, $colours])
<x-carousel-item :label="$name">
<div data-md-showcase-carousel-swatch style="{{ $colours }}">
<div style="display: grid; place-items: center; width: 100%; height: 100%; {{ $colours }}">
<x-shape :name="$shape" size="192" />
</div>
</x-carousel-item>
@@ -48,7 +48,7 @@
['oval', 'background-color: var(--md-sys-color-primary); color: var(--md-sys-color-on-primary);'],
] as [$shape, $colours])
<x-carousel-item>
<div data-md-showcase-carousel-swatch style="{{ $colours }}">
<div style="display: grid; place-items: center; width: 100%; height: 100%; {{ $colours }}">
<x-shape :name="$shape" size="96" />
</div>
</x-carousel-item>
@@ -66,7 +66,7 @@
['16/9', 'very-sunny', 'background-color: var(--md-sys-color-secondary); color: var(--md-sys-color-on-secondary);'],
] as [$aspect, $shape, $colours])
<x-carousel-item :aspect="$aspect" :label="$aspect">
<div data-md-showcase-carousel-swatch style="{{ $colours }}">
<div style="display: grid; place-items: center; width: 100%; height: 100%; {{ $colours }}">
<x-shape :name="$shape" size="80" />
</div>
</x-carousel-item>
@@ -81,7 +81,7 @@
['Night', 'puffy-diamond', 'background: linear-gradient(to bottom right, var(--md-sys-color-inverse-surface), var(--md-sys-color-primary)); color: var(--md-sys-color-inverse-primary);'],
] as [$name, $shape, $colours])
<x-carousel-item :label="$name">
<div data-md-showcase-carousel-swatch style="{{ $colours }}">
<div style="display: grid; place-items: center; width: 100%; height: 100%; {{ $colours }}">
<x-shape :name="$shape" size="160" />
</div>
</x-carousel-item>
@@ -53,7 +53,7 @@
BLADE,
'A set that scrolls' => <<<'BLADE'
{{-- M3 asks an overflowing chip row for a visible affordance: the edge it can still scroll towards fades, and on a mouse a button sits over it. --}}
<div data-md-showcase-chip-scroll>
<div style="width: 100%; max-width: 384px;">
<x-chip-set label="Sort and filter" hint="Drag, or use the arrow keys" scroll>
<x-chip type="filter" label="Newest" name="sort[]" value="newest" :selected="true" />
<x-chip type="filter" label="Largest" name="sort[]" value="largest" />
@@ -13,7 +13,7 @@
<x-badge value="Archived" color="neutral" outline />
<span style="position: relative; display: inline-flex"><x-icon name="chat" /><x-badge value="2" color="neutral" floating /></span>
<x-badge tonal color="tertiary"><x-icon name="bolt" filled optical="20" size="12" /> Pro</x-badge>
<x-badge value="Beta" tonal color="plain" data-md-showcase-badge-plain />
<x-badge value="Beta" tonal color="plain" style="background-color: var(--md-sys-color-primary-fixed); color: var(--md-sys-color-on-primary-fixed);" />
BLADE,
'Snackbars' => <<<'BLADE'
<x-row gap="space200" wrap align="center" x-data>
@@ -33,7 +33,7 @@
<p class="md-type-body-md md-ink-variant">
A description makes the snackbar 68px, M3's two-line height; below <code>medium</code> the action wraps under the text.
Press <kbd class="md-type-label-md" data-md-showcase-kbd>Alt</kbd>&nbsp;+&nbsp;<kbd class="md-type-label-md" data-md-showcase-kbd>G</kbd> to move the focus to a snackbar that has an action.
Press <kbd class="md-type-label-md" style="border-radius: var(--md-sys-shape-corner-xs); background-color: var(--md-sys-color-surface-container-highest); padding: 0 var(--md-sys-measurement-space75);">Alt</kbd>&nbsp;+&nbsp;<kbd class="md-type-label-md" style="border-radius: var(--md-sys-shape-corner-xs); background-color: var(--md-sys-color-surface-container-highest); padding: 0 var(--md-sys-measurement-space75);">G</kbd> to move the focus to a snackbar that has an action.
</p>
</x-stack>
BLADE,
@@ -41,7 +41,7 @@
<x-button icon="content_copy" tooltip="Copy link" />
<x-button icon="qr_code_2" tooltip-bottom="Show QR code" />
<x-tooltip text="Expires in 3 days" side="right">
<span tabindex="0" class="md-type-body-md md-ink-variant md-focus-ring" data-md-showcase-focus-demo>holiday-photos.zip</span>
<span tabindex="0" class="md-type-body-md md-ink-variant md-focus-ring" style="border-radius: var(--md-sys-shape-corner-xs);">holiday-photos.zip</span>
</x-tooltip>
BLADE,
'Rich tooltips' => <<<'BLADE'
@@ -89,11 +89,11 @@
<x-empty-state title="No routes yet" description="Draw a route on the map, or import one from a GPX file.">
<x-slot:illustration style="color: var(--md-sys-color-primary)">
<svg style="width: 128px; height: 128px" viewBox="0 0 120 120" fill="none" aria-hidden="true">
<circle cx="60" cy="60" r="56" data-md-showcase-illustration="container" />
<circle cx="60" cy="60" r="56" style="fill: var(--md-sys-color-primary-container)" />
<path d="M28 86C40 62 56 92 68 64S86 42 90 46" stroke="currentColor" stroke-width="5" stroke-linecap="round" stroke-dasharray="1 10" />
<circle cx="28" cy="86" r="7" fill="currentColor" />
<path d="M90 18a12 12 0 0 1 12 12c0 10-12 22-12 22S78 40 78 30a12 12 0 0 1 12-12Z" data-md-showcase-illustration="accent" />
<circle cx="90" cy="30" r="4" data-md-showcase-illustration="on-accent" />
<path d="M90 18a12 12 0 0 1 12 12c0 10-12 22-12 22S78 40 78 30a12 12 0 0 1 12-12Z" style="fill: var(--md-sys-color-tertiary)" />
<circle cx="90" cy="30" r="4" style="fill: var(--md-sys-color-on-tertiary)" />
</svg>
</x-slot:illustration>
<x-slot:actions>
@@ -188,7 +188,7 @@
</div>
BLADE,
'A standard side sheet: co-planar from expanded, modal below' => <<<'BLADE'
<x-row data-md-showcase-side-sheet-demo align="start" gap="space300" stack-below="expanded" x-data="{ open: true }">
<x-row align="stretch" gap="space300" stack-below="expanded" x-data="{ open: true }">
<x-stack gap="space200" style="flex: 1 1 0%; min-width: 0;">
<x-button label="Show or hide the filters" variant="tonal" x-on:click="open = ! open" />
<p class="md-type-body-md md-ink-variant">
@@ -1,7 +1,7 @@
@php
$examples = [
'Data table' => <<<'BLADE'
<div data-md-showcase-table-scroll>
<div style="width: 100%; overflow-x: auto;">
<x-table>
<thead>
<tr>
@@ -35,8 +35,8 @@
<input id="showcase-error-filled" data-md-field-control value="2020-01-01" aria-invalid="true" />
</x-field>
<x-row gap="space125" wrap align="center">
<x-input size="sm" icon="search" placeholder="Filter" aria-label="Filter" class="showcase-w-sm" />
<x-input size="xs" placeholder="Find" aria-label="Find" class="showcase-w-xs" />
<x-input size="sm" icon="search" placeholder="Filter" aria-label="Filter" style="width: 192px;" />
<x-input size="xs" placeholder="Find" aria-label="Find" style="width: 144px;" />
</x-row>
</x-stack>
</x-grid>
@@ -94,9 +94,9 @@
BLADE,
'A checkbox group at expanded' => <<<'BLADE'
{{-- M3: from expanded (840px), gather related checkboxes into a contained region instead of one long column. --}}
<x-card variant="outlined" data-md-showcase-demo-card data-md-showcase-size="lg">
<x-card variant="outlined" style="width: 100%; max-width: 672px;">
<fieldset>
<legend class="md-type-title-sm md-ink" data-md-showcase-legend>Tell me about</legend>
<legend class="md-type-title-sm md-ink" style="margin-bottom: var(--md-sys-measurement-space200);">Tell me about</legend>
<x-grid :columns="['compact' => 1, 'expanded' => 2]" gap="space200">
<x-checkbox label="Downloads" name="notify[]" value="downloads" checked />
@@ -112,7 +112,7 @@
'Radio buttons' => <<<'BLADE'
<x-grid :columns="['compact' => 1, 'medium' => 2]" gap="space300">
<x-radio label="Who can open the link" name="showcase-audience" value="password" :options="[['id' => 'anyone', 'name' => 'Anyone with the link'], ['id' => 'password', 'name' => 'Anyone with the password', 'hint' => 'Share the password separately'], ['id' => 'team', 'name' => 'My team only', 'disabled' => true]]" />
<x-radio label="Theme" name="showcase-radio-theme" value="system" inline :options="[['id' => 'light', 'name' => 'Light'], ['id' => 'dark', 'name' => 'Dark'], ['id' => 'system', 'name' => 'System']]" hint="Inline from sm" />
<x-radio label="Theme" name="showcase-radio-theme" value="system" inline :options="[['id' => 'light', 'name' => 'Light'], ['id' => 'dark', 'name' => 'Dark'], ['id' => 'system', 'name' => 'System']]" hint="Inline from medium" />
</x-grid>
BLADE,
'Switches' => <<<'BLADE'
@@ -156,7 +156,7 @@
<x-list-item title="design-review.mp4" description="3.4 GB · 7 days left" icon="movie" link="#fields" x-show="'design-review.mp4'.includes(query.toLowerCase())" />
</x-list>
<x-slot:trailing>
<span class="md-type-label-lg" data-md-showcase-avatar>AR</span>
<span class="md-type-label-lg" style="display: grid; place-items: center; width: 32px; height: 32px; border-radius: var(--md-sys-shape-corner-full); background-color: var(--md-sys-color-primary-container); color: var(--md-sys-color-on-primary-container);">AR</span>
</x-slot:trailing>
</x-search>
</div>
@@ -189,9 +189,9 @@
</div>
{{-- M3's search icon button: search as a secondary action, expanding into the full-screen view. --}}
<div data-md-showcase-search-bar>
<x-row gap="space100" align="center" style="border-radius: var(--md-sys-shape-corner-full); background-color: var(--md-sys-color-surface-container-high); padding: var(--md-sys-measurement-space50) var(--md-sys-measurement-space100);">
<x-button icon="menu" aria-label="Open the menu" />
<span class="md-type-title-md md-ink" data-md-showcase-search-bar-title>Shares</span>
<span class="md-type-title-md md-ink" style="flex: 1 1 auto;">Shares</span>
<x-search trigger="icon" label="Search shares">
<x-slot:suggestions>
<x-list>
@@ -200,11 +200,11 @@
</x-slot:suggestions>
<x-slot:empty>No shares match.</x-slot:empty>
</x-search>
</div>
</x-row>
</x-grid>
BLADE,
'A form' => <<<'BLADE'
<x-card variant="outlined" data-md-showcase-demo-card data-md-showcase-size="md">
<x-card variant="outlined" style="width: 100%; max-width: 576px;">
<x-form x-on:submit.prevent="materialToast('Share created', { type: 'success' })" separator>
<x-input label="Share name" required />
<x-textarea label="Message for recipients" />
@@ -125,15 +125,16 @@
</x-menu>
BLADE,
'Icons in their own colour' => <<<'BLADE'
{{-- icon-class takes the application's own class, unlayered so it wins over the item's ink: here .showcase-ink-tertiary { color: var(--md-sys-color-tertiary) }. A disabled item's icon stays disabled. --}}
<x-menu label="New plan">
<x-slot:trigger>
<x-button label="New plan" icon="add" variant="filled" />
</x-slot:trigger>
<x-menu-item label="Running" icon="directions_run" data-md-showcase-icon-color="tertiary" />
<x-menu-item label="Cycling" icon="directions_bike" data-md-showcase-icon-color="secondary" />
<x-menu-item label="Running" icon="directions_run" icon-class="showcase-ink-tertiary" />
<x-menu-item label="Cycling" icon="directions_bike" icon-class="showcase-ink-secondary" />
<x-menu-item label="Swimming" icon="pool" icon-class="md-ink-info" />
<x-menu-item label="Rowing" icon="rowing" data-md-showcase-icon-color="tertiary" disabled />
<x-menu-item label="Rowing" icon="rowing" icon-class="showcase-ink-tertiary" disabled />
</x-menu>
BLADE,
];
@@ -4,22 +4,22 @@
<x-stack gap="space300" style="width: 100%;">
<x-stack gap="space100" style="max-width: 400px;">
<p class="md-type-label-lg md-ink-variant">Compact: icon over label</p>
<div data-md-showcase-nav-demo="bar">
<div data-md-showcase-nav-page class="md-type-body-md md-ink-variant">The page</div>
<x-surface level="surface" corner="lg" outlined style="display: flex; flex-direction: column; height: 224px; overflow: hidden;">
<p class="md-type-body-md md-ink-variant" style="flex: 1 1 auto; padding: var(--md-sys-measurement-space200);">The page</p>
<x-navigation-bar>
<x-navigation-bar-item label="Shares" icon="folder_shared" link="#navigation" no-wire-navigate active />
<x-navigation-bar-item label="Upload" icon="upload" link="#navigation" no-wire-navigate />
<x-navigation-bar-item label="Inbox" icon="inbox" link="#navigation" no-wire-navigate badge="3" />
<x-navigation-bar-item label="Account" icon="account_circle" link="#navigation" no-wire-navigate :badge="true" badge-label="Needs attention" />
</x-navigation-bar>
</div>
</x-surface>
</x-stack>
<x-stack gap="space100" style="max-width: 800px;">
<p class="md-type-label-lg md-ink-variant">From 600px wide: icon beside label, centred</p>
<div data-md-showcase-nav-scroll>
<div data-md-showcase-nav-demo="bar-wide">
<div data-md-showcase-nav-page class="md-type-body-md md-ink-variant">The page</div>
<x-surface level="surface" corner="lg" outlined style="overflow-x: auto;">
<div style="display: flex; flex-direction: column; height: 224px; min-width: 600px;">
<p class="md-type-body-md md-ink-variant" style="flex: 1 1 auto; padding: var(--md-sys-measurement-space200);">The page</p>
<x-navigation-bar>
<x-navigation-bar-item label="Shares" icon="folder_shared" link="#navigation" no-wire-navigate active />
<x-navigation-bar-item label="Upload" icon="upload" link="#navigation" no-wire-navigate />
@@ -27,26 +27,26 @@
<x-navigation-bar-item label="Account" icon="account_circle" link="#navigation" no-wire-navigate />
</x-navigation-bar>
</div>
</div>
</x-surface>
</x-stack>
<x-stack gap="space100" style="max-width: 400px;">
<p class="md-type-label-lg md-ink-variant">Hide on scroll: scroll the page down, then up</p>
<div data-md-showcase-nav-demo="bar">
<div data-md-showcase-nav-page class="md-type-body-md md-ink-variant">The bar follows the window's scrolling, not this box's: scroll the showcase down and it leaves, scroll up and it springs back. It stays while a snackbar or a bottom sheet is on screen.</div>
<x-surface level="surface" corner="lg" outlined style="display: flex; flex-direction: column; height: 224px; overflow: hidden;">
<p class="md-type-body-md md-ink-variant" style="flex: 1 1 auto; padding: var(--md-sys-measurement-space200);">The bar follows the window's scrolling, not this box's: scroll the showcase down and it leaves, scroll up and it springs back. It stays while a snackbar or a bottom sheet is on screen.</p>
<x-navigation-bar hide-on-scroll>
<x-navigation-bar-item label="Shares" icon="folder_shared" link="#navigation" no-wire-navigate active />
<x-navigation-bar-item label="Upload" icon="upload" link="#navigation" no-wire-navigate />
<x-navigation-bar-item label="Inbox" icon="inbox" link="#navigation" no-wire-navigate badge="3" />
</x-navigation-bar>
</div>
</x-surface>
</x-stack>
<x-stack gap="space100" style="max-width: 800px;">
<p class="md-type-label-lg md-ink-variant">Tall (80px): icon over label whatever the width</p>
<div data-md-showcase-nav-scroll>
<div data-md-showcase-nav-demo="bar-wide">
<div data-md-showcase-nav-page class="md-type-body-md md-ink-variant">The page</div>
<x-surface level="surface" corner="lg" outlined style="overflow-x: auto;">
<div style="display: flex; flex-direction: column; height: 224px; min-width: 600px;">
<p class="md-type-body-md md-ink-variant" style="flex: 1 1 auto; padding: var(--md-sys-measurement-space200);">The page</p>
<x-navigation-bar tall>
<x-navigation-bar-item label="Shares" icon="folder_shared" link="#navigation" no-wire-navigate active />
<x-navigation-bar-item label="Upload" icon="upload" link="#navigation" no-wire-navigate />
@@ -54,13 +54,13 @@
<x-navigation-bar-item label="Account" icon="account_circle" link="#navigation" no-wire-navigate />
</x-navigation-bar>
</div>
</div>
</x-surface>
</x-stack>
</x-stack>
BLADE,
'Collapsed, narrow (centred) and expanded rails' => <<<'BLADE'
<x-row gap="space300" wrap align="start" style="width: 100%;">
<div data-md-showcase-nav-demo="rail">
<x-surface corner="lg" outlined style="display: flex; height: 576px; overflow: hidden;">
<x-navigation-rail mode="collapsed" label="Collapsed example" divider>
<x-slot:header>
<x-fab label="Compose" icon="edit" />
@@ -78,9 +78,9 @@
<x-navigation-rail-item label="Settings" icon="settings" link="#navigation" no-wire-navigate />
</x-slot:footer>
</x-navigation-rail>
</div>
</x-surface>
<div data-md-showcase-nav-demo="rail">
<x-surface corner="lg" outlined style="display: flex; height: 576px; overflow: hidden;">
<x-navigation-rail mode="collapsed" width="narrow" align="center" label="Narrow example" divider>
<x-slot:header>
<x-fab label="Compose" icon="edit" />
@@ -94,9 +94,9 @@
<x-navigation-rail-item label="Settings" icon="settings" link="#navigation" no-wire-navigate />
</x-slot:footer>
</x-navigation-rail>
</div>
</x-surface>
<div data-md-showcase-nav-demo="rail">
<x-surface corner="lg" outlined style="display: flex; height: 576px; overflow: hidden;">
<x-navigation-rail mode="expanded" label="Expanded example">
<x-slot:header>
<x-fab label="Compose" icon="edit" />
@@ -114,11 +114,11 @@
<x-navigation-rail-item label="Settings" icon="settings" link="#navigation" no-wire-navigate />
</x-slot:footer>
</x-navigation-rail>
</div>
</x-surface>
</x-row>
BLADE,
'Collapsible rail' => <<<'BLADE'
<div data-md-showcase-nav-demo="rail-wide">
<x-surface corner="lg" outlined style="display: flex; width: 100%; height: 480px; overflow: hidden;">
<x-navigation-rail label="Collapsible example">
<x-slot:brand>
<span class="md-type-title-lg md-truncate" style="display: block;">Mail</span>
@@ -133,13 +133,13 @@
<x-navigation-rail-item label="Sent" icon="send" link="#navigation" no-wire-navigate />
</x-navigation-rail>
<div data-md-showcase-nav-content class="md-type-body-md md-ink-variant">
<x-surface level="surface-container-low" padding="space300" class="md-type-body-md md-ink-variant" style="flex: 1 1 auto; min-width: 0;">
The menu button collapses and expands the rail, and the FAB morphs into an extended FAB with it. The choice is remembered and applied before the next page paints every collapsible rail follows it, <code>&lt;x-scaffold&gt;</code>'s from <code>expanded</code> (840px) too.
</div>
</div>
</x-surface>
</x-surface>
BLADE,
'Rail that hides when collapsed' => <<<'BLADE'
<div data-md-showcase-nav-demo="rail-wide">
<x-surface corner="lg" outlined style="display: flex; width: 100%; height: 480px; overflow: hidden;">
<x-navigation-rail label="Immersive example" hide-when-collapsed>
<x-slot:brand>
<span class="md-type-title-lg md-truncate" style="display: block;">Studio</span>
@@ -150,11 +150,13 @@
<x-navigation-rail-item label="Exports" icon="download" link="#navigation" no-wire-navigate />
</x-navigation-rail>
<x-stack gap="space200" data-md-showcase-nav-content class="md-type-body-md md-ink-variant">
<p>M3's other expanded behaviour: collapsing this rail takes it out of the layout instead of narrowing it to 96px, so an immersive page gets the whole window. The only way back is a menu button of the application's own — its own button then docks it again.</p>
<x-button icon="menu" label="Open navigation" x-on:click="$store.rail.show()" />
</x-stack>
</div>
<x-surface level="surface-container-low" padding="space300" style="flex: 1 1 auto; min-width: 0;">
<x-stack gap="space200" class="md-type-body-md md-ink-variant">
<p>M3's other expanded behaviour: collapsing this rail takes it out of the layout instead of narrowing it to 96px, so an immersive page gets the whole window. The only way back is a menu button of the application's own — its own button then docks it again.</p>
<x-button icon="menu" label="Open navigation" x-on:click="$store.rail.show()" />
</x-stack>
</x-surface>
</x-surface>
BLADE,
];
@endphp
@@ -64,7 +64,7 @@
<x-datepicker label="Disabled" value="2026-09-13" disabled />
<x-datepicker label="Read-only" value="2026-09-13" readonly />
<x-row gap="space125" wrap align="center">
<x-datepicker size="sm" aria-label="From" class="showcase-w-sm" />
<x-datepicker size="sm" aria-label="From" style="width: 192px;" />
</x-row>
</x-stack>
</x-grid>
@@ -20,7 +20,7 @@
<x-progress circular wavy label="Circular wavy, indeterminate" />
<x-progress value="65" circular thick label="Circular thick" />
<x-progress value="65" circular wavy thick label="Circular wavy thick" />
<x-progress circular wavy data-md-showcase-progress-lg label="Circular wavy, 96px" />
<x-progress circular wavy label="Circular wavy, 96px" style="width: 96px; height: 96px;" />
BLADE,
'Colours' => <<<'BLADE'
<x-progress value="35" color="secondary" label="Secondary" />