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
77 lines
4.2 KiB
PHP
77 lines
4.2 KiB
PHP
{{-- Switches the colour theme through `$store.theme` (resources/js/theme.js), so every toggle on a
|
|
page reads and writes the one choice and none needs an id.
|
|
|
|
`mode`:
|
|
- `toggle` (the default): an icon button between light and dark. The icon is where it takes
|
|
you — a sun while the page is dark, a moon while it is light — and it is a toggle button,
|
|
"Dark theme", pressed while dark.
|
|
- `cycle`: an icon button that steps light → dark → system, showing the choice it is on.
|
|
- `picker`: M3's segmented buttons for the three choices, for a settings page.
|
|
|
|
The theme is the visitor's, known only in the browser, so the parts that depend on it wait for
|
|
Alpine (`x-cloak`) rather than render a guess. `class` lands on the button or the group. --}}
|
|
|
|
@props([
|
|
'mode' => 'toggle',
|
|
])
|
|
|
|
@php
|
|
$mode = in_array($mode, ['toggle', 'cycle', 'picker'], true) ? $mode : 'toggle';
|
|
@endphp
|
|
|
|
@if ($mode === 'picker')
|
|
<div
|
|
role="radiogroup"
|
|
aria-label="{{ __('Theme') }}"
|
|
x-data
|
|
data-theme-toggle="picker"
|
|
{{ $attributes->class(['inline-flex h-10 rounded-corner-full border border-outline']) }}
|
|
>
|
|
@foreach (['light' => ['Light', 'light_mode'], 'dark' => ['Dark', 'dark_mode'], 'system' => ['System', 'brightness_auto']] as $choice => [$text, $icon])
|
|
<button
|
|
type="button"
|
|
role="radio"
|
|
aria-checked="false"
|
|
x-bind:aria-checked="($store.theme.choice === '{{ $choice }}').toString()"
|
|
x-bind:tabindex="$store.theme.choice === '{{ $choice }}' ? 0 : -1"
|
|
x-on:click="$store.theme.set('{{ $choice }}')"
|
|
x-on:keydown.arrow-right.prevent="$el.nextElementSibling?.click(); $el.nextElementSibling?.focus();"
|
|
x-on:keydown.arrow-left.prevent="$el.previousElementSibling?.click(); $el.previousElementSibling?.focus();"
|
|
data-theme-option="{{ $choice }}"
|
|
class="state-layer focus-ring inline-flex min-w-0 flex-1 cursor-pointer items-center justify-center gap-2 border-outline px-3 type-label-lg text-on-surface not-first:border-s first:rounded-s-corner-full last:rounded-e-corner-full aria-checked:bg-secondary-container aria-checked:text-on-secondary-container"
|
|
>
|
|
<x-livewire-material::icon name="check" class="hidden size-4.5 in-aria-checked:block" />
|
|
<x-livewire-material::icon :name="$icon" class="size-4.5 in-aria-checked:hidden" />
|
|
{{ __($text) }}
|
|
</button>
|
|
@endforeach
|
|
</div>
|
|
@else
|
|
<button
|
|
type="button"
|
|
x-data
|
|
data-icon-button
|
|
data-theme-toggle="{{ $mode }}"
|
|
@if ($mode === 'cycle')
|
|
aria-label="{{ __('Theme') }}"
|
|
x-bind:aria-label="{ light: @js(__('Theme: light')), dark: @js(__('Theme: dark')), system: @js(__('Theme: system')) }[$store.theme.choice]"
|
|
x-on:click="$store.theme.set({ light: 'dark', dark: 'system', system: 'light' }[$store.theme.choice])"
|
|
@else
|
|
aria-label="{{ __('Dark theme') }}"
|
|
aria-pressed="false"
|
|
x-bind:aria-pressed="($store.theme.resolved === 'dark').toString()"
|
|
x-on:click="$store.theme.toggle()"
|
|
@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']) }}
|
|
>
|
|
@if ($mode === 'cycle')
|
|
<x-livewire-material::icon name="light_mode" x-cloak x-show="$store.theme.choice === 'light'" />
|
|
<x-livewire-material::icon name="dark_mode" x-cloak x-show="$store.theme.choice === 'dark'" />
|
|
<x-livewire-material::icon name="brightness_auto" x-cloak x-show="$store.theme.choice === 'system'" />
|
|
@else
|
|
<x-livewire-material::icon name="light_mode" x-cloak x-show="$store.theme.resolved === 'dark'" />
|
|
<x-livewire-material::icon name="dark_mode" x-cloak x-show="$store.theme.resolved !== 'dark'" />
|
|
@endif
|
|
</button>
|
|
@endif
|