blade('')) ->toContain('role="list"') ->toContain('aria-label="Files"') ->toContain('data-list="plain"') ->toContain('data-dividers') ->not->toContain('divide-y') ->toContain('role="listitem"') ->and((string) $this->blade(''))->not->toContain('data-dividers') ->and((string) $this->blade(''))->not->toContain('data-dividers'); }); it('draws M3 Expressive\'s segmented list', function () { expect((string) $this->blade('')) ->toContain('data-list="segmented"') ->toContain('gap-0.5'); }); it('grows an item from one to three lines, top-aligning the tallest', function () { expect((string) $this->blade(''))->toContain('items-center')->toContain('min-h-14 py-2') ->and((string) $this->blade(''))->toContain('items-center')->toContain('min-h-18 py-2')->toContain('248 MB') ->and((string) $this->blade('')) ->toContain('items-start') ->toContain('min-h-22 py-3') ->toContain('Protected') ->not->toContain('items-center'); }); it('leaves 16px between the item and what leads or trails it', function () { expect((string) $this->blade(''))->toContain('flex gap-4 px-4'); }); it('draws the expressive icon size in a segmented list', function () { expect((string) $this->blade('')) ->toContain('size-5') ->not->toContain('size-6') ->and((string) $this->blade(''))->toContain('size-6'); }); it('leads with an icon, an avatar or an image, and trails with text or an icon', function () { expect((string) $this->blade('')) ->toContain('3 days') ->and(substr_count((string) $this->blade(''), 'toBe(2) ->and((string) $this->blade(''))->toContain('bg-primary-container')->toContain('>AM') ->and((string) $this->blade(''))->toContain('and((string) $this->blade(''))->toContain('size-14'); }); it('makes a linked item a row that opens from anywhere', function () { expect((string) $this->blade('')) ->toContain('data-list-row') ->toContain('href="/settings"') ->toContain('data-list-open') ->toContain('wire:navigate'); }); it('is a list box of options when it is one a person chooses from', function () { expect((string) $this->blade('')) ->toContain('role="listbox"') ->toMatch('/role="option"\s+aria-selected="true"/') ->toMatch('/role="option"\s+aria-selected="false"/') ->not->toContain('aria-multiselectable') ->and((string) $this->blade('')) ->toContain('role="listbox"') ->toContain('aria-multiselectable="true"') ->and((string) $this->blade('')) ->toContain('role="list"') ->toMatch('/role="listitem"\s+aria-current="true"/') ->not->toContain('aria-selected'); }); it('draws a second cue on a selected option, which icon-right replaces', function () { expect(substr_count((string) $this->blade(''), 'toBe(1) ->and(substr_count((string) $this->blade(''), 'toBe(1) ->and(substr_count((string) $this->blade(''), 'toBe(0) ->and(substr_count((string) $this->blade(''), 'toBe(0); }); it('leaves a disabled item out of the keyboard and announces it disabled', function () { expect((string) $this->blade('')) ->toContain('aria-disabled="true"') ->toContain('pointer-events-none text-on-surface/38') ->not->toContain('href="/settings"') ->not->toContain('data-list-open') ->not->toContain('data-list-row'); }); it('marks a selected item and takes controls in its slots', function () { expect((string) $this->blade('')) ->toContain('data-selected') ->toContain('') ->toContain(''); });