A sticky toast stays until it is dismissed or its action pressed, for a
question that must be answered ("A new version is ready" with Reload).
It is kept aside rather than queued, so it never holds up ordinary
toasts: one that arrives while it shows takes its place, and the sticky
toast comes back once the queue is empty. One is kept at a time; a newer
sticky toast replaces it. Every other toast keeps today's queue.
An action's `event` names a window event dispatched when it is pressed,
beside `handler`, for toasts whose detail cannot carry a function. The
snackbar now closes before either runs, so a toast they show is not the
one dismissed.
`data-toast` and `data-toast-action` give applications stable hooks for
their tests.
The queue now forgets a cleared timer in next(): a toast dismissed by a
click that neither hovered nor focused it first, as a screen reader
activates a button, left its timer running and cut the next toast short.
The showcase's snackbar buttons had no Alpine scope and did nothing; they
are wrapped in one, with a sticky example.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01RHoXZSHc8gGpZjFmA5fPc2
79 lines
4.9 KiB
PHP
79 lines
4.9 KiB
PHP
@php
|
|
$examples = [
|
|
'Badges' => <<<'BLADE'
|
|
<span class="relative inline-flex"><x-icon name="notifications" /><x-badge floating /></span>
|
|
<span class="relative inline-flex"><x-icon name="mail" /><x-badge value="4" floating /></span>
|
|
<span class="relative inline-flex"><x-icon name="inbox" /><x-badge value="1204" max="999" floating /></span>
|
|
<x-badge value="Expired" tonal />
|
|
<x-badge value="Active" color="success" tonal />
|
|
<x-badge value="Password" color="info" tonal />
|
|
<x-badge value="Pro" outline />
|
|
BLADE,
|
|
'Snackbars' => <<<'BLADE'
|
|
<div x-data class="flex flex-wrap items-center gap-4">
|
|
<x-button label="Saved" variant="tonal" x-on:click="materialToast('Settings saved', { type: 'success' })" />
|
|
<x-button label="With a description" variant="tonal" x-on:click="materialToast('Upload failed', { type: 'error', description: 'The file is larger than 4 GB.' })" />
|
|
<x-button label="With an action" variant="tonal" x-on:click="materialToast('Share deleted', { action: { label: 'Undo', handler: () => materialToast('Share restored', { type: 'info' }) } })" />
|
|
<x-button label="Until dismissed" variant="tonal" x-on:click="materialToast('Your storage is almost full', { type: 'warning', timeout: 0 })" />
|
|
<x-button label="Sticky, with an event" variant="tonal" x-on:click="materialToast('A new version is ready', { type: 'info', sticky: true, action: { label: 'Reload', event: 'showcase:reload' } })" x-on:showcase:reload.window="materialToast('Reloading…')" />
|
|
</div>
|
|
BLADE,
|
|
'Plain tooltips' => <<<'BLADE'
|
|
<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="focus-ring rounded-corner-xs type-body-md text-on-surface-variant">holiday-photos.zip</span>
|
|
</x-tooltip>
|
|
BLADE,
|
|
'Rich tooltips' => <<<'BLADE'
|
|
<x-rich-tooltip title="Expiry" text="Recipients lose access after this time. Admins can change the longest time allowed.">
|
|
<x-button icon="help" aria-label="About expiry" />
|
|
</x-rich-tooltip>
|
|
|
|
<x-rich-tooltip title="Password protection" text="Recipients need the password before they can see the files." persistent>
|
|
<x-button label="Press for details" icon="lock" variant="outlined" />
|
|
<x-slot:actions>
|
|
<x-button label="Learn more" />
|
|
</x-slot:actions>
|
|
</x-rich-tooltip>
|
|
BLADE,
|
|
'Alerts' => <<<'BLADE'
|
|
<x-alert title="Storage almost full" description="3.8 GB of 4 GB used. Old shares are deleted when they expire." color="warning" class="w-full" />
|
|
<x-alert description="Links are shown only once. Copy yours before you leave the page." class="w-full" dismissible />
|
|
<x-alert title="Upload failed" color="error" class="w-full">
|
|
The connection dropped at 64%.
|
|
<x-slot:actions><x-button label="Try again" /></x-slot:actions>
|
|
</x-alert>
|
|
<x-alert description="Settings saved." color="success" class="w-full" />
|
|
BLADE,
|
|
'Stats' => <<<'BLADE'
|
|
<div class="grid w-full gap-4 sm:grid-cols-2 lg:grid-cols-4">
|
|
<x-stat title="Shares" value="1,204" icon="link" description="12 this week" />
|
|
<x-stat title="Files" value="8,317" icon="description" />
|
|
<x-stat title="Stored" value="3.2 GB" icon="hard_drive" description="of 4 GB" />
|
|
<x-stat title="Downloads" value="42,019" icon="download" />
|
|
</div>
|
|
BLADE,
|
|
'Empty state' => <<<'BLADE'
|
|
<x-empty-state icon="upload_file" title="No shares yet" description="Files you share appear here, with their links and when they expire." class="w-full">
|
|
<x-slot:actions>
|
|
<x-button label="Upload files" icon="upload" variant="filled" />
|
|
</x-slot:actions>
|
|
</x-empty-state>
|
|
BLADE,
|
|
];
|
|
@endphp
|
|
|
|
<section id="communication" class="scroll-mt-24 space-y-6">
|
|
<h2 class="type-headline-md">Communication</h2>
|
|
|
|
<p class="max-w-3xl type-body-md text-on-surface-variant">
|
|
<code><x-badge></code>, <code><x-toast></code> (the snackbar host, fed by the <code>Toasts</code> concern or <code>materialToast()</code>),
|
|
<code><x-tooltip></code>, <code><x-rich-tooltip></code>, <code><x-alert></code>, <code><x-stat></code> and <code><x-empty-state></code>.
|
|
</p>
|
|
|
|
@foreach ($examples as $title => $code)
|
|
<x-showcase::example :$title :$code />
|
|
@endforeach
|
|
</section>
|