Put the menu on M3's Expressive spacing and behaviour
Items were 44px tall with the baseline menu's 12px sides, the separator had half its 8dp padding, a disabled item was skipped by the keyboard entirely, a chosen item was told by colour and shape alone, and the list simply faded in place. Now: 48px rows with 16px either side, an 8px separator, disabled items focusable but never activatable, a trailing check on a selected item, and an enter-exit that scales the list out of the corner nearest its trigger — the scale on the spatial spring, the fade on the effects one. Plan step 18, actions.md ACT-11, ACT-12, ACT-13, ACT-26, ACT-27, ACT-28. 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
429be9b64f
commit
9828c9258a
@@ -3,7 +3,7 @@
|
||||
@props(['label'])
|
||||
|
||||
<div role="group" aria-label="{{ $label }}" {{ $attributes->class('py-1 first:pt-0 last:pb-0') }}>
|
||||
<div aria-hidden="true" class="px-3 pt-2 pb-1 type-label-lg text-on-surface-variant">{{ $label }}</div>
|
||||
<div aria-hidden="true" class="px-4 pt-2 pb-1 type-label-lg text-on-surface-variant">{{ $label }}</div>
|
||||
|
||||
{{ $slot }}
|
||||
</div>
|
||||
|
||||
@@ -4,11 +4,13 @@
|
||||
under the label and a `shortcut` at the end (M3's trailing supporting text: "⌘C"). `link`
|
||||
makes it an anchor, with `wire:navigate` unless `external` or `no-wire-navigate`. `selected`
|
||||
(true or false) makes it a `menuitemcheckbox` with `aria-checked`; a selected item takes
|
||||
Expressive's selected shape and tertiary-container. `current` is for a menu of places rather
|
||||
Expressive's selected shape and tertiary-container, and a `check` at its end unless it has an
|
||||
`icon-right` of its own — M3 asks for a cue beyond the colour and the shape. `current` is for a menu of places rather
|
||||
than choices — a section picker — and marks the page you are on: `aria-current="page"`, the
|
||||
selected shape in secondary-container, the colour M3 gives the navigation indicator. `badge`
|
||||
draws `<x-badge>` at the end of the row: `true` for a dot, or a count. `disabled` keeps it in the list, out of
|
||||
reach. `keep-open` leaves the menu open when it is activated — for a choice the person may
|
||||
draws `<x-badge>` at the end of the row: `true` for a dot, or a count. `disabled` keeps it in the list, reachable by the
|
||||
keyboard but not selectable — M3 keeps a disabled item focusable so a person can find out it
|
||||
is there. `keep-open` leaves the menu open when it is activated — for a choice the person may
|
||||
want to change twice.
|
||||
|
||||
`icon-class` is for an icon whose colour means something of its own, a sport's glyph in the
|
||||
@@ -17,9 +19,12 @@
|
||||
utilities wins depends on the order Tailwind emits them. A disabled item's icon stays
|
||||
disabled.
|
||||
|
||||
44px tall (SegmentedMenuTokens.Item), body-large label, 20px icons, 4px corners that open to
|
||||
12px at the ends of the list, the corner on the spatial spring and the colour on the effects
|
||||
one (`state-transition-fast`). --}}
|
||||
48px tall, body-large label, 20px icons, 16px either side (SegmentedMenuTokens' Expressive
|
||||
spacing), 4px corners that open to 12px at the ends of the list — the corner on the spatial
|
||||
spring and the colour on the effects one (`state-transition-fast`). The row is 48px rather
|
||||
than SegmentedMenuTokens' 44px: M3's menu page publishes 48dp and asks for ≥48×48 targets
|
||||
inside an item's slots, and the library's own select and choices menus are 48px, so the more
|
||||
binding source wins over the more specific one. --}}
|
||||
|
||||
@props([
|
||||
'label' => null,
|
||||
@@ -44,7 +49,7 @@
|
||||
|
||||
$attributes = $attributes
|
||||
->class([
|
||||
'group/item state-layer flex w-full min-h-11 cursor-pointer items-center gap-3 px-3 text-start outline-none',
|
||||
'group/item state-layer flex w-full min-h-12 cursor-pointer items-center gap-3 px-4 text-start outline-none',
|
||||
'rounded-corner-xs first:rounded-t-corner-md last:rounded-b-corner-md',
|
||||
'state-transition-fast',
|
||||
'focus-visible:outline-3 focus-visible:-outline-offset-3 focus-visible:outline-secondary',
|
||||
@@ -105,5 +110,8 @@
|
||||
|
||||
@if ($iconRight)
|
||||
<x-livewire-material::icon :name="$iconRight" optical="20" :class="'size-5 '.$iconInk" />
|
||||
@elseif ($selected === true)
|
||||
{{-- The third cue M3 recommends, so a chosen item is not told by colour and shape alone. --}}
|
||||
<x-livewire-material::icon name="check" optical="20" :class="'size-5 '.$iconInk" />
|
||||
@endif
|
||||
</{{ $tag }}>
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
{{-- A line between groups of items in an `<x-menu>`. --}}
|
||||
{{-- A line between groups of items in an `<x-menu>`: 1px, with M3's 8px above and below it, inset
|
||||
to the 16px the items keep either side. --}}
|
||||
|
||||
<hr role="separator" {{ $attributes->class('mx-3 my-1 h-px border-0 bg-outline-variant') }} />
|
||||
<hr role="separator" {{ $attributes->class('mx-4 my-2 h-px border-0 bg-outline-variant') }} />
|
||||
|
||||
@@ -34,7 +34,11 @@
|
||||
|
||||
A menu too long for the window scrolls, as M3 asks, rather than running off the edge of the
|
||||
top layer where nothing can reach it: 18rem at most, and less on a short window. The arrow
|
||||
keys, Home, End and typeahead bring the item they move to into view.
|
||||
keys, Home, End and typeahead bring the item they move to into view, and a disabled item is
|
||||
among them: M3 keeps one reachable so a person can find out that it exists.
|
||||
|
||||
It opens by growing out of the corner nearest its trigger and fades as it goes
|
||||
(`popover-transition`), which is the transition M3 asks to tie a menu to what opened it.
|
||||
|
||||
The container is Expressive's standard menu (surface-container-low, 16px corner, elevation
|
||||
2), or `vibrant` in tertiary-container — StandardMenuTokens and VibrantMenuTokens from
|
||||
@@ -73,13 +77,13 @@
|
||||
@class([
|
||||
'm-0 min-w-28 max-w-70 max-h-[min(18rem,calc(100dvh-2rem))] overflow-y-auto border-0 p-1 rounded-corner-lg shadow-elevation-2 [inset:auto]',
|
||||
'my-1 [position-try-fallbacks:flip-block,flip-inline,flip-block_flip-inline]',
|
||||
'opacity-0 transition-[opacity,translate,display,overlay] transition-discrete duration-(--md-sys-motion-effects-fast-duration) ease-effects-fast open:opacity-100 starting:open:opacity-0',
|
||||
'popover-transition',
|
||||
'bg-surface-container-low text-on-surface' => ! $vibrant,
|
||||
'bg-tertiary-container text-on-tertiary-container' => $vibrant,
|
||||
'[position-area:bottom_span-right]' => $position === 'bottom-start',
|
||||
'[position-area:bottom_span-left]' => $position === 'bottom-end',
|
||||
'[position-area:top_span-right]' => $position === 'top-start',
|
||||
'[position-area:top_span-left]' => $position === 'top-end',
|
||||
'origin-top [position-area:bottom_span-right]' => $position === 'bottom-start',
|
||||
'origin-top [position-area:bottom_span-left]' => $position === 'bottom-end',
|
||||
'origin-bottom [position-area:top_span-right]' => $position === 'top-start',
|
||||
'origin-bottom [position-area:top_span-left]' => $position === 'top-end',
|
||||
])
|
||||
>
|
||||
{{ $slot }}
|
||||
|
||||
Reference in New Issue
Block a user