diff --git a/src/components/medications/scheduling/CadencePicker.tsx b/src/components/medications/scheduling/CadencePicker.tsx index 85b886448..7a84ef0b5 100644 --- a/src/components/medications/scheduling/CadencePicker.tsx +++ b/src/components/medications/scheduling/CadencePicker.tsx @@ -308,7 +308,13 @@ function CadenceOption({ data-slot="cadence-option" data-kind={kind} > -
+ {/* Wrapping the row in
+ {label} + {selected && kind === "weekdays" && (
diff --git a/src/components/medications/scheduling/CreationWizard.tsx b/src/components/medications/scheduling/CreationWizard.tsx index acac32ecb..f0564a4e7 100644 --- a/src/components/medications/scheduling/CreationWizard.tsx +++ b/src/components/medications/scheduling/CreationWizard.tsx @@ -72,7 +72,7 @@ * .errors.fieldRequired — "Required" */ -import { useCallback, useMemo, useState } from "react"; +import { useCallback, useEffect, useMemo, useRef, useState } from "react"; import { useRouter } from "next/navigation"; import { useQueryClient } from "@tanstack/react-query"; import { Loader2, Sparkles } from "lucide-react"; @@ -522,10 +522,37 @@ export function CreationWizard({ const [submitError, setSubmitError] = useState(null); const [fieldErrors, setFieldErrors] = useState>({}); + // Ref on the step body so we can pull focus into the first + // interactive control whenever the wizard advances. Without this a + // keyboard / screen-reader user stays parked on the Back / Next + // button across step transitions instead of landing on the new + // step's input. + const bodyRef = useRef(null); + const isFirstRenderRef = useRef(true); + const applyPartial = useCallback((partial: Partial) => { setPayload((prev) => ({ ...prev, ...partial })); }, []); + // Focus the first interactive element when the step changes. + // Skip the initial render so opening the wizard never steals focus + // from the page chrome. + useEffect(() => { + if (isFirstRenderRef.current) { + isFirstRenderRef.current = false; + return; + } + const node = bodyRef.current; + if (!node) return; + const target = node.querySelector( + 'input:not([disabled]):not([type="hidden"]), select:not([disabled]), textarea:not([disabled]), button:not([disabled]), [tabindex]:not([tabindex="-1"])', + ); + if (!target) return; + // preventScroll keeps the focus jump silent for reduced-motion + // users; the surrounding layout already keeps the body in view. + target.focus({ preventScroll: true }); + }, [step]); + const canContinue = useMemo( () => validateStep(payload, step), [payload, step], @@ -627,7 +654,7 @@ export function CreationWizard({

{stepOf}

{stepTitle} - + {step === 1 && (