From b77c89a6a6cf4b4d17b151d693d56d58a67360a0 Mon Sep 17 00:00:00 2001
From: Maya Kid <29959320+Maya-Kid@users.noreply.github.com>
Date: Thu, 15 Oct 2026 18:42:44 +1100
Subject: [PATCH 1/3] Preserve accessible input names and expandable status
button semantics
Signed-off-by: Maya Kid <29959320+Maya-Kid@users.noreply.github.com>
---
content/solid/composer.mdx | 13 ++++++++++++-
content/solid/turn-status.mdx | 2 ++
src/components/ui/composer.tsx | 4 ++++
src/components/ui/turn-status.tsx | 6 ++++--
src/examples/composer-demo.tsx | 1 +
src/examples/composer-running.tsx | 1 +
6 files changed, 24 insertions(+), 3 deletions(-)
diff --git a/content/solid/composer.mdx b/content/solid/composer.mdx
index 879f51a..86ea7fe 100644
--- a/content/solid/composer.mdx
+++ b/content/solid/composer.mdx
@@ -31,9 +31,19 @@ import { Composer } from "@/components/ui/composer"
```tsx
const [text, setText] = React.useState("")
-
+
```
+`textareaProps` names and describes the input itself. It accepts `id`, `aria-label`,
+`aria-labelledby`, and `aria-describedby`; use its `id` with an external label's
+`htmlFor`. Other HTML attributes, including a top-level `id` or `aria-label`,
+continue to apply to the outer wrapper.
+
## While a turn runs
The send mark has no block behind it in any state: its brightness says what it will do. With `running`, it is the quiet square that stops the turn, until something is typed, which is then sent behind it.
@@ -52,6 +62,7 @@ The send mark has no block behind it in any state: its brightness says what it w
| `onValueChange` | `(value: string) => void` | - |
| `onSubmit` | `(value: string) => void` | - |
| `onStop` | `() => void` | - |
+| `textareaProps` | `Pick, "id" \| "aria-label" \| "aria-labelledby" \| "aria-describedby">` | - |
| `running` | `boolean` | `false` |
| `leading` | `ReactNode` | - |
| `tags` | `ReactNode` | - |
diff --git a/content/solid/turn-status.mdx b/content/solid/turn-status.mdx
index 9ab79a2..0078af8 100644
--- a/content/solid/turn-status.mdx
+++ b/content/solid/turn-status.mdx
@@ -40,6 +40,8 @@ import { TurnStatus } from "@/components/ui/turn-status"
## With steps
Given children, the line is a button and opens to show them: the calls of the step in hand.
+The activity label is announced by a separate status region, so the button keeps
+its native role and updates to the clock and token count do not repeat the announcement.
diff --git a/src/components/ui/composer.tsx b/src/components/ui/composer.tsx
index 697e3ca..57f4241 100644
--- a/src/components/ui/composer.tsx
+++ b/src/components/ui/composer.tsx
@@ -32,6 +32,7 @@ function Composer({
onStop,
running = false,
placeholder,
+ textareaProps,
leading,
tags,
above,
@@ -48,6 +49,8 @@ function Composer({
onStop?: () => void
running?: boolean
placeholder?: string
+ /** Names and describes the input; other HTML attributes belong to the wrapper. */
+ textareaProps?: Pick, "id" | "aria-label" | "aria-labelledby" | "aria-describedby">
leading?: React.ReactNode
tags?: React.ReactNode
/** Stands above the line of text: pictures going with the message. */
@@ -101,6 +104,7 @@ function Composer({
mark is never left on a line of its own. */}