blade('')) ->toContain('size-14 rounded-corner-lg') ->toContain('bg-primary-container text-on-primary-container') ->toContain('shadow-elevation-3') ->toContain('aria-label="New share"') ->toContain('popover="manual"'); }); it('sizes a FAB at 56, 80 and 96px', function (string $size, string $classes, string $icon) { expect((string) $this->blade(""))->toContain($classes)->toContain($icon); })->with([ 'sm' => ['sm', 'size-14 rounded-corner-lg', 'size-6'], 'md' => ['md', 'size-20 rounded-corner-lg-increased', 'size-7'], 'lg' => ['lg', 'size-24 rounded-corner-xl', 'size-8'], ]); it('fills the FAB\'s glyph, as M3 asks twice over', function () { $svg = trim((string) file_get_contents(__DIR__.'/../../../resources/svg/symbols/filled/add.svg')); $filled = substr($svg, (int) strpos($svg, '><') + 1); expect((string) $this->blade(''))->toContain($filled) ->and((string) $this->blade(''))->toContain($filled); }); it('extends with a label', function () { expect((string) $this->blade('')) ->toContain('h-20 min-w-20 gap-4 px-[26px] rounded-corner-lg-increased type-title-lg') ->toContain('bg-tertiary text-on-tertiary') ->toContain('Upload') ->not->toContain('aria-label'); }); it('gives the extended FAB M3\'s gaps and its 80px minimum width', function (string $size, string $classes) { expect((string) $this->blade(""))->toContain($classes); })->with([ 'sm' => ['sm', 'h-14 min-w-20 gap-2'], 'md' => ['md', 'h-20 min-w-20 gap-4'], 'lg' => ['lg', 'h-24 min-w-24 gap-5'], ]); it('marks its root for the places that draw a nested FAB their own way', function () { expect((string) $this->blade(''))->toContain('data-fab'); }); it('cannot be disabled, because M3 says to remove a FAB instead', function () { $html = (string) $this->blade(''); // `disabled` is no longer a prop, so it falls through as a plain attribute rather than // painting M3's disabled treatment. expect($html)->not->toContain('disabled:bg-on-surface/10')->not->toContain('disabled:shadow-none'); }); it('opens a FAB menu of end-aligned actions above it', function () { $html = (string) $this->blade(<<<'BLADE' BLADE); expect($html) ->toContain('x-data="materialMenu"') ->toContain('aria-label="New"') ->toContain('bg-secondary-container text-on-secondary-container aria-expanded:bg-secondary aria-expanded:text-on-secondary') ->toContain('aria-expanded:rounded-corner-full') ->toContain('role="menu"') ->toContain('[position-area:top_span-left]') ->toContain('role="menuitem"') ->toContain('wire:click="upload"') ->toContain('h-14') ->toContain('Upload files'); });