diff --git a/resources/views/components/list-item.blade.php b/resources/views/components/list-item.blade.php
index f9791dbe..c87a38ad 100644
--- a/resources/views/components/list-item.blade.php
+++ b/resources/views/components/list-item.blade.php
@@ -13,7 +13,9 @@
`link` makes the whole item the link. Otherwise, to make it open something while its trailing
controls keep their own presses, give it `data-list-row` and put `data-list-open` on the one
control that opens — see resources/js/list-rows.js. `selected` (true) is M3's selected item,
- in secondary-container; `disabled` greys it. --}}
+ in secondary-container; `disabled` greys it to 38%, drops its link and announces it
+ `aria-disabled` — M3's states model treats disabled as not interactive, so a disabled item
+ answers neither the pointer nor the keyboard. --}}
@props([
'title' => null,
@@ -32,7 +34,7 @@
])
@php
- $isLink = filled($link);
+ $isLink = filled($link) && ! $disabled;
$lines = (filled($overline) ? 1 : 0) + (filled($description) ? 1 : 0);
$initials = filled($avatar) && ! str_contains((string) $avatar, '/') && ! str_contains((string) $avatar, '.');
@endphp
@@ -42,6 +44,7 @@
data-list-item
@if ($isLink) data-list-row @endif
@if ($selected) data-selected @endif
+ @if ($disabled) aria-disabled="true" @endif
{{ $attributes->class([
'relative flex items-center gap-3 px-4 text-on-surface',
'min-h-14 py-2' => $lines === 0,
diff --git a/tests/Feature/Components/ListTest.php b/tests/Feature/Components/ListTest.php
index 7da5a031..c01436ef 100644
--- a/tests/Feature/Components/ListTest.php
+++ b/tests/Feature/Components/ListTest.php
@@ -38,6 +38,15 @@ it('makes a linked item a row that opens from anywhere', function () {
->toContain('wire:navigate');
});
+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')