Skip to content

Latest commit

 

History

History
367 lines (323 loc) · 13.6 KB

File metadata and controls

367 lines (323 loc) · 13.6 KB

UI/UX Overhaul Plan - Borrowing from t3code

Comprehensive plan to elevate echoes-code's UI/UX by adopting proven patterns from t3code. Tracked in PROGRESS.md


Phase 1 - Quick Wins (P0)

1.1 Root Error Boundary

  • Create src/renderer/src/components/ui/ErrorBoundary.tsx
  • Class component with componentDidCatch and getDerivedStateFromError
  • Error UI: gradient backdrop, error message, collapsible stack trace, "Reload" button
  • Theme-aware styling using CSS variables
  • Wrap app root in App.tsx (or future router root)
  • Reference: t3code __root.tsx error boundary

1.2 Toast Notification System

  • Install @base-ui-components/react (unstyled primitives)
  • Create src/renderer/src/components/ui/Toast.tsx
    • ToastProvider wrapping app root
    • Toast types: success, error, info, warning, loading
    • Stacking with auto-dismiss (5s default)
    • Position: bottom-right
    • Entrance/exit animations (slideUp + fadeIn)
    • Manual dismiss button
    • useToast() hook for imperative usage: toast.success("Saved")
  • Create src/renderer/src/hooks/useToast.ts
  • Replace inline notifications:
    • PR creation success/error (TitleBar.tsx)
    • Feedback submission result (TitleBar.tsx)
    • Provider connection status changes (App.tsx)
    • Authentication errors (SettingsView.tsx)
    • Settings save confirmation (SettingsView.tsx)
    • Rate limit warnings (ThreadView.tsx)
  • Reference: t3code toast.tsx (400+ lines, stacking, swipe-to-dismiss)

1.3 Theme Transition Suppression

  • Add .no-transitions class to global.css:
    .no-transitions, .no-transitions * {
      transition: none !important;
      animation: none !important;
    }
  • Update theme switch handler to:
    1. Add .no-transitions to documentElement
    2. Apply data-theme
    3. requestAnimationFrame → remove .no-transitions
  • Reference: t3code useTheme.ts transition suppression

1.4 Draft Preservation Per Thread

  • Create src/renderer/src/stores/draftStore.ts
    • Simple store: Map<threadId, string>
    • setDraft(threadId, text), getDraft(threadId), clearDraft(threadId)
    • Persist to localStorage key echoes-drafts
  • Integrate into ThreadView.tsx:
    • On thread switch: save current input, load draft for new thread
    • On send: clear draft
  • Reference: t3code useComposerDraftStore

Phase 2 - Foundation (P1)

2.1 Reusable UI Component Library

Create src/renderer/src/components/ui/ with these primitives:

  • Button.tsx

    • Variants: default, outline, ghost, destructive, link
    • Sizes: sm, default, lg
    • Loading state (spinner + disabled)
    • Icon-only variant
    • Focus-visible ring
  • Input.tsx

    • Sizes: sm, default, lg
    • Focus ring with accent color
    • Disabled state (opacity 64%)
    • Placeholder styling
    • Error state (red border)
  • Badge.tsx

    • Variants: default, success, warning, error, outline
    • Replace inline status dots, "Needs input" labels, cloud/local badges
  • Dialog.tsx

    • Overlay + centered panel
    • Header, body, footer sections
    • Close button (X icon)
    • Escape to close, click-outside to close
    • Entrance animation (scale + opacity)
    • Replace: About dialog, Feedback dialog, Delete confirmation, Settings modal
  • Tooltip.tsx

    • Positioned floating text
    • Configurable side/alignment
    • Delay on hover (200ms)
    • Replace: PR error tooltip, shortcut hints
  • Spinner.tsx

    • Standardized loading spinner
    • Sizes: sm, default, lg
    • Replace all duplicated inline SVG spinners
  • Separator.tsx

    • Horizontal/vertical variants
    • Replace inline borderTop dividers
  • Skeleton.tsx

    • Shimmer animation (2s linear infinite, 120deg gradient)
    • Rounded rectangle base
    • Width/height props
    • Reference: t3code skeleton.tsx
  • ScrollArea.tsx

    • Custom scrollbar wrapper
    • Theme-aware scrollbar colors
    • 6px width, hover brightens
  • Kbd.tsx

    • Keyboard shortcut display badge
    • Styled key caps
    • Reference: t3code kbd.tsx

2.2 State Management with Zustand

  • Install zustand
  • Create stores in src/renderer/src/stores/:
    • appStore.ts — activeThreadId, expandedProjects, settingsOpen, sidebarOpen
    • settingsStore.ts — theme, accent, fontSize, density, language, permissionLevel, planMode, useWorktree (persisted to localStorage)
    • draftStore.ts — per-thread draft messages (from Phase 1)
    • providerStore.ts — provider connection status, accounts
  • Migrate state out of App.tsx into stores
  • Remove prop drilling — components access stores directly
  • Reference: t3code store.ts with Zustand 5.0, persisted state, versioned migration

