Reach M3's 48px target from every 40px navigation control
The theme toggle and the account-menu avatar are drawn 40px and had no target extension; both now carry `touch-target`, and the avatar's clipping moves from the button (which would have cut the pseudo-target off) to the <img>. The rail's hand-rolled `after:` target becomes the same utility. Plan: docs/plans/material-3-alignment.md, step 14 (navigation N-01). Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01Qwx5USif3wFFmxtHg5U1g9
This commit is contained in:
co-authored by
Claude Opus 5
parent
0adfb6fff4
commit
4a4982b1ef
@@ -38,10 +38,10 @@
|
|||||||
type="button"
|
type="button"
|
||||||
aria-label="{{ $label }}"
|
aria-label="{{ $label }}"
|
||||||
data-account-menu
|
data-account-menu
|
||||||
class="focus-ring inline-flex size-10 shrink-0 cursor-pointer items-center justify-center overflow-hidden rounded-corner-full bg-primary-container type-label-lg text-on-primary-container"
|
class="touch-target focus-ring inline-flex size-10 shrink-0 cursor-pointer items-center justify-center rounded-corner-full bg-primary-container type-label-lg text-on-primary-container"
|
||||||
>
|
>
|
||||||
@if ($image)
|
@if ($image)
|
||||||
<img src="{{ $avatar }}" alt="" class="size-full object-cover" />
|
<img src="{{ $avatar }}" alt="" class="size-full rounded-corner-full object-cover" />
|
||||||
@elseif (filled($initials))
|
@elseif (filled($initials))
|
||||||
{{ $initials }}
|
{{ $initials }}
|
||||||
@else
|
@else
|
||||||
|
|||||||
@@ -109,7 +109,7 @@
|
|||||||
x-on:click="menu()"
|
x-on:click="menu()"
|
||||||
x-bind:aria-label="expanded ? @js(__('Collapse navigation')) : @js(__('Expand navigation'))"
|
x-bind:aria-label="expanded ? @js(__('Collapse navigation')) : @js(__('Expand navigation'))"
|
||||||
x-bind:aria-expanded="expanded.toString()"
|
x-bind:aria-expanded="expanded.toString()"
|
||||||
class="state-layer focus-ring inline-flex size-10 shrink-0 cursor-pointer items-center justify-center rounded-corner-full text-on-surface-variant after:absolute after:top-1/2 after:left-1/2 after:size-12 after:-translate-x-1/2 after:-translate-y-1/2"
|
class="state-layer touch-target focus-ring inline-flex size-10 shrink-0 cursor-pointer items-center justify-center rounded-corner-full text-on-surface-variant"
|
||||||
>
|
>
|
||||||
<span class="contents rail-collapsed:hidden"><x-livewire-material::icon name="menu_open" class="size-6" /></span>
|
<span class="contents rail-collapsed:hidden"><x-livewire-material::icon name="menu_open" class="size-6" /></span>
|
||||||
<span class="hidden rail-collapsed:contents"><x-livewire-material::icon name="menu" class="size-6" /></span>
|
<span class="hidden rail-collapsed:contents"><x-livewire-material::icon name="menu" class="size-6" /></span>
|
||||||
|
|||||||
@@ -93,7 +93,7 @@
|
|||||||
x-bind:aria-pressed="($store.theme.resolved === 'dark').toString()"
|
x-bind:aria-pressed="($store.theme.resolved === 'dark').toString()"
|
||||||
x-on:click="$store.theme.toggle()"
|
x-on:click="$store.theme.toggle()"
|
||||||
@endif
|
@endif
|
||||||
{{ $attributes->class(['state-layer focus-ring inline-flex size-10 shrink-0 cursor-pointer items-center justify-center rounded-corner-full text-on-surface-variant transition-[border-radius] duration-(--md-sys-motion-spatial-fast-duration) ease-spatial-fast active:rounded-corner-sm']) }}
|
{{ $attributes->class(['state-layer touch-target focus-ring inline-flex size-10 shrink-0 cursor-pointer items-center justify-center rounded-corner-full text-on-surface-variant transition-[border-radius] duration-(--md-sys-motion-spatial-fast-duration) ease-spatial-fast active:rounded-corner-sm']) }}
|
||||||
>
|
>
|
||||||
@if ($mode === 'cycle')
|
@if ($mode === 'cycle')
|
||||||
<x-livewire-material::icon name="light_mode" x-cloak x-show="$store.theme.choice === 'light'" />
|
<x-livewire-material::icon name="light_mode" x-cloak x-show="$store.theme.choice === 'light'" />
|
||||||
|
|||||||
@@ -86,6 +86,8 @@ it('switches the theme through the store in three shapes', function () {
|
|||||||
expect((string) $this->blade('<x-theme-toggle />'))
|
expect((string) $this->blade('<x-theme-toggle />'))
|
||||||
->toContain('data-theme-toggle="toggle"')
|
->toContain('data-theme-toggle="toggle"')
|
||||||
->toContain('aria-label="Dark theme"')
|
->toContain('aria-label="Dark theme"')
|
||||||
|
// 40px drawn, 48px reached: M3's minimum target (N-01).
|
||||||
|
->toContain('touch-target')
|
||||||
->toContain('$store.theme.toggle()')
|
->toContain('$store.theme.toggle()')
|
||||||
->and((string) $this->blade('<x-theme-toggle mode="cycle" />'))
|
->and((string) $this->blade('<x-theme-toggle mode="cycle" />'))
|
||||||
->toContain('data-theme-toggle="cycle"')
|
->toContain('data-theme-toggle="cycle"')
|
||||||
@@ -107,12 +109,15 @@ it('opens an account menu from the initials of a name', function () {
|
|||||||
expect($html)
|
expect($html)
|
||||||
->toContain('aria-label="Account"')
|
->toContain('aria-label="Account"')
|
||||||
->toContain('data-account-menu')
|
->toContain('data-account-menu')
|
||||||
|
// The 40px avatar reaches 48px, and nothing clips the pseudo-target (N-01).
|
||||||
|
->toContain('touch-target')
|
||||||
|
->not->toContain('overflow-hidden')
|
||||||
->toMatch('/>\s*AM\s*<\/button>/')
|
->toMatch('/>\s*AM\s*<\/button>/')
|
||||||
->toContain('anna@example.com')
|
->toContain('anna@example.com')
|
||||||
->toContain('Settings')
|
->toContain('Settings')
|
||||||
->toContain('data-account-theme')
|
->toContain('data-account-theme')
|
||||||
->toContain('Sign out')
|
->toContain('Sign out')
|
||||||
->and((string) $this->blade('<x-account-menu avatar="/anna.jpg" :theme="false" />'))
|
->and((string) $this->blade('<x-account-menu avatar="/anna.jpg" :theme="false" />'))
|
||||||
->toContain('<img src="/anna.jpg"')
|
->toContain('<img src="/anna.jpg" alt="" class="size-full rounded-corner-full object-cover" />')
|
||||||
->not->toContain('data-account-theme');
|
->not->toContain('data-account-theme');
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -22,6 +22,8 @@ it('gives the collapsible, modal and adaptive rails a menu button and the store'
|
|||||||
->toContain('data-navigation-rail-menu')
|
->toContain('data-navigation-rail-menu')
|
||||||
->toContain('aria-label="Collapse navigation"')
|
->toContain('aria-label="Collapse navigation"')
|
||||||
->toContain('aria-expanded="true"')
|
->toContain('aria-expanded="true"')
|
||||||
|
// The 40px menu button reaches M3's 48px target through the shared utility (N-01).
|
||||||
|
->toContain('touch-target')
|
||||||
->not->toContain('data-navigation-rail-scrim')
|
->not->toContain('data-navigation-rail-scrim')
|
||||||
->not->toContain('x-trap')
|
->not->toContain('x-trap')
|
||||||
->and((string) $this->blade('<x-navigation-rail mode="modal" />'))
|
->and((string) $this->blade('<x-navigation-rail mode="modal" />'))
|
||||||
|
|||||||
Reference in New Issue
Block a user