Submatter/.convoys/workspace-chat-polish/planning-ui.md
varutasu fcd6a59a2c
Some checks failed
CI / Lint, type-check, test (push) Failing after 4m25s
Deploy homelab (CT 116) / Deploy to CT 116 (push) Successful in 14m28s
Implement chat sidebar with Favorites/Channels/DMs sections, search/filter, and expansion state
2026-11-02 22:28:55 +00:00

7.9 KiB
Raw Blame History

planning-ui.md

UI Planning for workspace-chat-polish

This document outlines the visual hierarchy, component boundaries, interaction affordances, keyboard parity, responsive behavior, and handoff decisions for the Chat sidebar polish, grounded in the existing specification.

1. Overview

  • The Chat sidebar is a reusable, contextual component mounted only on Chat routes, replacing the Spaces sidebar in that context.
  • It contains exactly three collapsible sections: Favorites, Channels, and DMs.
  • The sidebar must not own message history; conversation ownership remains with ChatWorkspace.

2. Visual Hierarchy

Level Component Responsibility Evidence
Global Shell AppShell Determines if current route is a Chat route and selects Sidebar vs ChatSidebar. Spec §182
Chat Context ChatSidebar Owns section state, search/filter, navigation, and mutations. Spec §183
Section Header ChatSectionHeader Disclosure control, hover/focus actions, Add, More menu. Spec §100‑104
List Rows ChatListRow (shared) Avatar, label, preview/count, selected state, unread treatment. Spec §125‑126
Conversation ChatWorkspace Owns message history, thread state, composer, message mutations. Spec §186
Composer ChatComposer Accepts explicit send/edit mode, controlled body, submit/cancel callbacks. Spec §146‑147
Delete Shared accessible dialog Confirms destructive action, traps/restores focus, disables duplicate submission. Spec §148‑149

3. Component Boundaries

  • ChatSidebar: Reusable, route‑aware, must not own message history.
  • ChatSectionHeader: Handles disclosure (aria-expanded), hover/focus visibility, Add and More actions.
  • ChatListRow: Shared row primitive for Favorites, Channels, DMs with variants for metadata, unread state, and participant avatars.
  • ChatWorkspace: After ChatSidebar mounts, removes its own channel‑navigation aside to avoid duplicate navigation.
  • ChatComposer: Controlled edit state; populates composer with original body, shows Update/Cancel, preserves conflict recovery.

4. Interaction Affordances

  • Hover/Focus: All actions (Add, More, disclosure) hidden at rest but exposed on :hover and :focus-within. Use focus-visible for keyboard exposure.
  • Section Disclosure: aria-expanded on the disclosure control; labelled region for section body.
  • Add Actions: Right‑aligned in section header; also accessible via keyboard focus.
  • More Menu: Right‑aligned in section header; provides section‑level actions.
  • Message Identity: Use avatar primitive; display name > email > fallback (e.g., Unknown member). Raw UUID never shown as primary label. Tooltip for abbreviated identity.
  • Edit Flow: Focus primary composer → load original body → show Update/Save and Cancel → preserve edited message in history with editing indicator.
  • Delete Flow: Open shared accessible dialog stating “deletion is destructive”, provide Cancel and Delete actions, prevent accidental submission, restore focus to originating message action on Cancel.

5. Keyboard Parity

  • All hover‑only controls must be reachable via keyboard (focus-within).
  • Section headers and row actions must have clear accessible names and maintain aria-expanded state.
  • Focus management: Delete dialog traps focus; on Cancel restores focus to the originating message action.

6. Responsive Behavior

  • Desktop: Secondary Chat surface 260–300 px wide, bordered from conversation; both are independently scrollable.
  • Narrow Viewports: Chat surface becomes an accessible sheet/drawer (single column) rather than forcing a three‑column layout.
  • Maintain global rail width and behavior across breakpoints.

7. Open Risks & Decisions

Risk Description Decision / Mitigation
Flat Channels list length May become long; requires search/filter now but keep grouping opt‑in. Implement search/filter affordance in ChatSectionHeader now; grouping remains user‑selected later (Spec §161).
System status visibility Save, send failures, reconnect, delete completion need visible status and non‑visual announcements. Use existing status primitives (toast/aria-live) and ensure announcements on mutation completion (Spec §162).
Edit Cancel path clarity Must be obvious; edit state belongs to conversation scope. Ensure Update/Cancel buttons are prominently styled and keyboard‑accessible; focus returns to message action after cancel (Spec §163).
Edit pending state Disable actions while mutations pending; show conflict recovery. Disable Update/Delete during pending; surface conflict message rather than losing text (Spec §166).
Delete dialog focus handling Must trap focus and restore on Cancel. Use shared dialog primitive with focus trap; verify focus restoration after cancel (Spec §149).
Profile fallback Should never render raw UUID as primary author label. Fallback to initials or Unknown member; show tooltip for abbreviated identity (Spec §132).
Favorite cross‑workspace authorization Must reject targets outside active workspace. Enforce via service authorization; unique indexes on discriminated target; do not weaken cross‑workspace checks (Spec §198).
Channel metadata & space links Optional nullable spaceId only if justified; must stay tenant‑scoped. Add minimal reusable fields (nullable spaceId + bounded metadata) and enforce object‑type validation in service layer (Spec §199).
DM participant projection Must validate one or many participants and render identity safely. Reuse existing createDirect input; ensure participant picker shows safe identity; group‑DM indicator for >1 participant (Spec §128‑129, §222).
Route detection helper Must avoid false positives; recognize only /[workspaceSlug]/chat and descendants. Implement segment‑aware helper based on usePathname (Spec §191).
Message history ownership ChatSidebar must not own message history. Ensure ChatWorkspace remains sole owner; ChatSidebar only provides navigation and section state (Spec §183‑186).

8. Handoff Decisions

  • Route‑aware shell to render ChatSidebar only on Chat routes; preserve existing Sidebar elsewhere.
  • Extract ChatSidebar contracts from ChatWorkspace without altering data behavior (Spec §110‑111).
  • Implement profile projection for channel authors to display safe identity (Spec §197).
  • Reuse existing composer for edit mode; add explicit edit mode control.
  • Adopt shared accessible dialog for delete flow; no inline delete panel.
  • Favorites persistence to evolve from object‑only to discriminated target (object/chatChannel) with mutual‑exclusion and unique indexes (Spec §198).
  • Channel metadata to be added only if product use requires it; keep space grouping optional and non‑visual by default.

File: /workspace/submatter/.convoys/workspace-chat-polish/planning-ui.md
Key Decisions:

  • ChatSidebar is route‑aware, reusable, and owns only section state (no message history).
  • Component boundaries defined: ChatSidebar, ChatSectionHeader, ChatListRow, ChatWorkspace, ChatComposer, shared dialog.
  • Visual language reuses existing primitives; hover/focus actions exposed via focus-within.
  • Responsive: 260–300 px sidebar on desktop, sheet/drawer on narrow viewports.
  • Edit uses primary composer with Update/Cancel; delete uses shared accessible dialog with focus management.
  • Open risks addressed via search/filter, status announcements, edit pending state handling, delete focus trap, profile fallback, cross‑workspace favorite validation, channel metadata justification, DM participant safety, and segment‑aware route detection.