| Data integrity |
A send, an edit, a mode switch, or a saved draft never drops text, formatting, or media. A failed send keeps its text for another try, and never posts twice. The one exception is a draft upload that the daily cleanup removed, and its tile says it expired. |
Common practice in chat products |
| What you see is what you send |
The composer offers only formatting that the sent message keeps. An edit with no text and no attachment left never offers a send that must fail. |
Common practice in rich text chat |
| First message |
The first message or comment on a heading with no channel row creates the row and sends. |
Common practice in chat products |
| Voice notes |
Release ends a hold. A slide cancels or locks. The composer's 5-minute cap stops a long note. |
Slide to cancel and slide to lock follow Telegram and WhatsApp. There, release sends the note. Here, release shows a preview, as #265 asks. The cap is the composer's own limit. |
| Keyboard |
Escape closes one layer at a time. |
WAI-ARIA Authoring Practices, combobox and dialog patterns |
| Overlays |
One composer overlay is open at a time. The link dialog leaves the soft keyboard as it found it, except where #285 changes the rule on purpose. |
The chatroom and extensions agent docs |
| Focus |
No positive tabindex, and focus follows the visual order. A chat open that asks for focus gets it. |
WCAG 2.2, success criterion 2.4.3 |
| Names, roles, and states |
Every control has an accessible name. A toggle exposes its state. Menus, lists, and handles work with a keyboard. Live regions do not repeat. |
WCAG 2.2, success criteria 4.1.2 and 4.1.3, and the WAI-ARIA Authoring Practices |
| Toolbar state |
A format button shows its active state as the caret moves. |
Common practice in rich text toolbars |
| Touch targets |
The composer row buttons and every control that #279 lists have a touch target of at least 44 × 44 px on a phone. |
The design system ComposerBar row: "action targets 44px mobile". WCAG 2.2, success criterion 2.5.8, sets 24 px as the floor. |
| File limits |
A file over the size limit that the composer does not downscale is refused when it is added. A size failure offers no Retry. |
Common practice in chat products |
| Layout and loading |
A skeleton has the size of what replaces it, and never stays next to an error. A signed-in member sees the composer, not a join prompt. |
Core Web Vitals, Cumulative Layout Shift |
| Notifications |
A mention notifies the named member, and an email address mentions nobody. |
Common practice in chat products |
| Verification |
Chat flows run in CI, and a failing chat spec fails its job. |
Common practice |
| Code health and docs |
No dead code except what the house rules keep, and SignInToJoinChannel, which #274 leaves for a separate decision. No any in the chat store fields and broadcast payloads that #272 lists. No leaked listeners, no needless re-renders, and agent docs that match the code. |
AGENTS.md §Code Quality and §Workflow And Review Expectations. No house rule bans any in general, and the shared ESLint config turns @typescript-eslint/no-explicit-any off. This review sets that part. |
Purpose
This issue tracks the chat composer review of 2026-09-13. It lists every issue that the review filed, and one earlier issue, #263. It also holds one flag. The flag says whether the composer meets the standard in the table below.
The flag
Flag: amber. Every issue in the red list closed on 2026-09-22. The one open issue is #276: the chatroom specs run in CI, and the rest of the webapp specs still need a decision there.
Update the flag when an issue closes. Move to amber only when every issue in the red list is closed.
The standard
tabindex, and focus follows the visual order. A chat open that asks for focus gets it.SignInToJoinChannel, which #274 leaves for a separate decision. Noanyin the chat store fields and broadcast payloads that #272 lists. No leaked listeners, no needless re-renders, and agent docs that match the code.anyin general, and the shared ESLint config turns@typescript-eslint/no-explicit-anyoff. This review sets that part.Issues
Red list: data loss or a broken core flow
Amber list: other user-facing issues, and the CI job
Code health and docs
Earlier issue
#263 is not a review finding. It fixes the
send-and-retryspec, and #276 lands after it. #266, #281, and #290 change the same early clear.How the review worked
14ab7f9c1. The two later commits change only files for the hypermultimedia README images.