Plan step 38 review: the frame's structural rule that kept a section's own <h2> for screen readers (Tailwind's [&>section>h2]:sr-only before, a showcase.css rule during the rewrite) was removed as dead weight once every section had a real heading, so each page drew its title twice, the <h1> and an identical headline under it. The <h2>s are md-visually-hidden again, the frame's comment says why, and the section page test asserts it. The Layout section's description said "window size classes"; M3's term is breakpoints. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01Qwx5USif3wFFmxtHg5U1g9
260 lines
16 KiB
PHP
260 lines
16 KiB
PHP
@php
|
|
$examples = [
|
|
'Cards' => <<<'BLADE'
|
|
<x-grid :columns="['compact' => 1, 'expanded' => 3]" gap="space200" style="width: 100%;">
|
|
<x-card title="Filled" subtitle="surface-container-highest">
|
|
The default card.
|
|
<x-slot:actions><x-button label="Open" /></x-slot:actions>
|
|
</x-card>
|
|
|
|
<x-card title="Elevated" subtitle="surface-container-low, elevation 1" variant="elevated">
|
|
<x-slot:menu><x-button icon="more_vert" tooltip="More" /></x-slot:menu>
|
|
For content that floats a little.
|
|
</x-card>
|
|
|
|
<x-card title="Outlined" subtitle="an outline-variant edge" variant="outlined" separator>
|
|
Quiet, on the surface itself.
|
|
</x-card>
|
|
</x-grid>
|
|
BLADE,
|
|
'A card that opens from anywhere on it' => <<<'BLADE'
|
|
<x-card variant="outlined" data-md-list-row style="width: 100%; max-width: 384px;">
|
|
<a href="#containment" data-md-list-open class="md-type-title-md">holiday-photos.zip</a>
|
|
<p class="md-ink-variant" style="margin-top: var(--md-sys-measurement-space50);">248 MB · expires in 3 days</p>
|
|
<x-slot:actions>
|
|
<x-button label="Copy link" icon="content_copy" x-on:click="materialToast('Link copied', { type: 'success' })" />
|
|
</x-slot:actions>
|
|
</x-card>
|
|
BLADE,
|
|
'A directly actionable card: the card is the tab stop' => <<<'BLADE'
|
|
<x-card variant="elevated" actionable role="link" title="contract.pdf" style="width: 100%; max-width: 384px;">
|
|
<a href="#containment" data-md-list-open tabindex="-1" class="md-type-title-md">contract.pdf</a>
|
|
<p class="md-ink-variant" style="margin-top: var(--md-sys-measurement-space50);">1.2 MB · downloaded twice</p>
|
|
<x-slot:actions>
|
|
<x-button label="Copy link" icon="content_copy" x-on:click="materialToast('Link copied', { type: 'success' })" />
|
|
</x-slot:actions>
|
|
</x-card>
|
|
BLADE,
|
|
'A card being dragged' => <<<'BLADE'
|
|
<x-stack gap="space200" x-data="{ dragged: false }" style="width: 100%; max-width: 384px;">
|
|
<x-button label="Pick it up or put it down" variant="tonal" x-on:click="dragged = ! dragged" />
|
|
<x-card variant="elevated" title="holiday-photos.zip" subtitle="248 MB" x-bind:data-md-dragged="dragged || null">
|
|
Elevation 4 and the 16% state layer, for as long as the application says the card is being carried.
|
|
</x-card>
|
|
</x-stack>
|
|
BLADE,
|
|
'Lists' => <<<'BLADE'
|
|
<x-grid :columns="['compact' => 1, 'medium' => 2]" gap="space300" style="width: 100%;">
|
|
<x-list dividers label="Files">
|
|
<x-list-item title="holiday-photos.zip" description="248 MB" icon="folder_zip" trailing="3 days" />
|
|
<x-list-item title="contract.pdf" overline="Password protected" description="1.2 MB · downloaded twice" icon="picture_as_pdf" trailing="1 hour" />
|
|
<x-list-item title="Settings" icon="settings" icon-right="chevron_right" link="#containment" />
|
|
</x-list>
|
|
|
|
<x-list segmented label="Recipients">
|
|
<x-list-item title="Anna Müller" description="Downloaded yesterday" avatar="AM" :selected="true" />
|
|
<x-list-item title="Ben Keller" description="Not opened yet" avatar="BK" link="#containment" />
|
|
<x-list-item title="Chiara Rossi" avatar="CR">
|
|
<x-slot:end><x-button icon="more_vert" tooltip="More" /></x-slot:end>
|
|
</x-list-item>
|
|
<x-list-item title="Dan Fischer" description="Invitation withdrawn" avatar="DF" link="#containment" disabled />
|
|
</x-list>
|
|
</x-grid>
|
|
BLADE,
|
|
'A list to choose from' => <<<'BLADE'
|
|
<x-list selectable label="Expiry" style="width: 100%; max-width: 384px;">
|
|
<x-list-item title="One hour" :selected="false" />
|
|
<x-list-item title="Three days" :selected="true" />
|
|
<x-list-item title="Thirty days" :selected="false" />
|
|
</x-list>
|
|
BLADE,
|
|
'A list with leading video' => <<<'BLADE'
|
|
<x-list dividers label="Clips" style="width: 100%; max-width: 448px;">
|
|
<x-list-item title="Sunrise over the lake" description="2:14 · 48 MB">
|
|
<x-slot:video>
|
|
<div style="display: grid; place-items: center; background: linear-gradient(to bottom right, var(--md-sys-color-primary-container), var(--md-sys-color-tertiary-container)); color: var(--md-sys-color-on-primary-container);">
|
|
<x-icon name="play_circle" />
|
|
</div>
|
|
</x-slot:video>
|
|
</x-list-item>
|
|
<x-list-item overline="Draft" title="Walking the old town" description="Uploaded yesterday · 7:48">
|
|
<x-slot:video>
|
|
<div style="display: grid; place-items: center; background: linear-gradient(to bottom right, var(--md-sys-color-secondary-container), var(--md-sys-color-primary-container)); color: var(--md-sys-color-on-secondary-container);">
|
|
<x-icon name="play_circle" />
|
|
</div>
|
|
</x-slot:video>
|
|
</x-list-item>
|
|
</x-list>
|
|
BLADE,
|
|
'Dividers and collapse' => <<<'BLADE'
|
|
<x-stack gap="space200" style="width: 100%;">
|
|
<x-collapse title="How long do links last?" icon="schedule" open>
|
|
Until the expiry you chose, from one hour to thirty days.
|
|
</x-collapse>
|
|
<x-divider />
|
|
<x-collapse title="Can recipients upload files?" variant="filled">
|
|
No. They can only download what you shared.
|
|
</x-collapse>
|
|
<x-row gap="space200" align="center" style="height: 40px;"><span>Left</span><x-divider vertical /><span>Right</span></x-row>
|
|
</x-stack>
|
|
BLADE,
|
|
'A divider with a subheader' => <<<'BLADE'
|
|
<div style="width: 100%; max-width: 448px;">
|
|
<x-divider text="Today" />
|
|
<x-list label="Today">
|
|
<x-list-item title="holiday-photos.zip" description="Shared with 3 people" icon="folder_zip" />
|
|
<x-list-item title="contract.pdf" description="Downloaded twice" icon="picture_as_pdf" />
|
|
</x-list>
|
|
<x-divider text="Earlier this week" style="margin-top: var(--md-sys-measurement-space100);" />
|
|
<x-list label="Earlier this week">
|
|
<x-list-item title="minutes.docx" description="Expired" icon="description" />
|
|
</x-list>
|
|
</div>
|
|
BLADE,
|
|
'Collapse bound to a property' => <<<'BLADE'
|
|
<x-stack gap="space200" x-data="{ advanced: false }" style="width: 100%;">
|
|
<x-row wrap align="center" gap="space200">
|
|
<x-button label="Open" variant="tonal" x-on:click="advanced = true" />
|
|
<x-button label="Close" variant="tonal" x-on:click="advanced = false" />
|
|
<span class="md-type-body-md md-ink-variant">advanced: <span x-text="advanced"></span></span>
|
|
</x-row>
|
|
<x-collapse title="Advanced settings" icon="tune" variant="filled" x-model="advanced">
|
|
Bound with x-model here. In a Livewire view, wire:model="advanced" binds a boolean property the same way, and the page arrives with it open or closed as the property is.
|
|
</x-collapse>
|
|
</x-stack>
|
|
BLADE,
|
|
'Dialogs' => <<<'BLADE'
|
|
<div x-data="{ open: false }">
|
|
<x-button label="Basic dialog" variant="tonal" x-on:click="open = true" />
|
|
<x-modal title="Delete this share?" subtitle="Recipients lose access at once. This cannot be undone." alert>
|
|
<x-slot:actions>
|
|
<x-button label="Cancel" x-on:click="close()" />
|
|
<x-button label="Delete" danger x-on:click="close()" />
|
|
</x-slot:actions>
|
|
</x-modal>
|
|
</div>
|
|
|
|
<div x-data="{ open: false }">
|
|
<x-button label="With a hero icon" variant="tonal" x-on:click="open = true" />
|
|
<x-modal title="Reset the password?" icon="lock_reset">
|
|
Recipients with the old password will need the new one.
|
|
<x-slot:actions>
|
|
<x-button label="Cancel" x-on:click="close()" />
|
|
<x-button label="Reset" x-on:click="close()" />
|
|
</x-slot:actions>
|
|
</x-modal>
|
|
</div>
|
|
|
|
<div x-data="{ open: false }">
|
|
<x-button label="Full screen on a phone" variant="tonal" x-on:click="open = true" />
|
|
<x-modal title="Share settings" fullscreen>
|
|
A form that needs the room.
|
|
<x-slot:actions><x-button label="Save" variant="filled" x-on:click="close()" /></x-slot:actions>
|
|
</x-modal>
|
|
</div>
|
|
BLADE,
|
|
'A dialog whose body scrolls: dividers only while content is hidden' => <<<'BLADE'
|
|
<div x-data="{ open: false }">
|
|
<x-button label="Long body" variant="tonal" x-on:click="open = true" />
|
|
<x-modal title="Terms of the share link" subtitle="Scroll them: a rule appears under the headline once the text leaves its top, and the one over the buttons goes at its end.">
|
|
<x-stack gap="space200">
|
|
<p>A share link opens the files you chose, and only those. Adding a file to the folder later does not add it to a link you have already sent; make a new link for it.</p>
|
|
<p>Anyone who has the link can open it until it expires. Forwarding the link forwards that access, so send it to the people who need it and to nobody else.</p>
|
|
<p>A password, when you set one, is asked for every time the link is opened. Send it separately from the link, by another channel, so one intercepted message is not enough.</p>
|
|
<p>The link expires at the time you picked. After that it shows a page saying so, and downloads that were still running stop at once.</p>
|
|
<p>You can end a link early from the list of shares. Ending it takes effect immediately for everyone, including people who opened it a moment ago.</p>
|
|
<p>Downloads are counted per file. The count is shown to you and never to the people you shared with.</p>
|
|
<p>Files larger than 2 GB are offered as a single archive only when the whole share fits under the archive limit; otherwise each file downloads on its own.</p>
|
|
<p>Previews are generated for images, PDFs and plain text. Other types show their name, size and an icon.</p>
|
|
<p>Deleting a file you shared removes it from every link that holds it. People who open such a link see the files that are left.</p>
|
|
<p>These terms apply to every link you create from now on. Links you created before keep the terms they were made under.</p>
|
|
</x-stack>
|
|
<x-slot:actions>
|
|
<x-button label="Decline" x-on:click="close()" />
|
|
<x-button label="Accept" x-on:click="close()" />
|
|
</x-slot:actions>
|
|
</x-modal>
|
|
</div>
|
|
|
|
<div x-data="{ open: false }">
|
|
<x-button label="Always divided (separator)" variant="tonal" x-on:click="open = true" />
|
|
<x-modal title="Who can open the link" separator>
|
|
<x-radio label="Audience" name="showcase-dialog-audience" value="password" :options="[['id' => 'anyone', 'name' => 'Anyone with the link'], ['id' => 'password', 'name' => 'Anyone with the password'], ['id' => 'team', 'name' => 'My team only']]" />
|
|
<x-slot:actions>
|
|
<x-button label="Cancel" x-on:click="close()" />
|
|
<x-button label="Save" x-on:click="close()" />
|
|
</x-slot:actions>
|
|
</x-modal>
|
|
</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-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">
|
|
From <code>expanded</code> (840px) the sheet beside this text is co-planar: no scrim, no focus trap, flat on the surface, divided from this column by a rule. Narrow the window and the same sheet becomes the modal one.
|
|
</p>
|
|
</x-stack>
|
|
|
|
<x-drawer standard title="Filters" subtitle="Narrow the list down">
|
|
<x-list selectable label="Expiry">
|
|
<x-list-item title="One hour" :selected="false" />
|
|
<x-list-item title="Three days" :selected="true" />
|
|
<x-list-item title="Thirty days" :selected="false" />
|
|
</x-list>
|
|
<x-slot:actions><x-button label="Apply" variant="filled" /></x-slot:actions>
|
|
</x-drawer>
|
|
</x-row>
|
|
BLADE,
|
|
'Sheets' => <<<'BLADE'
|
|
<div x-data="{ open: false }">
|
|
<x-button label="Side sheet" variant="tonal" x-on:click="open = true" />
|
|
<x-drawer title="Share details" subtitle="holiday-photos.zip" with-close-button separator>
|
|
<x-list>
|
|
<x-list-item title="Size" trailing="248 MB" />
|
|
<x-list-item title="Expires" trailing="in 3 days" />
|
|
<x-list-item title="Downloads" trailing="12" />
|
|
</x-list>
|
|
<x-slot:actions><x-button label="Delete" icon="delete" x-on:click="close()" /></x-slot:actions>
|
|
</x-drawer>
|
|
</div>
|
|
|
|
<div x-data="{ open: false }">
|
|
<x-button label="Bottom sheet" variant="tonal" x-on:click="open = true" />
|
|
<x-bottom-sheet title="Share via">
|
|
<x-list>
|
|
<x-list-item title="Copy link" icon="content_copy" />
|
|
<x-list-item title="Email" icon="mail" />
|
|
<x-list-item title="QR code" icon="qr_code_2" />
|
|
</x-list>
|
|
</x-bottom-sheet>
|
|
</div>
|
|
|
|
<div x-data="{ open: false }">
|
|
<x-button label="Bottom sheet with preset heights" variant="tonal" x-on:click="open = true" />
|
|
<x-bottom-sheet title="Nearby places" snap>
|
|
<p class="md-type-body-md md-ink-variant">Press the drag handle, or focus it and press Enter, to move to the next height; from the last it closes. Dragging it settles on the nearest.</p>
|
|
<x-list>
|
|
<x-list-item title="Hafen" description="240 m · open until 23:00" icon="location_on" />
|
|
<x-list-item title="Stadtbibliothek" description="600 m · closes at 18:00" icon="location_on" />
|
|
<x-list-item title="Seepromenade" description="1.1 km · always open" icon="location_on" />
|
|
</x-list>
|
|
</x-bottom-sheet>
|
|
</div>
|
|
BLADE,
|
|
];
|
|
@endphp
|
|
|
|
<x-livewire-material::stack as="section" id="containment" gap="space300">
|
|
<h2 class="md-visually-hidden">Containment</h2>
|
|
|
|
<p class="md-type-body-md md-ink-variant">
|
|
<code><x-card></code>, <code><x-list></code> and <code><x-list-item></code>, <code><x-divider></code>, <code><x-collapse></code>,
|
|
<code><x-modal></code>, <code><x-drawer></code> and <code><x-bottom-sheet></code>.
|
|
</p>
|
|
|
|
@foreach ($examples as $title => $code)
|
|
<x-showcase::example :$title :$code />
|
|
@endforeach
|
|
</x-livewire-material::stack>
|