Package views now write <x-livewire-material::button>, so a configured prefix (which Blade spells <x-m::button>) and an application component of the same name can no longer break or shadow them. The showcase rewrites its examples to the configured prefix. Adds the README, and waits for the adaptive rail to hear a resize before the navigation tests press its menu button. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01V9NnLxnPp8vaaurb3Z1MFy
82 lines
3.4 KiB
PHP
82 lines
3.4 KiB
PHP
{{-- One item in an `<x-menu>`: an action, a link, or a choice.
|
|
|
|
`label`, a leading `icon`, an `icon-right`, a `description` 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. `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 want to change twice.
|
|
|
|
44px tall (SegmentedMenuTokens.Item), body-large label, 20px icons, 4px corners that open to
|
|
12px at the ends of the list. --}}
|
|
|
|
@props([
|
|
'label' => null,
|
|
'icon' => null,
|
|
'iconRight' => null,
|
|
'description' => null,
|
|
'shortcut' => null,
|
|
'link' => null,
|
|
'external' => false,
|
|
'noWireNavigate' => false,
|
|
'selected' => null,
|
|
'disabled' => false,
|
|
'keepOpen' => false,
|
|
])
|
|
|
|
@php
|
|
$isLink = filled($link);
|
|
$tag = $isLink ? 'a' : 'button';
|
|
|
|
$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',
|
|
'rounded-corner-xs first:rounded-t-corner-md last:rounded-b-corner-md',
|
|
'transition-[border-radius,background-color] duration-(--md-sys-motion-spatial-fast-duration) ease-spatial-fast',
|
|
'focus-visible:outline-3 focus-visible:-outline-offset-3 focus-visible:outline-secondary',
|
|
'py-2' => filled($description),
|
|
'rounded-corner-md bg-tertiary-container text-on-tertiary-container' => $selected === true,
|
|
'pointer-events-none text-on-surface/38' => $disabled,
|
|
])
|
|
->merge(array_filter([
|
|
'role' => $selected === null ? 'menuitem' : 'menuitemcheckbox',
|
|
'aria-checked' => $selected === null ? null : ($selected ? 'true' : 'false'),
|
|
'aria-disabled' => $disabled ? 'true' : null,
|
|
'tabindex' => '-1',
|
|
'type' => $isLink ? null : 'button',
|
|
'href' => $isLink ? $link : null,
|
|
'target' => $isLink && $external ? '_blank' : null,
|
|
'rel' => $isLink && $external ? 'noopener' : null,
|
|
'wire:navigate' => $isLink && ! $external && ! $noWireNavigate && ! $attributes->has('wire:navigate') ? true : null,
|
|
'data-keep-open' => $keepOpen ? true : null,
|
|
], fn ($value): bool => $value !== null));
|
|
|
|
$iconInk = match (true) {
|
|
$disabled => 'text-on-surface/38',
|
|
$selected === true => 'text-on-tertiary-container',
|
|
default => 'text-on-surface-variant',
|
|
};
|
|
@endphp
|
|
|
|
<{{ $tag }} {{ $attributes }}>
|
|
@if ($icon)
|
|
<x-livewire-material::icon :name="$icon" :filled="$selected === true" :class="'size-5 '.$iconInk" />
|
|
@endif
|
|
|
|
<span class="min-w-0 flex-1">
|
|
<span class="block truncate type-body-lg">{{ $label ?? $slot }}</span>
|
|
|
|
@if ($description)
|
|
<span @class(['block type-body-md', $iconInk])>{{ $description }}</span>
|
|
@endif
|
|
</span>
|
|
|
|
@if ($shortcut)
|
|
<span @class(['shrink-0 type-label-sm', $iconInk])>{{ $shortcut }}</span>
|
|
@endif
|
|
|
|
@if ($iconRight)
|
|
<x-livewire-material::icon :name="$iconRight" :class="'size-5 '.$iconInk" />
|
|
@endif
|
|
</{{ $tag }}>
|