2.3 Skeleton Loading States

  • Apply Skeleton component (from 2.1) to:
    • Sidebar: skeleton project/thread list while Convex query loads
    • ThreadView: skeleton message bubbles while messages load
    • SettingsView: skeleton sections while settings load
    • User profile: skeleton avatar + name while user loads
  • Add contextual empty states:
    • "Select a thread or create a new one"
    • "No messages yet"
    • "No projects — create your first project"
  • Reference: t3code skeleton.tsx + empty state patterns

2.4 Accessibility Improvements

  • Icon-only buttons: Add aria-label to all icon-only buttons
    • Close, minimize, maximize (TitleBar)
    • Menu, delete, expand/collapse (Sidebar)
    • Copy, send, stop (ThreadView)
  • Custom widgets: Add proper ARIA roles
    • Theme selector: role="radiogroup" + role="radio" + aria-checked
    • Accent selector: same pattern
    • Density selector: same pattern
    • Tab lists: role="tablist" + role="tab" + aria-selected
  • Form inputs: aria-invalid on validation errors, aria-describedby for help text
  • Live regions: aria-live="polite" on streaming message area
  • Spinner: role="status" + aria-label="Loading"
  • Focus management:
    • Visible focus rings: outline: 2px solid var(--accent) on :focus-visible
    • Logical tab order across TitleBar -> Sidebar -> Content -> Input
    • Focus trap in modals/dialogs
    • Return focus to trigger when modal closes
  • Keyboard navigation:
    • Arrow keys in sidebar project/thread list
    • Escape closes modals/menus/panels
  • Reference: t3code ARIA attributes, focus-visible rings, role usage

2.5 Popover Component

  • Create src/renderer/src/components/ui/Popover.tsx
    • Auto-positioning (flips when near viewport edges)
    • Configurable side (top/right/bottom/left) and alignment
    • Focus management
    • Click-outside dismiss
    • Smooth entrance transition
  • Replace existing absolute-positioned menus:
    • TitleBar menu dropdown
    • Model selector dropdown (ThreadView)
    • Permission level selector (ThreadView)
  • Reference: t3code popover.tsx

2.6 Scrollbar Theme Awareness

  • Update global.css scrollbar styles per theme:
    [data-theme="dark"] ::-webkit-scrollbar-thumb { background: rgba(255,255,255,0.15); }
    [data-theme="light"] ::-webkit-scrollbar-thumb { background: rgba(0,0,0,0.2); }
    [data-theme="midnight"] ::-webkit-scrollbar-thumb { background: rgba(255,255,255,0.1); }
    [data-theme="nord"] ::-webkit-scrollbar-thumb { background: rgba(136,192,208,0.25); }
    [data-theme="sepia"] ::-webkit-scrollbar-thumb { background: rgba(160,82,45,0.3); }
  • Add hover state: slightly brighter on ::-webkit-scrollbar-thumb:hover
  • Reduce width to 6px
  • Reference: t3code scrollbar styling per theme

Phase 3 - Architecture (P2)

3.1 Tailwind CSS Migration

  • Install tailwindcss 4.x, @tailwindcss/vite
  • Configure @theme in CSS to map existing CSS variables to Tailwind tokens
  • Install class-variance-authority (CVA) for component variants
  • Migrate UI primitives (Phase 2 components) to Tailwind classes
  • Migrate existing components one-by-one:
    • EchoesLogo.tsx
    • ContextMenu.tsx
    • TitleBar.tsx
    • Sidebar.tsx
    • ThreadView.tsx
    • SettingsView.tsx
    • LoginPage.tsx
    • MarkdownContent.tsx
    • GitHubPanel.tsx
  • Remove inline const styles: Record<string, React.CSSProperties> blocks
  • Reference: t3code Tailwind 4.0 + CVA setup

3.2 File-Based Router

  • Install @tanstack/react-router
  • Configure hash-history for Electron
  • Define route tree:
    routes/
      __root.tsx          — providers, error boundary, toast
      _app.tsx            — authenticated layout (TitleBar + Sidebar + outlet)
      _app.index.tsx      — empty state / onboarding
      _app.$threadId.tsx  — ThreadView
      _app.settings.tsx   — SettingsView
      login.tsx           — LoginPage
    
  • Split App.tsx (1560 lines) into route files
  • Move route-level state into URL (activeThreadId, settingsView)
  • Reference: t3code @tanstack/react-router file-based routes

