Chat thread
betaThe canonical message bubble: incoming/outgoing, attachments inside, meta (avatar, name, time, delivery state, actions) below. Used by chats and the e-mail conversation view.
Canon 17 Oct 2026 (owner decision): bubble from prototype proto/mail-konverzace@6355a0399 (.kvb-*) replaces the K7-4 chat bubble (accent-tint, meta inside). Incoming --line-100, outgoing solid --accent; --radius-xl with --radius-xs sender-side corner; padding --sp-3 --sp-5; attachments inside under the text; meta below; max 80% (phone 85%). Voice/video outgoing stays on --accent-tint (follow-up). History: K7-4 (acrm !4447), AD review 2 Oct 2026, sending/failed states (!4514), published = meta text only (13 Oct 2026). Registry repaired 17 Oct 2026 (review F2): removed classes with no CSS definition and no TSX use on main: .cht-bubble, .cht-atts, .cht-att, .cht-who, .cht-link. Registry repaired 17 Oct 2026 (review F3): mapped existing Ladle stories.
Used in 2 files · 2 areas · 3× — components/mail, pages/komunikace
Roles
ChatThreadrendersrole="log"witharia-labelset by the host (the other party's name). A log announces new children as they arrive. An e-mail conversation view that does not useChatThreadshould give its own containerrole="list"withrole="listitem"rows.ChatBubblerenders plaindivs (no role override, noaria-labelon the bubble: it would replace the real multi-line DOM text and break "Find on page" and browser translation).
Reading order inside a message row
- A visually-hidden (
.acrm-sr) sender label (fromLabel) — "Já" / the contact's name — BEFORE the bubble, so a reader reaching a single message knows whose it is. A visiblesenderNamein the meta row isaria-hiddento avoid reading the name twice. - The message text, as real DOM content.
- Attachments (host-rendered
Attachment/.cht-att; links and buttons keep their own roles). - The meta row: time, then — for outgoing messages with a
state— the status icon (decorative) followed by a visually-hiddenstateLabel("přečteno"/"read"), then host actions.
Keyboard
ChatBubble has no interactive elements of its own. Host actions are real <button>s (.cht-link) in the meta row: reachable by Tab in reading order, visible :focus-visible (colour change + underline), toggles expose aria-expanded (e.g. "Original"). A clamped long message offers "Show all" / "Show less" (.cht-more, inside the bubble, aria-expanded) as such a button; clamped text stays fully available to assistive technology (the clamp is visual) once expanded.
Touch
Host actions in the meta row are text buttons. Where the host needs the 44 px target (--tap-min) on touch it extends the hit area with an invisible pseudo-element, without changing the look.
Icons
check / checks / clock / alert-circle come from the DS icon set. They convey state, so WCAG 1.4.11 (non-text contrast, 3:1) applies. read uses --accent on the page (4.29:1 light, 4.04:1 dark).
Contrast (WCAG 2.1, measured (L1+0.05)/(L2+0.05))
| element | light | dark | target | status |
|---|---|---|---|---|
incoming text — --fg on --line-100 | 16.0:1 | 13.1:1 | AA 4.5:1 | met in both |
outgoing text — --fg-on-accent on --accent | 4.44:1 | 4.44:1 | AA 4.5:1 | 0.06 short (same pair as Button primary) |
meta (time, host actions) — --fg-muted on page | 2.75:1 | 3.82:1 | AA 4.5:1 | documented limitation (owner decision R21) |
read icon — --accent on page | 4.29:1 | 4.04:1 | non-text 3:1 | met in both |
The meta tone is the owner-approved quiet metadata colour (--fg-muted); the outgoing text pair is the accent / on-accent pair used app-wide. Both are flagged for a token-level decision, not fixed per component.
Source: docs/discussion/chat-thread.a11y.md · GitLab