From 45e06f48a03354b600782259010ae6222241aff0 Mon Sep 17 00:00:00 2001
From: "Khai Shern, Toh" <55418374+Leos-Khai@users.noreply.github.com>
Date: Mon, 21 Sep 2026 05:46:08 +0800
Subject: [PATCH] fix: composer hero reads project name to screen readers
(#12397)
---
.../features/threads/NewTaskDraftScreen.tsx | 2 +-
.../src/components/chat/DraftHeroHeadline.tsx | 24 +++++++++++++++----
2 files changed, 20 insertions(+), 6 deletions(-)
diff --git a/apps/mobile/src/features/threads/NewTaskDraftScreen.tsx b/apps/mobile/src/features/threads/NewTaskDraftScreen.tsx
index 9732ed6865f54e6d459f76ba6d255eafa6f7d45a..681f6c5ee52d16ce253a59e34371ab247747bc73 100644
--- a/apps/mobile/src/features/threads/NewTaskDraftScreen.tsx
+++ b/apps/mobile/src/features/threads/NewTaskDraftScreen.tsx
@@ -1455,7 +1455,7 @@ export function NewTaskDraftScreen(props: {
in
+ // The trigger's accessible name comes from its visible text (the
+ // project title) so the hero sentence reads naturally: an
+ // aria-label here would replace the title with an action phrase
+ // mid-sentence and baffle screen-reader users.
+
}
>
{activeProjectDisplayName ?? "Choose a project"}
@@ -233,8 +234,21 @@ export function DraftHeroHeadline({
);
+ // The composer hero is a sentence, so the heading's accessible name must be
+ // a complete sentence too. The project picker is a control rendered inline
+ // in the h1; without an explicit label its widget state bleeds into the
+ // announced phrase.
+ const headingLabel = hasResolvedProject
+ ? `What should we build in ${activeProjectDisplayName}?`
+ : canChooseProject
+ ? `${activeProjectDisplayName ?? "Choose a project"} to start`
+ : "Add a project to start";
+
return (
-
+
{hasResolvedProject ? (
<>What should we build in {projectSelector}?>
) : canChooseProject ? (
--
2.54.0