fix(journey-editor): remove-confirm focus, role=group, Escape key

Focus moves to Cancel when confirm appears (no focus-drops-to-body),
confirm area has role=group with aria-label, and Escape dismisses.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
Marcel
2026-06-10 19:32:16 +02:00
parent 585244d65b
commit 74b94ccd84
2 changed files with 61 additions and 2 deletions

View File

@@ -221,6 +221,60 @@ describe('JourneyItemRow — remove confirm', () => {
});
});
describe('JourneyItemRow — remove confirm a11y', () => {
it('confirm area is wrapped in role=group with an accessible label', async () => {
render(JourneyItemRow, {
item: docItem({ note: 'Wichtige Notiz' }),
...defaultProps()
});
await userEvent.click(page.getByRole('button', { name: m.journey_remove_item_aria() }));
const group = document.querySelector('[role="group"]');
expect(group).toBeTruthy();
expect(group!.getAttribute('aria-label')).toBeTruthy();
});
it('keyboard focus moves to Cancel button when confirm appears', async () => {
render(JourneyItemRow, {
item: docItem({ note: 'Wichtige Notiz' }),
...defaultProps()
});
await userEvent.click(page.getByRole('button', { name: m.journey_remove_item_aria() }));
await vi.waitFor(() => {
const cancelBtn = page
.getByRole('button', { name: m.journey_remove_confirm_cancel() })
.element();
expect(document.activeElement).toBe(cancelBtn);
});
});
it('pressing Escape while confirm is open hides confirm and refocuses remove button', async () => {
render(JourneyItemRow, {
item: docItem({ note: 'Wichtige Notiz' }),
...defaultProps()
});
await userEvent.click(page.getByRole('button', { name: m.journey_remove_item_aria() }));
await vi.waitFor(() => {
const cancelBtn = page
.getByRole('button', { name: m.journey_remove_confirm_cancel() })
.element();
expect(document.activeElement).toBe(cancelBtn);
});
await userEvent.keyboard('{Escape}');
await vi.waitFor(() => {
const removeBtn = page.getByRole('button', { name: m.journey_remove_item_aria() }).element();
expect(document.activeElement).toBe(removeBtn);
});
await expect.element(page.getByText(m.journey_remove_confirm())).not.toBeInTheDocument();
});
});
describe('JourneyItemRow — pending remove state', () => {
it('renders dimmed with the pending text and without a remove button', async () => {
render(JourneyItemRow, {