Finish the keyboards, and say a state once

Shift+M and Shift+Y reach the month and year dropdowns, which is M3's
date picker keyboard table; Home and End go to the ends of an open
combobox list, and stay the field's own caret keys when it is closed. The
password reveal drops aria-pressed and keeps only its flipping label, so
a screen reader hears the state once rather than twice and inverted. The
radio's `inline` now says that M3 cautions against a row and wants an
option chosen on load.

Plan step 20, findings IN-22, IN-23, IN-28 and IN-29.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Qwx5USif3wFFmxtHg5U1g9
This commit is contained in:
Andreas Reinhold / reini
2026-09-14 06:13:00 +02:00
co-authored by Claude Fable 5.1
parent 856b6f476b
commit 0074f9bd5c
10 changed files with 69 additions and 14 deletions
+1 -1
View File
@@ -116,7 +116,7 @@ it('shows and hides a password', function () {
->type('#password-field', 'secret')
->click('[data-field-reveal]')
->assertScript("document.querySelector('#password-field').type === 'text'")
->assertAttribute('[data-field-reveal]', 'aria-pressed', 'true')
->assertAttribute('[data-field-reveal]', 'aria-label', 'Hide password')
->click('[data-field-reveal]')
->assertScript("document.querySelector('#password-field').type === 'password'");
});
+3
View File
@@ -52,6 +52,9 @@ it('draws a searchable combobox with a popover list', function () {
->toMatch('/anchor-name: (--material-choices-[a-z0-9]{10})/')
->toContain('x-modelable="value"')
->toContain('field-arrow')
// WAI-ARIA's combobox keyboard, Home and End included.
->toContain('x-on:keydown.home="jump($event, false)"')
->toContain('x-on:keydown.end="jump($event, true)"')
->toContain('Nothing matches');
preg_match('/anchor-name: (--material-choices-[a-z0-9]{10})/', $html, $anchor);
@@ -54,6 +54,14 @@ it('makes the field a read-only trigger for the modal and modal input pickers',
->and(datepickerConfig($html)['mode'])->toBe($mode);
})->with(['modal', 'input']);
it('names each dropdown so Shift+M and Shift+Y can reach it', function () {
$html = (string) $this->blade('<x-datepicker label="Birthday" />');
expect($html)
->toContain('data-datepicker-menu-button="months"')
->toContain('data-datepicker-menu-button="years"');
});
it('falls back to the docked picker for an unknown mode', function () {
expect(datepickerConfig((string) $this->blade('<x-datepicker label="Date" mode="wheel" />'))['mode'])->toBe('docked');
});
+3 -1
View File
@@ -93,7 +93,9 @@ it('lets a password be shown and hidden again', function () {
->not->toContain('type="text"')
->toContain('x-bind:type="shown ? \'text\' : \'password\'"')
->toContain('data-field-reveal')
->toContain('aria-pressed="false"')
->toContain('aria-label="Show password"')
// The flipping label already says the state; aria-pressed would say it again, inverted.
->not->toContain('aria-pressed')
->toContain('autocomplete="current-password"');
});