authorgravatar for 55418374+Leos-Khai@users.noreply.github.comKhai Shern, Toh <55418374+Leos-Khai@users.noreply.github.com> 2026-09-21 05:46:08+08:00
committergravatar for noreply@github.comGitHub <noreply@github.com> 2026-09-20 18:46:08-03:00
log45e06f48a03354b600782259010ae6222241aff0
treebe1cde3cca5f79db5c0caf0aeae44c36264be370
parent2d8f9a8f55d2195ac820c91f0f1e8f66a055f841
signature Signed by PGP key B5690EEEBB952194

fix: composer hero reads project name to screen readers (#12397)


2 files changed, 20 insertions(+), 6 deletions(-)

apps/mobile/src/features/threads/NewTaskDraftScreen.tsx+1-1
......@@ -1455,7 +1455,7 @@ export function NewTaskDraftScreen(props: {
14551455 <Text className="text-2xl font-t3-medium tracking-tight text-foreground">in </Text>
14561456 <Pressable
14571457 accessibilityHint="Opens the project picker"
1458 accessibilityLabel={`Change project from ${selectedProject.title}`}
1458 accessibilityLabel={selectedProject.title}
14591459 accessibilityRole="button"
14601460 disabled={isComposerInteractionLocked}
14611461 onPress={chooseProject}
apps/web/src/components/chat/DraftHeroHeadline.tsx+19-5
......@@ -136,10 +136,11 @@ export function DraftHeroHeadline({
136136 <Tooltip>
137137 <TooltipTrigger
138138 render={
139 <MenuTrigger
140 aria-label={hasResolvedProject ? "Change project" : "Choose a project"}
141 className="pointer-events-auto inline-block max-w-64 truncate border-foreground/60 border-b border-dotted align-baseline text-foreground transition-colors hover:border-foreground/80 focus-visible:rounded-sm focus-visible:outline-hidden focus-visible:ring-2 focus-visible:ring-ring"
142 />
139 // The trigger's accessible name comes from its visible text (the
140 // project title) so the hero sentence reads naturally: an
141 // aria-label here would replace the title with an action phrase
142 // mid-sentence and baffle screen-reader users.
143 <MenuTrigger className="pointer-events-auto inline-block max-w-64 truncate border-foreground/60 border-b border-dotted align-baseline text-foreground transition-colors hover:border-foreground/80 focus-visible:rounded-sm focus-visible:outline-hidden focus-visible:ring-2 focus-visible:ring-ring" />
143144 }
144145 >
145146 {activeProjectDisplayName ?? "Choose a project"}
......@@ -233,8 +234,21 @@ export function DraftHeroHeadline({
233234 </button>
234235 );
235236
237 // The composer hero is a sentence, so the heading's accessible name must be
238 // a complete sentence too. The project picker is a control rendered inline
239 // in the h1; without an explicit label its widget state bleeds into the
240 // announced phrase.
241 const headingLabel = hasResolvedProject
242 ? `What should we build in ${activeProjectDisplayName}?`
243 : canChooseProject
244 ? `${activeProjectDisplayName ?? "Choose a project"} to start`
245 : "Add a project to start";
246
236247 return (
237 <h1 className="mx-auto w-full max-w-5xl text-center font-normal text-2xl text-foreground tracking-tight sm:text-3xl">
248 <h1
249 aria-label={headingLabel}
250 className="mx-auto w-full max-w-5xl text-center font-normal text-2xl text-foreground tracking-tight sm:text-3xl"
251 >
238252 {hasResolvedProject ? (
239253 <>What should we build in {projectSelector}?</>
240254 ) : canChooseProject ? (