Take the icon off the snackbar and lift the FAB clear of it

M3 says to avoid an icon in a snackbar and gives the supporting text no fourth
colour, so the state glyph and the 80% description are gone: a type now only
picks the announcement role. The 40px action and close buttons take the shared
touch-target, Escape dismisses a snackbar that holds the focus, and the host
publishes --material-snackbar-height on <html> so a `fab` button sits above the
snackbar instead of under it. Plan step 18, actions.md ACT-17, ACT-18, ACT-20,
ACT-34, ACT-35.

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
2026-09-14 06:09:47 +02:00
co-authored by Claude Opus 5
parent eac7f6a1de
commit 7bc4f740e7
7 changed files with 76 additions and 33 deletions
+3 -1
View File
@@ -168,7 +168,9 @@ it('is a FAB on a compact window and a filled button from medium, in one element
$html = (string) $this->blade('<x-button label="New share" icon="add" fab />');
expect(substr_count($html, '<button'))->toBe(1)
->and($html)->toContain('max-medium:fixed')->toContain('max-medium:bg-primary-container')->toContain('bg-primary text-on-primary');
->and($html)->toContain('max-medium:fixed')->toContain('max-medium:bg-primary-container')->toContain('bg-primary text-on-primary')
// M3 puts a snackbar above a FAB, never over one: the host publishes its height.
->toContain('max-medium:bottom-[calc(var(--material-bottom-bar,0px)+var(--material-snackbar-height,0px)+1rem)]');
});
it('submits a form when asked', function () {
+11
View File
@@ -10,6 +10,17 @@ it('hosts the snackbar queue, kept across wire:navigate', function () {
->toContain('justify-center');
});
it('draws no state icon, and reaches 48px from its 40px controls', function () {
$html = (string) $this->blade('<x-toast />');
// M3 tells you to avoid an icon in a snackbar; the type is left to pick the announcement role.
expect(substr_count($html, '<svg'))->toBe(1)
->and($html)->not->toContain('text-inverse-success')
->not->toContain('opacity-80')
->toContain('data-toast-action class="state-layer focus-ring touch-target')
->toContain('state-layer focus-ring touch-target inline-flex size-10');
});
it('can sit at the start', function () {
expect((string) $this->blade('<x-toast position="bottom-start" />'))->toContain('justify-start');
});