3.3 Sheet Component

  • Create src/renderer/src/components/ui/Sheet.tsx
    • Slide-in panels from any edge (left/right/top/bottom)
    • Backdrop overlay with click-to-close
    • Smooth transition (300ms cubic-bezier)
    • keepMounted option
    • Portal rendering for z-index
  • Use for:
    • Mobile sidebar (slide from left)
    • GitHub panel (slide from right)
    • Future terminal drawer (slide from bottom)
  • Reference: t3code sheet.tsx

3.4 Responsive Design

  • Create src/renderer/src/hooks/useMediaQuery.ts
  • Define breakpoints: mobile (<768px), tablet (768-1180px), desktop (>1180px)
  • Responsive sidebar:
    • Desktop: fixed 280px
    • Mobile: offcanvas overlay via Sheet, hamburger toggle
  • Responsive settings:
    • Desktop: modal dialog
    • Mobile: full-screen view
  • Touch targets: minimum 44x44px on pointer-coarse devices
  • GitHub panel: collapse to icon on narrow widths
  • Reference: t3code useMediaQuery.ts, mobile breakpoint patterns

3.5 Shiki Syntax Highlighting

  • Install shiki (or @shikijs/core)
  • Create highlighting utility with:
    • LRU cache (500 entries)
    • Lazy language grammar loading
    • Suspense boundary with plain-text fallback
    • Theme-aware token colors (one theme per app theme)
  • Integrate into MarkdownContent.tsx code block renderer
  • Reference: t3code ChatMarkdown.tsx Shiki + LRU cache

3.6 Typography System

  • Define type scale as CSS variables:
    --font-xs: 0.75rem;
    --font-sm: 0.875rem;
    --font-base: 1rem;
    --font-lg: 1.125rem;
    --font-xl: 1.25rem;
  • Standardize line heights: 1.5 body, 1.25 headings, 1.6 code
  • Apply consistently across all components
  • Reference: t3code DM Sans + systematic font scale

Phase 4 - Power Features (P3)

4.1 Rich Text Editor (Lexical)

  • Install lexical + @lexical/react + plugins
  • Create src/renderer/src/components/ComposerEditor.tsx
    • @mentions for files/symbols (with icons)
    • History plugin (Ctrl+Z/Y in input)
    • Slash commands (/plan, /diff, /model)
    • Keyboard: Shift+Enter newline, Ctrl+Enter send
    • Keep: image paste support
  • Replace textarea in ThreadView
  • Reference: t3code ComposerPromptEditor.tsx with Lexical

4.2 Integrated Terminal Drawer

  • Install xterm + xterm-addon-fit
  • Create src/renderer/src/components/TerminalDrawer.tsx
    • Slides up from bottom of ThreadView
    • Resizable height (drag handle)
    • Toggle via Ctrl+` keyboard shortcut
    • Shows stdout/stderr from executed commands
    • Connects to backend PTY
  • Create terminal state store
  • Reference: t3code ThreadTerminalDrawer.tsx + xterm.js

4.3 Git Diff Panel

  • Create src/renderer/src/components/DiffPanel.tsx
    • Side panel (right of ThreadView), collapsible
    • Per-message file diffs with Shiki syntax highlighting
    • Split (side-by-side) and unified views
    • File tree with changed file list
    • Resizable width via CSS variable
  • Desktop: inline sidebar (min 26rem)
  • Mobile: Sheet modal
  • Reference: t3code DiffPanel.tsx + DiffWorkerPoolProvider

4.4 Command Palette

  • Create src/renderer/src/components/CommandPalette.tsx
    • Open with Ctrl+K / Cmd+K
    • Searchable list of app actions
    • Recent items section
    • Keyboard navigation (arrow keys + enter)
    • Fuzzy matching
  • Register actions:
    • New thread, switch thread, open settings
    • Switch model, toggle plan mode
    • Toggle sidebar, toggle GitHub panel
  • Reference: t3code command.tsx

Architecture Notes

Current State (echoes-code)

  • 9 components, 4 hooks, 1 CSS file
  • Inline React styles (const styles: Record<string, React.CSSProperties>)
  • No component library, no router, no state management library
  • App.tsx is 1560 lines with all routing + state
  • No toast, no error boundary, no skeleton loading

Target State (after this plan)

  • ~25+ components (9 existing + 12 UI primitives + power features)
  • Tailwind CSS with CVA for variant management
  • Tanstack Router with file-based routes
  • Zustand stores for state management
  • Toast system, error boundaries, skeleton loading
  • Rich text editor, terminal, diff panel, command palette
  • Accessible, responsive, theme-polished

Key Dependencies to Add

@base-ui-components/react   — unstyled UI primitives
zustand                     — state management
@tanstack/react-router      — file-based routing
tailwindcss                 — utility CSS (v4)
@tailwindcss/vite           — Vite plugin
class-variance-authority    — component variants
shiki                       — syntax highlighting
lexical @lexical/react      — rich text editor
xterm xterm-addon-fit       — terminal emulator