From a138ce9fc1a48b0ab25d1c301cbd5ee6eab66d74 Mon Sep 17 00:00:00 2001 From: Val Alexander Date: Fri, 10 Apr 2026 03:44:32 -0500 Subject: [PATCH] Replace draft upload icon with close action - Update sidebar draft threads to show a close button - Remove the cloud upload affordance from draft rows - Clean up DESIGN.md table formatting --- DESIGN.md | 62 +++++++++++++++-------------- apps/web/src/components/Sidebar.tsx | 28 ++++++++++++- 2 files changed, 58 insertions(+), 32 deletions(-) diff --git a/DESIGN.md b/DESIGN.md index 4cbdf2243..a83e69c56 100644 --- a/DESIGN.md +++ b/DESIGN.md @@ -52,34 +52,34 @@ conversation with the agent. Every pixel must earn its place. ### Typography -| Role | Size | Weight | Tracking | Font Stack | -|------|------|--------|----------|------------| -| Thread title (sidebar) | `text-xs` (0.75rem) | `font-normal` | default | Inter, system-ui, sans-serif | -| Thread subtitle / metadata | `text-[10px]` | `font-normal` | default | Inter, system-ui, sans-serif | -| Badge text | `text-[10px]` | `font-medium` | default | Inter, system-ui, sans-serif | -| Button text | `text-sm` (0.875rem) | `font-medium` | default | Inter, system-ui, sans-serif | -| Heading / dialog title | `text-lg` (1.125rem) | `font-semibold` | `-0.01em` | Inter, system-ui, sans-serif | -| Code / terminal | `text-sm` | `font-normal` | default | SF Mono, Consolas, monospace | -| Project name | `text-xs` | `font-semibold` | default | Inter, system-ui, sans-serif | +| Role | Size | Weight | Tracking | Font Stack | +| -------------------------- | -------------------- | --------------- | --------- | ---------------------------- | +| Thread title (sidebar) | `text-xs` (0.75rem) | `font-normal` | default | Inter, system-ui, sans-serif | +| Thread subtitle / metadata | `text-[10px]` | `font-normal` | default | Inter, system-ui, sans-serif | +| Badge text | `text-[10px]` | `font-medium` | default | Inter, system-ui, sans-serif | +| Button text | `text-sm` (0.875rem) | `font-medium` | default | Inter, system-ui, sans-serif | +| Heading / dialog title | `text-lg` (1.125rem) | `font-semibold` | `-0.01em` | Inter, system-ui, sans-serif | +| Code / terminal | `text-sm` | `font-normal` | default | SF Mono, Consolas, monospace | +| Project name | `text-xs` | `font-semibold` | default | Inter, system-ui, sans-serif | ### Color Semantics Colors are referenced through CSS custom properties, never hardcoded hex values. -| Token | Usage | -|-------|-------| -| `text-foreground` | Primary text | -| `text-muted-foreground` | Secondary/deemphasized text | +| Token | Usage | +| -------------------------- | ------------------------------------------------- | +| `text-foreground` | Primary text | +| `text-muted-foreground` | Secondary/deemphasized text | | `text-muted-foreground/50` | Tertiary/metadata text (branch names, timestamps) | -| `bg-background` | Page background | -| `bg-accent` | Hover state, active row highlight | -| `bg-accent/60` | Active sidebar item | -| `bg-accent/40` | Selected sidebar item | -| `text-emerald-600` | Additions / success (green) | -| `text-rose-500` | Deletions / error (red) | -| `text-warning` | Warning states, behind-upstream | -| `text-destructive` | Destructive actions (delete) | -| `border-border/60` | Subtle badge borders | +| `bg-background` | Page background | +| `bg-accent` | Hover state, active row highlight | +| `bg-accent/60` | Active sidebar item | +| `bg-accent/40` | Selected sidebar item | +| `text-emerald-600` | Additions / success (green) | +| `text-rose-500` | Deletions / error (red) | +| `text-warning` | Warning states, behind-upstream | +| `text-destructive` | Destructive actions (delete) | +| `border-border/60` | Subtle badge borders | ### Spacing Rules @@ -95,14 +95,14 @@ Colors are referenced through CSS custom properties, never hardcoded hex values. Six premium themes, each with light and dark variants: -| Theme | Vibe | -|-------|------| -| **Iridescent Void** | Futuristic, expensive, slightly alien | -| **Solar Witch** | Magical, cozy, ritualistic | -| **Carbon** | Stark, modern, performance-focused | -| **Vapor** | Refined, fluid, purposeful | -| **Cotton Candy** | Sweet, dreamy, pink and blue | -| **Cathedral Circuit** | Sacred machine, techno-gothic | +| Theme | Vibe | +| --------------------- | ------------------------------------- | +| **Iridescent Void** | Futuristic, expensive, slightly alien | +| **Solar Witch** | Magical, cozy, ritualistic | +| **Carbon** | Stark, modern, performance-focused | +| **Vapor** | Refined, fluid, purposeful | +| **Cotton Candy** | Sweet, dreamy, pink and blue | +| **Cathedral Circuit** | Sacred machine, techno-gothic | All themes define the same set of CSS custom properties. Components must use semantic tokens (`bg-accent`, `text-muted-foreground`) — never theme-specific values. @@ -142,6 +142,7 @@ const buttonVariants = cva("base classes", { ### Focus States All interactive elements use the same focus ring: + ``` focus-visible:border-ring focus-visible:ring-ring/50 focus-visible:ring-[3px] ``` @@ -249,6 +250,7 @@ a single flow: ``` Quick action resolves automatically based on git state: + - Has changes + no PR → "Commit, push & PR" - Has changes + existing PR → "Commit & push" - No changes + ahead → "Push & create PR" diff --git a/apps/web/src/components/Sidebar.tsx b/apps/web/src/components/Sidebar.tsx index a71a56228..7db4e0db8 100644 --- a/apps/web/src/components/Sidebar.tsx +++ b/apps/web/src/components/Sidebar.tsx @@ -33,7 +33,6 @@ import { ChevronsDownUpIcon, ChevronsUpDownIcon, CircleDotIcon, - CloudUploadIcon, ExternalLinkIcon, FolderIcon, GitBranchIcon, @@ -46,6 +45,7 @@ import { SettingsIcon, TriangleAlertIcon, UserIcon, + XIcon, XCircleIcon, } from "lucide-react"; import { type MouseEvent, memo, useCallback, useEffect, useMemo, useRef, useState } from "react"; @@ -319,6 +319,7 @@ interface MemoizedThreadRowProps { position: { x: number; y: number }, ) => Promise; handleMultiSelectContextMenu: (position: { x: number; y: number }) => Promise; + closeDraftThread: (threadId: ThreadIdType) => void; } const MemoizedThreadRow = memo( @@ -343,6 +344,7 @@ const MemoizedThreadRow = memo( handleThreadClick, handleThreadContextMenu, handleMultiSelectContextMenu, + closeDraftThread, }: MemoizedThreadRowProps) { const threadStatus = resolveThreadStatusPill({ thread, @@ -441,7 +443,21 @@ const MemoizedThreadRow = memo( onCancel={cancelEditing} /> - + {isDraft ? ( + + ) : null} ); @@ -944,6 +960,13 @@ export default function Sidebar() { ], ); + const closeDraftThread = useCallback( + (threadId: ThreadId) => { + void deleteThread(threadId); + }, + [deleteThread], + ); + const { copyToClipboard: copyThreadIdToClipboard } = useCopyToClipboard<{ threadId: ThreadId; }>({ @@ -1453,6 +1476,7 @@ export default function Sidebar() { handleThreadClick={handleThreadClick} handleThreadContextMenu={handleThreadContextMenu} handleMultiSelectContextMenu={handleMultiSelectContextMenu} + closeDraftThread={closeDraftThread} /> ))}