Draw the scheme picker without Tailwind
Plan step 36 (navigation group, third batch, last component):
<x-scheme-picker>'s class lists move into resources/css/components/
scheme-picker.css, keyed on data-md-scheme-picker (its legend and
options grid, 2 columns below medium and 4 from it) and
data-md-scheme-picker-option, whose radio inside is read with :has()
for the chosen and the focus states — the input, not the label, is
the real control and carries the ring group.css's own segments keep
the same refinement for. `dark:bg-(--swatch-dark)` becomes
[data-theme='dark'] on the swatch (theme.css's own dark custom
variant reduces to a plain descendant selector here, since the
swatch never carries data-theme itself); the profile's name keeps its
label-large type as a text class on the view, since it is the
caller's own prose.
Hooks renamed: data-scheme-picker to data-md-scheme-picker,
data-scheme-option to data-md-scheme-picker-option, updated in
SchemePickerTest.php and tests/Browser/{ThemeTest,ColourProfilesTest}.php.
Browser tests added (docs/plans/material-3-browser-tests.md): the
contrast switch repaints at once and survives a wire:navigate, and
prefers-contrast: more picks high (Playwright's contrast context
option, the same shape as the existing reducedMotion tests).
This is the last navigation-group component off Tailwind. Every
package component is now drawn without Tailwind; tailwind.css keeps
only tokens/theme.css and tokens/utilities.css, which the showcase
still needs until step 38.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Qwx5USif3wFFmxtHg5U1g9
This commit is contained in:
co-authored by
Claude Sonnet 5
parent
74cbcd2f44
commit
bc284b2b33
@@ -52,46 +52,42 @@
|
||||
@if ($profiles !== [])
|
||||
<fieldset
|
||||
x-data="{ swatches: @js($swatches) }"
|
||||
data-scheme-picker
|
||||
{{ $attributes->whereDoesntStartWith(['wire:model', 'x-model'])->except('name')->class('min-w-0') }}
|
||||
data-md-scheme-picker
|
||||
{{ $attributes->whereDoesntStartWith(['wire:model', 'x-model'])->except('name') }}
|
||||
>
|
||||
@if (filled($label))
|
||||
<legend class="mb-2 type-label-lg text-on-surface-variant">{{ $label }}</legend>
|
||||
<legend data-md-scheme-picker-legend class="md-type-label-lg md-ink-variant">{{ $label }}</legend>
|
||||
@endif
|
||||
|
||||
<div class="grid grid-cols-2 gap-2 medium:grid-cols-4">
|
||||
<div data-md-scheme-picker-options>
|
||||
@foreach ($profiles as $profile => $scheme)
|
||||
<label
|
||||
data-scheme-option="{{ $profile }}"
|
||||
class="state-layer flex min-w-0 cursor-pointer select-none flex-col items-start gap-2 rounded-corner-lg border border-outline-variant bg-surface-container-low p-3 text-on-surface transition-[background-color,border-color] duration-(--md-sys-motion-effects-fast-duration) ease-effects-fast has-checked:border-transparent has-checked:bg-secondary-container has-checked:text-on-secondary-container has-focus-visible:outline-3 has-focus-visible:outline-offset-2 has-focus-visible:outline-secondary"
|
||||
>
|
||||
<label data-md-scheme-picker-option="{{ $profile }}" class="md-state-layer">
|
||||
<input
|
||||
{{ $attributes->whereStartsWith(['wire:model', 'x-model']) }}
|
||||
type="radio"
|
||||
name="{{ $name }}"
|
||||
value="{{ $profile }}"
|
||||
x-on:change="$store.theme.previewScheme($event.target.value)"
|
||||
class="peer sr-only"
|
||||
/>
|
||||
|
||||
<span class="flex shrink-0 -space-x-1.5" aria-hidden="true">
|
||||
<span data-md-scheme-picker-swatches aria-hidden="true">
|
||||
@foreach ($roles as $role)
|
||||
<span
|
||||
data-md-scheme-picker-swatch
|
||||
style="--swatch-light: {{ $scheme['light'][$role] }}; --swatch-dark: {{ $scheme['dark'][$role] }}"
|
||||
x-bind:style="{
|
||||
'--swatch-light': swatches['{{ $profile }}'][$store.theme.resolvedContrast].light['{{ $role }}'],
|
||||
'--swatch-dark': swatches['{{ $profile }}'][$store.theme.resolvedContrast].dark['{{ $role }}'],
|
||||
}"
|
||||
class="size-5 rounded-corner-full bg-(--swatch-light) ring-2 ring-surface-container-low in-has-checked:ring-secondary-container dark:bg-(--swatch-dark)"
|
||||
></span>
|
||||
@endforeach
|
||||
</span>
|
||||
|
||||
<span class="w-full truncate pe-6 type-label-lg">{{ __($scheme['label']) }}</span>
|
||||
<span data-md-scheme-picker-label class="md-truncate md-type-label-lg">{{ __($scheme['label']) }}</span>
|
||||
|
||||
{{-- In the corner, so a long name keeps its room. The wrapper carries the position. --}}
|
||||
<span class="pointer-events-none absolute end-2 top-2 hidden peer-checked:block">
|
||||
<x-livewire-material::icon name="check" class="size-5" />
|
||||
<span data-md-scheme-picker-check>
|
||||
<x-livewire-material::icon name="check" :size="20" />
|
||||
</span>
|
||||
</label>
|
||||
@endforeach
|
||||
@@ -99,10 +95,10 @@
|
||||
|
||||
@if ($messages !== [])
|
||||
@foreach ($messages as $message)
|
||||
<p class="mt-1 type-body-sm text-error">{{ $message }}</p>
|
||||
<p data-md-scheme-picker-hint class="md-type-body-sm md-ink-error">{{ $message }}</p>
|
||||
@endforeach
|
||||
@elseif (filled($hint))
|
||||
<p class="mt-1 type-body-sm text-on-surface-variant">{{ $hint }}</p>
|
||||
<p data-md-scheme-picker-hint class="md-type-body-sm md-ink-variant">{{ $hint }}</p>
|
||||
@endif
|
||||
</fieldset>
|
||||
@endif
|
||||
|
||||
Reference in New Issue
Block a user