Submatter/.convoys/workspace-chat-foundation/brief-3-chat-ui.md

3.7 KiB
Raw Blame History

brief convoy role title status priority slice_dependencies recommended_model model_tier
3 workspace-chat-foundation role-implementer Chat workspace UI and left-rail navigation blocked P1
brief-1-chat-persistence
brief-2-chat-realtime
auto/coding standard

Brief 3 — Task-chat-ui-and-navigation.md

Goal

Expose workspace chat through the existing application shell with accessible channel navigation, durable history/read state, and realtime updates.

Files

Expected scope; confirm conventions against nearby workspace routes and UI components.

  • apps/web/app/(app)/[workspaceSlug]/chat/page.tsx — channel selection/redirect or empty state.
  • apps/web/app/(app)/[workspaceSlug]/chat/[channelSlug]/page.tsx — channel conversation route.
  • apps/web/components/layout/icon-rail.tsx — Chat destination and accessible unread/mention badge.
  • apps/web/components/chat/ — channel list, paginated message feed, composer, thread affordance, connection state, and retry UI.
  • apps/web/components/providers/ or focused hooks — realtime event reconciliation with tRPC/React Query caches.
  • Adjacent component/unit tests.

Required design

  • Server state is authoritative; realtime events invalidate or reconcile durable query data. Foundation UI supports workspace-context channels only; project/object entry points wait for the context authorization task. Never expose unauthorized titles/previews, mention candidates or counts; purge inaccessible cached conversations on denial/revocation. Mention UI must not promise agent addition/execution before its reviewed membership flow exists.
  • Ordinary unread activity uses a dot. In this convoy, the numeric badge is computed from persisted message-mention rows above each channel read cursor plus unread direct-channel activity. The later notifications epic adds unified inbox projections without changing the rail contract.
  • Unread means a channel's highest message sequence is greater than the member's last-read sequence. Opening a channel does not mark unseen content read until the client intentionally advances the visible boundary.
  • Direct-channel unread activity contributes to the numeric Chat badge; ordinary public/private channel activity contributes only the unread dot unless the user is mentioned.
  • Optimistic messages and thread replies have deterministic pending, committed, failed, and retry states keyed by the idempotency key.
  • History and thread history use per-channel sequence cursor pagination and preserve scroll position while loading older messages.
  • Realtime read-state invalidations reconcile rail/channel badges across the user's devices.
  • Keyboard and screen-reader behavior cover navigation, unread indicators, composer, threads, and failures.
  • Use existing Radix/Tailwind primitives and the current right-panel pattern for a minimally complete thread list/reply surface.

Acceptance

  • A user can enter Chat from the left rail, switch channels, send/retry messages and thread replies, intentionally advance the read boundary, and reload without losing state.
  • Realtime messages and replies appear once and per-channel reconnect catch-up converges to server truth.
  • Rail/channel unread, direct-message, and mention indicators update across devices after durable mark-read operations.
  • Loading, empty, unauthorized, archived, offline, and failed-send states are handled.
  • Responsive layout and keyboard navigation work without inaccessible color-only signals.
  • pnpm lint && pnpm type-check && pnpm test pass.

Prompt

Read the workspace layout, icon rail, right panel, UI primitives, tRPC provider, and the APIs/events produced by briefs 1–2. Do not add a separate design system or raw internal fetch calls. Keep notification inbox and agent participation out of this slice.