Draw the theme toggle without Tailwind

Plan step 36 (navigation group, third batch): <x-theme-toggle>'s icon
button (mode="toggle"|"cycle") moves into resources/css/components/
theme-toggle.css, keyed on data-md-theme-toggle="toggle"|"cycle" and
still carrying data-md-icon-button, the hook toolbar.css matches
generically so the toggle takes a toolbar's own icon colour when
placed in one (N-13). The button renders the shared md-state-layer/
md-touch-target/md-focus-ring classes (N-01's 48px target); its
corner morphs from full to sm while pressed on the fast spatial
spring, the same motion <x-button>'s own icon buttons take.

mode="picker"|"contrast" already drew a connected group over native
radios (N-04, N-17's fix), so only its wrapper's hook needed renaming.

Hook renamed: data-theme-toggle to data-md-theme-toggle, updated in
AppBarTest.php, which carries theme-toggle's render tests.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Qwx5USif3wFFmxtHg5U1g9
This commit is contained in:
Andreas Reinhold / reini
2026-09-15 00:45:09 +02:00
co-authored by Claude Sonnet 5
parent f5c90c3874
commit 74cbcd2f44
5 changed files with 65 additions and 8 deletions
+15 -5
View File
@@ -218,7 +218,7 @@ it('keeps a toolbar at the bottom clear of the navigation bar', function () {
it('offers M3\'s three contrast levels, marking the one in force', function () {
expect((string) $this->blade('<x-theme-toggle mode="contrast" />'))
->toContain('data-theme-toggle="contrast"')
->toContain('data-md-theme-toggle="contrast"')
->toContain('aria-label="Contrast"')
// A connected button group over native radios, not the deprecated segmented button (N-04).
->toContain('data-md-button-group="connected"')
@@ -242,20 +242,30 @@ it('names a theme row for a screen reader and legends it on request', function (
it('switches the theme through the store in three shapes', function () {
expect((string) $this->blade('<x-theme-toggle />'))
->toContain('data-theme-toggle="toggle"')
->toContain('data-md-theme-toggle="toggle"')
->toContain('data-md-icon-button')
->toContain('aria-label="Dark theme"')
// 40px drawn, 48px reached: M3's minimum target (N-01).
->toContain('touch-target')
->toContain('md-touch-target')
->toContain('$store.theme.toggle()')
->and((string) $this->blade('<x-theme-toggle mode="cycle" />'))
->toContain('data-theme-toggle="cycle"')
->toContain('data-md-theme-toggle="cycle"')
->toContain("{ light: 'dark', dark: 'system', system: 'light' }")
->and((string) $this->blade('<x-theme-toggle mode="picker" />'))
->toContain('data-theme-toggle="picker"')
->toContain('data-md-theme-toggle="picker"')
->toContain('x-model="chosen"')
->toContain('name="material-theme"')
->toContain('value="system"')
->toContain('$store.theme.set(value)');
$css = ComponentStylesheet::read('theme-toggle');
// The corner morphs from full to sm while pressed, the same motion <x-button>'s own icon
// buttons take (button.css), on the fast spatial spring.
expect($css->declarations("[data-md-theme-toggle='toggle'], [data-md-theme-toggle='cycle']"))
->toHaveKey('border-radius', 'var(--md-sys-shape-corner-full)')
->and($css->declarations("[data-md-theme-toggle='toggle']:active, [data-md-theme-toggle='cycle']:active"))
->toBe(['border-radius' => 'var(--md-sys-shape-corner-sm)']);
});
it('opens an account menu from the initials of a name', function () {
@@ -34,6 +34,7 @@ dataset('navigation components', [
'navigation-rail-section',
'section-nav',
'account-menu',
'theme-toggle',
]);
/**