--- name: workspace-chat-polish classification: feature success_metric: Workspace Chat presents one coherent, accessible navigation and message experience with a contextual sidebar, recognizable authors, composer-based editing, modal deletion, and Favorites/Channels/DMs organization. skip: [] status: in-progress created: 2026-11-02 model_policy: roles: role-conductor: claude-planning role-ia-architect: claude-planning role-ui-designer: claude-planning role-ux-reviewer: claude-planning role-architect: claude-planning role-implementer: qwen-coder role-reviewer: qwen-coder role-a11y-auditor: claude-planning escalate_to: claude-planning --- # UX Planning for Workspace Chat Polish ## 1. Evidence from existing planning document - **Route detection**: Use `usePathname` segment‑aware helper to detect only `/[workspaceSlug]/chat` and descendants (line 190‑192). Avoid substring matches that could false‑positive on object titles. - **Component boundaries**: `AppShell` decides Chat vs Sidebar; `ChatSidebar` owns section state, `ChatSectionHeader` owns disclosure/focus actions, `ChatListRow` is shared across sections, `ChatWorkspace` owns message history and composer state (lines 181‑188). - **Profile identity**: Use existing `users` data (`name`, `avatarUrl`) and project a workspace‑authorized participant summary; never render raw UUID as visible identity (line 132, 197). - **Edit flow**: Populate the primary composer, show “Update”/`Cancel`, keep original message in history with editing indicator (lines 135‑144). - **Delete flow**: Use a shared accessible dialog primitive, trap/restore focus, prevent accidental submission, restore focus on cancel (lines 147‑148). - **Favorites & DMs**: Favorites use a single router contract with discriminated target (`object` or `chatChannel`) and enforce cross‑workspace authorization; DMs support one‑to‑many participants via existing `createDirect` API (lines 198‑204). ## 2. Heuristic Risks & Recommendations | Heuristic | Risk | Recommendation | |-----------|------|----------------| | **Recognition over recall** | Flat Channels list may become long; users must scan many items. | Provide optional search/filter input in the sidebar header; keep default flat list but allow grouping via a user‑selected mode. | | **Visibility of system status** | Saving edits, failed sends, reconnect, delete completion lack clear feedback. | Show inline status messages (toast/aria-live) and non‑visual announcements for each state change. | | **User control & freedom** | Edit requires obvious Cancel; delete needs Cancel as default and focus restoration. | Ensure Cancel button is prominent, focus is restored to the originating action on cancel, and delete dialog defaults to Cancel. | | **Consistency & standards** | UI may diverge from Spaces sidebar primitives. | Reuse existing `ChatSectionHeader`, `ChatListRow`, `Dialog` primitives; match colors, button styles, tooltips, dropdown behavior. | | **Flexibility & efficiency** | Keyboard focus may not reveal hover actions. | Expose the same actions on `:focus-within` and `focus-visible`; ensure Add, More, and Delete are reachable via keyboard without hover. | | **Error prevention** | Pending mutations may allow invalid edits or deletes. | Disable primary actions while mutations are in flight, show conflict resolution UI, preserve draft text on error. | | **Aesthetic / minimalist design** | Risk of adding Defaults or duplicate lists. | Strictly enforce the three sections (Favorites, Channels, DMs) and prohibit Defaults/New Message sections. | | **Help users recover from errors** | Profile lookup failures or favorite/DM creation errors need recovery. | Provide inline alerts/toast with retry where safe; fallback avatar/initials for missing profile data. | ## 3. Flow Acceptance Criteria 1. **Chat Route** – Rail → Chat contextual surface (sidebar + conversation). Sidebar appears only when URL matches `/[workspaceSlug]/chat*`; otherwise global rail shows existing Spaces sidebar. 2. **Edit Message** – Click “Edit” → focus primary composer → load original body → show “Update” and “Cancel” → on “Update” submit mutation → status announcement (e.g., “Message edited”) → history refresh with editing indicator; on “Cancel” discard changes, restore focus, no history change. 3. **Delete Message** – Click “Delete” → accessible confirmation dialog appears → focus trapped → “Cancel” returns focus to delete button, “Delete” performs destructive action → message replaced with tombstone or removal → focus returns to message list; dialog cannot be submitted twice. 4. **Add DM** – Click “Add” in DMs header → participant picker opens → supports selecting one or multiple participants → on selection, creates/opens direct channel → shows participant avatars/names safely (no raw IDs) → conversation loads. 5. **Section Interaction** – Disclosure control (`aria-expanded`) toggles section visibility; hover reveals Add/More actions; focus‑visible reveals same actions; all actions are keyboard operable. 6. **Accessibility** – All interactive elements have accessible names, `role="button"` where appropriate, `aria-live="polite"` for status announcements, focus order logical, color contrast meets WCAG AA, and screen‑reader users can navigate sections via headings. ## 4. Keyboard & Accessibility Requirements - **Focus Management**: Use `focus-within` and `focus-visible` to expose hover actions to keyboard users; trap focus inside the delete confirmation dialog and restore focus to the originating element on cancel. - **ARIA**: `aria-expanded` on disclosure controls, labelled regions for each section, `aria-live="polite"` for status messages (edit save, delete confirm, reconnect). - **Navigation**: Logical tab order; skip‑to‑content link to jump from global rail to Chat sidebar; ensure all interactive elements are reachable via `Tab`/`Enter`/`Space`. - **Screen Reader**: Provide concise accessible names (e.g., “Edit message”, “Delete message”, “Add direct message”). Avoid reading raw UUIDs; use participant display names or initials. - **Contrast & Hit Targets**: Minimum 44 × 44 px touch targets; ensure text and UI components meet WCAG AA contrast ratios. ## 5. Open Risks & Decisions Needed 1. **Search/Filter Implementation** – Should the sidebar include an input field for filtering channels/favorites, or rely on user‑selected grouping only? Decision pending. 2. **Space Metadata in Channels** – The plan mentions optional `spaceId` for channel metadata. Need to confirm whether existing space objects provide sufficient context or if additional fields are required. 3. **Favorites Target Contract** – Final schema for the favorites router (discriminated `object` vs `chatChannel`) and unique index strategy must be defined before implementation. 4. **Responsive Behavior** – Define breakpoint at which the Chat sidebar becomes a drawer/sheet; current guidance (260–300 px) needs concrete media query values. 5. **Dialog Primitive Reuse** – Verify if a shared accessible dialog component exists in the codebase; if not, a minimal shared dialog must be added. ## 6. Key Decisions (to be captured in implementation) - Use segment‑aware route detection (`usePathname`) to limit ChatSidebar mounting to Chat routes only. - Reuse existing `ChatSectionHeader`, `ChatListRow`, and `Dialog` primitives for consistency. - Project participant identities from `users` data; never expose raw UUIDs in the UI. - Implement favorites as a discriminated target with cross‑workspace authorization checks. - Ensure all actions (Add, More, Edit, Delete) are reachable via keyboard (`focus-visible`) and have visible focus indicators. - Provide inline status announcements for edit save, delete confirm, and failed operations. --- *File: /workspace/submatter/.convoys/workspace-chat-polish/planning-ux.md* *Key decisions captured above; open risks listed for future resolution.*