81 lines
7.9 KiB
Markdown
81 lines
7.9 KiB
Markdown
|
|
# 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.
|