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

81 lines
No EOL
7.9 KiB
Markdown
Raw Blame History

This file contains invisible Unicode characters

This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# 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.