From 934aad2afd4c32fd11e7f92473c8513c0ac5c2de Mon Sep 17 00:00:00 2001 From: FragginWagon Date: Thu, 10 Sep 2026 06:37:02 -0400 Subject: [PATCH] feat: manage focus and announce steps in guided wizard --- apps/web/src/assets/styles/global.scss | 2 + apps/web/src/pages/AdminHomePage.stories.js | 19 +++++++++ apps/web/src/pages/AdminHomePage.vue | 46 +++++++++++++++------ docs/IMPLEMENTATION-STATUS.md | 1 + 4 files changed, 55 insertions(+), 13 deletions(-) diff --git a/apps/web/src/assets/styles/global.scss b/apps/web/src/assets/styles/global.scss index f201145..a4da689 100644 --- a/apps/web/src/assets/styles/global.scss +++ b/apps/web/src/assets/styles/global.scss @@ -9,6 +9,7 @@ button, input, select, textarea { font: inherit; } button, a, input, select, textarea { &:focus-visible { outline: var(--border-strong) solid var(--color-focus); outline-offset: 3px; box-shadow: var(--glow-focus); } } button { cursor: pointer; } h1, h2, h3, h4 { margin: 0; font-family: var(--font-display); line-height: var(--leading-tight); } +.visually-hidden { position: absolute; width: 1px; height: 1px; margin: -1px; border: 0; padding: 0; overflow: hidden; clip: rect(0, 0, 0, 0); white-space: nowrap; } .catalog-page, .detail-page, .showcase-page { min-height: 100vh; background: var(--color-background); } .catalog-header, .catalog-results { width: min(1120px, calc(100% - var(--space-8))); margin: 0 auto; } @@ -55,6 +56,7 @@ h1 { max-width: 760px; margin: var(--space-3) 0 var(--space-4); font-size: var(- .admin-workspace-grid form { display: grid; gap: var(--space-3); } .admin-wizard { display: grid; gap: var(--space-4); margin: var(--space-8) 0; } .admin-wizard__nav { display: flex; justify-content: space-between; gap: var(--space-3); } +.admin-wizard > [role="region"]:focus { outline: var(--border-strong) solid var(--color-focus); outline-offset: 3px; } .admin-list { margin-top: var(--space-8); } .admin-list h2 { margin-bottom: var(--space-3); font-size: var(--text-xl); } .admin-list ul { display: grid; gap: var(--space-2); margin: 0; padding: 0; list-style: none; } diff --git a/apps/web/src/pages/AdminHomePage.stories.js b/apps/web/src/pages/AdminHomePage.stories.js index 354dbbd..0463106 100644 --- a/apps/web/src/pages/AdminHomePage.stories.js +++ b/apps/web/src/pages/AdminHomePage.stories.js @@ -1,8 +1,27 @@ +import { expect, userEvent, within } from "@storybook/test"; + import AdminHomePage from "./AdminHomePage.vue"; export default { title: "Pages/AdminHomePage", component: AdminHomePage }; export const Overview = {}; +export const WizardStepFocusManagement = { + parameters: { + docs: { + description: { + story: + "Selecting a wizard stage moves focus to that stage's panel and announces the step change for assistive technology.", + }, + }, + }, + play: async ({ canvasElement }) => { + const canvas = within(canvasElement); + await userEvent.click(canvas.getByRole("button", { name: /Sources/ })); + await expect(canvas.getByRole("region", { name: "Sources step" })).toHaveFocus(); + await expect(await canvas.findByText("Step 2 of 6: Sources - Link markets")).toBeInTheDocument(); + }, +}; + export const ProviderMappingWorkflow = { parameters: { docs: { diff --git a/apps/web/src/pages/AdminHomePage.vue b/apps/web/src/pages/AdminHomePage.vue index 63a0587..5a59321 100644 --- a/apps/web/src/pages/AdminHomePage.vue +++ b/apps/web/src/pages/AdminHomePage.vue @@ -1,5 +1,5 @@