Add the snackbar, badges, rich tooltips, alerts, stats and empty states
tests / lint (push) Successful in 1m3s
tests / feature (8.4) (push) Failing after 1m5s
tests / feature (8.5) (push) Failing after 1m4s
tests / browser (chrome, chromium) (push) Failing after 1m5s
tests / browser (firefox, firefox) (push) Failing after 1m1s
tests / browser (safari, webkit) (push) Failing after 1m1s

<x-toast> hosts the snackbar queue for the Toasts concern and
window.materialToast(), one at a time, paused on hover and focus, with
an optional action; it listens from the moment its script loads, so a
toast dispatched before Alpine starts is shown rather than lost.
<x-badge> is M3's dot and count, plus a tonal or outlined status label;
<x-rich-tooltip> is transient or persistent; <x-alert>, <x-stat> and
<x-empty-state> are built from M3's parts.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01V9NnLxnPp8vaaurb3Z1MFy
This commit is contained in:
Andreas Reinhold / reini
2026-09-13 06:59:40 +02:00
co-authored by Claude Opus 5
parent cd64f4f371
commit 648ad8efaf
20 changed files with 813 additions and 1 deletions
@@ -0,0 +1,68 @@
@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'
<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 })" />
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>&lt;x-badge&gt;</code>, <code>&lt;x-toast&gt;</code> (the snackbar host, fed by the <code>Toasts</code> concern or <code>materialToast()</code>),
<code>&lt;x-rich-tooltip&gt;</code>, <code>&lt;x-alert&gt;</code>, <code>&lt;x-stat&gt;</code> and <code>&lt;x-empty-state&gt;</code>.
</p>
@foreach ($examples as $title => $code)
<x-showcase::example :$title :$code />
@endforeach
</section>