Add design-guide skill for consistent UI development
Provides design system conventions, component index, typography scale, status/priority systems, composition patterns, and rules for maintaining the /design-guide showcase page. References frontend-design and web-design-guidelines skills. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
351
.claude/skills/design-guide/SKILL.md
Normal file
351
.claude/skills/design-guide/SKILL.md
Normal file
@@ -0,0 +1,351 @@
|
||||
---
|
||||
name: design-guide
|
||||
description: >
|
||||
Paperclip UI design system guide for building consistent, reusable frontend
|
||||
components. Use when creating new UI components, modifying existing ones,
|
||||
adding pages or features to the frontend, styling UI elements, or when you
|
||||
need to understand the design language and conventions. Covers: component
|
||||
creation, design tokens, typography, status/priority systems, composition
|
||||
patterns, and the /design-guide showcase page. Always use this skill
|
||||
alongside the frontend-design skill (for visual quality) and the
|
||||
web-design-guidelines skill (for web best practices).
|
||||
---
|
||||
|
||||
# Paperclip Design Guide
|
||||
|
||||
Paperclip's UI is a professional-grade control plane — dense, keyboard-driven, dark-themed by default. Every pixel earns its place.
|
||||
|
||||
**Always use with:** `frontend-design` (visual polish) and `web-design-guidelines` (web best practices).
|
||||
|
||||
---
|
||||
|
||||
## 1. Design Principles
|
||||
|
||||
- **Dense but scannable.** Maximum information without clicks to reveal. Whitespace separates, not pads.
|
||||
- **Keyboard-first.** Global shortcuts (Cmd+K, C, [, ]). Power users rarely touch the mouse.
|
||||
- **Contextual, not modal.** Inline editing over dialog boxes. Dropdowns over page navigations.
|
||||
- **Dark theme default.** Neutral grays (OKLCH), not pure black. Accent colors for status/priority only. Text is the primary visual element.
|
||||
- **Component-driven.** Prefer reusable components that capture style conventions. Build at the right abstraction — not too granular, not too monolithic.
|
||||
|
||||
---
|
||||
|
||||
## 2. Tech Stack
|
||||
|
||||
- **React 19** + **TypeScript** + **Vite**
|
||||
- **Tailwind CSS v4** with CSS variables (OKLCH color space)
|
||||
- **shadcn/ui** (new-york style, neutral base, CSS variables enabled)
|
||||
- **Radix UI** primitives (accessibility, focus management)
|
||||
- **Lucide React** icons (16px nav, 14px inline)
|
||||
- **class-variance-authority** (CVA) for component variants
|
||||
- **clsx + tailwind-merge** via `cn()` utility
|
||||
|
||||
Config: `ui/components.json` (aliases: `@/components`, `@/components/ui`, `@/lib`, `@/hooks`)
|
||||
|
||||
---
|
||||
|
||||
## 3. Design Tokens
|
||||
|
||||
All tokens defined as CSS variables in `ui/src/index.css`. Both light and dark themes use OKLCH.
|
||||
|
||||
### Colors
|
||||
|
||||
Use semantic token names, never raw color values:
|
||||
|
||||
| Token | Usage |
|
||||
|-------|-------|
|
||||
| `--background` / `--foreground` | Page background and primary text |
|
||||
| `--card` / `--card-foreground` | Card surfaces |
|
||||
| `--primary` / `--primary-foreground` | Primary actions, emphasis |
|
||||
| `--secondary` / `--secondary-foreground` | Secondary surfaces |
|
||||
| `--muted` / `--muted-foreground` | Subdued text, labels |
|
||||
| `--accent` / `--accent-foreground` | Hover states, active nav items |
|
||||
| `--destructive` | Destructive actions |
|
||||
| `--border` | All borders |
|
||||
| `--ring` | Focus rings |
|
||||
| `--sidebar-*` | Sidebar-specific variants |
|
||||
| `--chart-1` through `--chart-5` | Data visualization |
|
||||
|
||||
### Radius
|
||||
|
||||
Single `--radius` variable (0.625rem) with derived sizes:
|
||||
|
||||
- `rounded-sm` — small inputs, pills
|
||||
- `rounded-md` — buttons, inputs, small components
|
||||
- `rounded-lg` — cards, dialogs
|
||||
- `rounded-xl` — card containers, large components
|
||||
- `rounded-full` — badges, avatars, status dots
|
||||
|
||||
### Shadows
|
||||
|
||||
Minimal shadows: `shadow-xs` (outline buttons), `shadow-sm` (cards). No heavy shadows.
|
||||
|
||||
---
|
||||
|
||||
## 4. Typography Scale
|
||||
|
||||
Use these exact patterns — do not invent new ones:
|
||||
|
||||
| Pattern | Classes | Usage |
|
||||
|---------|---------|-------|
|
||||
| Page title | `text-xl font-bold` | Top of pages |
|
||||
| Section title | `text-lg font-semibold` | Major sections |
|
||||
| Section heading | `text-sm font-semibold text-muted-foreground uppercase tracking-wide` | Section headers in design guide, sidebar |
|
||||
| Card title | `text-sm font-medium` or `text-sm font-semibold` | Card headers, list item titles |
|
||||
| Body | `text-sm` | Default body text |
|
||||
| Muted | `text-sm text-muted-foreground` | Descriptions, secondary text |
|
||||
| Tiny label | `text-xs text-muted-foreground` | Metadata, timestamps, property labels |
|
||||
| Mono identifier | `text-xs font-mono text-muted-foreground` | Issue keys (PAP-001), CSS vars |
|
||||
| Large stat | `text-2xl font-bold` | Dashboard metric values |
|
||||
| Code/log | `font-mono text-xs` | Log output, code snippets |
|
||||
|
||||
---
|
||||
|
||||
## 5. Status & Priority Systems
|
||||
|
||||
### Status Colors (consistent across all entities)
|
||||
|
||||
Defined in `StatusBadge.tsx` and `StatusIcon.tsx`:
|
||||
|
||||
| Status | Color | Entity types |
|
||||
|--------|-------|-------------|
|
||||
| active, achieved, completed, succeeded, approved, done | Green shades | Agents, goals, issues, approvals |
|
||||
| running | Cyan | Agents |
|
||||
| paused | Orange | Agents |
|
||||
| idle, pending | Yellow | Agents, approvals |
|
||||
| failed, error, rejected, blocked | Red shades | Runs, agents, approvals, issues |
|
||||
| archived, planned, backlog, cancelled | Neutral gray | Various |
|
||||
| todo | Blue | Issues |
|
||||
| in_progress | Indigo | Issues |
|
||||
| in_review | Violet | Issues |
|
||||
|
||||
### Priority Icons
|
||||
|
||||
Defined in `PriorityIcon.tsx`: critical (red/AlertTriangle), high (orange/ArrowUp), medium (yellow/Minus), low (blue/ArrowDown).
|
||||
|
||||
### Agent Status Dots
|
||||
|
||||
Inline colored dots: running (cyan, animate-pulse), active (green), paused (yellow), error (red), offline (neutral).
|
||||
|
||||
---
|
||||
|
||||
## 6. Component Hierarchy
|
||||
|
||||
Three tiers:
|
||||
|
||||
1. **shadcn/ui primitives** (`ui/src/components/ui/`) — Button, Card, Input, Badge, Dialog, Tabs, etc. Do not modify these directly; extend via composition.
|
||||
2. **Custom composites** (`ui/src/components/`) — StatusBadge, EntityRow, MetricCard, etc. These capture Paperclip-specific design language.
|
||||
3. **Page components** (`ui/src/pages/`) — Compose primitives and composites into full views.
|
||||
|
||||
**See [references/component-index.md](references/component-index.md) for the complete component inventory with usage guidance.**
|
||||
|
||||
### When to Create a New Component
|
||||
|
||||
Create a reusable component when:
|
||||
- The same visual pattern appears in 2+ places
|
||||
- The pattern has interactive behavior (status changing, inline editing)
|
||||
- The pattern encodes domain logic (status colors, priority icons)
|
||||
|
||||
Do NOT create a component for:
|
||||
- One-off layouts specific to a single page
|
||||
- Simple className combinations (use Tailwind directly)
|
||||
- Thin wrappers that add no semantic value
|
||||
|
||||
---
|
||||
|
||||
## 7. Composition Patterns
|
||||
|
||||
These patterns describe how components work together. They may not be their own component, but they must be used consistently across the app.
|
||||
|
||||
### Entity Row with Status + Priority
|
||||
|
||||
The standard list item for issues and similar entities:
|
||||
|
||||
```tsx
|
||||
<EntityRow
|
||||
leading={<><StatusIcon status="in_progress" /><PriorityIcon priority="high" /></>}
|
||||
identifier="PAP-001"
|
||||
title="Implement authentication flow"
|
||||
subtitle="Assigned to Agent Alpha"
|
||||
trailing={<StatusBadge status="in_progress" />}
|
||||
onClick={() => {}}
|
||||
/>
|
||||
```
|
||||
|
||||
Leading slot always: StatusIcon first, then PriorityIcon. Trailing slot: StatusBadge or timestamp.
|
||||
|
||||
### Grouped List
|
||||
|
||||
Issues grouped by status header + entity rows:
|
||||
|
||||
```tsx
|
||||
<div className="flex items-center gap-2 px-4 py-2 bg-muted/50 rounded-t-md">
|
||||
<StatusIcon status="in_progress" />
|
||||
<span className="text-sm font-medium">In Progress</span>
|
||||
<span className="text-xs text-muted-foreground ml-1">2</span>
|
||||
</div>
|
||||
<div className="border border-border rounded-b-md">
|
||||
<EntityRow ... />
|
||||
<EntityRow ... />
|
||||
</div>
|
||||
```
|
||||
|
||||
### Property Row
|
||||
|
||||
Key-value pairs in properties panels:
|
||||
|
||||
```tsx
|
||||
<div className="flex items-center justify-between py-1.5">
|
||||
<span className="text-xs text-muted-foreground">Status</span>
|
||||
<StatusBadge status="active" />
|
||||
</div>
|
||||
```
|
||||
|
||||
Label is always `text-xs text-muted-foreground`, value on the right. Wrap in a container with `space-y-1`.
|
||||
|
||||
### Metric Card Grid
|
||||
|
||||
Dashboard metrics in a responsive grid:
|
||||
|
||||
```tsx
|
||||
<div className="grid md:grid-cols-2 xl:grid-cols-4 gap-4">
|
||||
<MetricCard icon={Bot} value={12} label="Active Agents" description="+3 this week" />
|
||||
...
|
||||
</div>
|
||||
```
|
||||
|
||||
### Progress Bar (Budget)
|
||||
|
||||
Color by threshold: green (<60%), yellow (60-85%), red (>85%):
|
||||
|
||||
```tsx
|
||||
<div className="w-full h-2 bg-muted rounded-full overflow-hidden">
|
||||
<div className="h-full rounded-full bg-green-400" style={{ width: `${pct}%` }} />
|
||||
</div>
|
||||
```
|
||||
|
||||
### Comment Thread
|
||||
|
||||
Author header (name + timestamp) then body, in bordered cards with `space-y-3`. Add comment textarea + button below.
|
||||
|
||||
### Cost Table
|
||||
|
||||
Standard `<table>` with `text-xs`, header row with `bg-accent/20`, `font-mono` for numeric values.
|
||||
|
||||
### Log Viewer
|
||||
|
||||
`bg-neutral-950 rounded-lg p-3 font-mono text-xs` container. Color lines by level: default (foreground), WARN (yellow-400), ERROR (red-400), SYS (blue-300). Include live indicator dot when streaming.
|
||||
|
||||
---
|
||||
|
||||
## 8. Interactive Patterns
|
||||
|
||||
### Hover States
|
||||
|
||||
- Entity rows: `hover:bg-accent/50`
|
||||
- Nav items: `hover:bg-accent/50 hover:text-accent-foreground`
|
||||
- Active nav: `bg-accent text-accent-foreground`
|
||||
|
||||
### Focus
|
||||
|
||||
`focus-visible:ring-ring focus-visible:ring-[3px]` — standard Tailwind focus-visible ring.
|
||||
|
||||
### Disabled
|
||||
|
||||
`disabled:opacity-50 disabled:pointer-events-none`
|
||||
|
||||
### Inline Editing
|
||||
|
||||
Use `InlineEditor` component — click text to edit, Enter saves, Escape cancels.
|
||||
|
||||
### Popover Selectors
|
||||
|
||||
StatusIcon and PriorityIcon use Radix Popover for inline selection. Follow this pattern for any clickable property that opens a picker.
|
||||
|
||||
---
|
||||
|
||||
## 9. Layout System
|
||||
|
||||
Three-zone layout defined in `Layout.tsx`:
|
||||
|
||||
```
|
||||
┌──────────┬──────────────────────────────┬──────────────────────┐
|
||||
│ Sidebar │ Breadcrumb bar │ │
|
||||
│ (w-60) ├──────────────────────────────┤ Properties panel │
|
||||
│ │ Main content (flex-1) │ (w-80, optional) │
|
||||
└──────────┴──────────────────────────────┴──────────────────────┘
|
||||
```
|
||||
|
||||
- Sidebar: `w-60`, collapsible, contains CompanySwitcher + SidebarSections
|
||||
- Properties panel: `w-80`, shown on detail views, hidden on lists
|
||||
- Main content: scrollable, `flex-1`
|
||||
|
||||
---
|
||||
|
||||
## 10. The /design-guide Page
|
||||
|
||||
**Location:** `ui/src/pages/DesignGuide.tsx`
|
||||
**Route:** `/design-guide`
|
||||
|
||||
This is the living showcase of every component and pattern in the app. It is the source of truth for how things look.
|
||||
|
||||
### Rules
|
||||
|
||||
1. **When you add a new reusable component, you MUST add it to the design guide page.** Show all variants, sizes, and states.
|
||||
2. **When you modify an existing component's API, update its design guide section.**
|
||||
3. **When you add a new composition pattern, add a section demonstrating it.**
|
||||
4. Follow the existing structure: `<Section title="...">` wrapper with `<SubSection>` for grouping.
|
||||
5. Keep sections ordered logically: foundational (colors, typography) first, then primitives, then composites, then patterns.
|
||||
|
||||
### Adding a New Section
|
||||
|
||||
```tsx
|
||||
<Section title="My New Component">
|
||||
<SubSection title="Variants">
|
||||
{/* Show all variants */}
|
||||
</SubSection>
|
||||
<SubSection title="Sizes">
|
||||
{/* Show all sizes */}
|
||||
</SubSection>
|
||||
<SubSection title="States">
|
||||
{/* Show interactive/disabled states */}
|
||||
</SubSection>
|
||||
</Section>
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 11. Component Index
|
||||
|
||||
**See [references/component-index.md](references/component-index.md) for the full component inventory.**
|
||||
|
||||
When you create a new reusable component:
|
||||
1. Add it to the component index reference file
|
||||
2. Add it to the /design-guide page
|
||||
3. Follow existing naming and file conventions
|
||||
|
||||
---
|
||||
|
||||
## 12. File Conventions
|
||||
|
||||
- **shadcn primitives:** `ui/src/components/ui/{component}.tsx` — lowercase, kebab-case
|
||||
- **Custom components:** `ui/src/components/{ComponentName}.tsx` — PascalCase
|
||||
- **Pages:** `ui/src/pages/{PageName}.tsx` — PascalCase
|
||||
- **Utilities:** `ui/src/lib/{name}.ts`
|
||||
- **Hooks:** `ui/src/hooks/{useName}.ts`
|
||||
- **API modules:** `ui/src/api/{entity}.ts`
|
||||
- **Context providers:** `ui/src/context/{Name}Context.tsx`
|
||||
|
||||
All components use `cn()` from `@/lib/utils` for className merging. All components use CVA for variant definitions when they have multiple visual variants.
|
||||
|
||||
---
|
||||
|
||||
## 13. Common Mistakes to Avoid
|
||||
|
||||
- Using raw hex/rgb colors instead of CSS variable tokens
|
||||
- Creating ad-hoc typography styles instead of using the established scale
|
||||
- Hardcoding status colors instead of using StatusBadge/StatusIcon
|
||||
- Building one-off styled elements when a reusable component exists
|
||||
- Adding components without updating the design guide page
|
||||
- Using `shadow-md` or heavier — keep shadows minimal (xs, sm only)
|
||||
- Using `rounded-2xl` or larger — max is `rounded-xl` (except `rounded-full` for pills)
|
||||
- Forgetting dark mode — always use semantic tokens, never hardcode light/dark values
|
||||
309
.claude/skills/design-guide/references/component-index.md
Normal file
309
.claude/skills/design-guide/references/component-index.md
Normal file
@@ -0,0 +1,309 @@
|
||||
# Paperclip Component Index
|
||||
|
||||
Complete inventory of all UI components. Update this file when adding new reusable components.
|
||||
|
||||
---
|
||||
|
||||
## Table of Contents
|
||||
|
||||
1. [shadcn/ui Primitives](#shadcnui-primitives)
|
||||
2. [Custom Components](#custom-components)
|
||||
3. [Layout Components](#layout-components)
|
||||
4. [Dialog & Form Components](#dialog--form-components)
|
||||
5. [Property Panel Components](#property-panel-components)
|
||||
6. [Agent Configuration](#agent-configuration)
|
||||
7. [Utilities & Hooks](#utilities--hooks)
|
||||
|
||||
---
|
||||
|
||||
## shadcn/ui Primitives
|
||||
|
||||
Location: `ui/src/components/ui/`
|
||||
|
||||
These are shadcn/ui base components. Do not modify directly — extend via composition.
|
||||
|
||||
| Component | File | Key Props | Notes |
|
||||
|-----------|------|-----------|-------|
|
||||
| Button | `button.tsx` | `variant` (default, secondary, outline, ghost, destructive, link), `size` (xs, sm, default, lg, icon, icon-xs, icon-sm, icon-lg) | Primary interactive element. Uses CVA. |
|
||||
| Card | `card.tsx` | CardHeader, CardTitle, CardDescription, CardAction, CardContent, CardFooter | Compound component. `py-6` default padding. |
|
||||
| Input | `input.tsx` | `disabled` | Standard text input. |
|
||||
| Badge | `badge.tsx` | `variant` (default, secondary, outline, destructive, ghost) | Generic label/tag. For status, use StatusBadge instead. |
|
||||
| Label | `label.tsx` | — | Form label, wraps Radix Label. |
|
||||
| Select | `select.tsx` | Trigger, Content, Item, etc. | Radix-based dropdown select. |
|
||||
| Separator | `separator.tsx` | `orientation` (horizontal, vertical) | Divider line. |
|
||||
| Checkbox | `checkbox.tsx` | `checked`, `onCheckedChange` | Radix checkbox with indicator. |
|
||||
| Textarea | `textarea.tsx` | Standard textarea props | Multi-line input. |
|
||||
| Avatar | `avatar.tsx` | `size` (sm, default, lg). Includes AvatarGroup, AvatarGroupCount | Image or fallback initials. |
|
||||
| Breadcrumb | `breadcrumb.tsx` | BreadcrumbList, BreadcrumbItem, BreadcrumbLink, BreadcrumbSeparator, BreadcrumbPage | Navigation breadcrumbs. |
|
||||
| Command | `command.tsx` | CommandInput, CommandList, CommandGroup, CommandItem | Command palette / search. Based on cmdk. |
|
||||
| Dialog | `dialog.tsx` | DialogTrigger, DialogContent, DialogHeader, DialogTitle, DialogDescription, DialogFooter | Modal overlay. |
|
||||
| DropdownMenu | `dropdown-menu.tsx` | Trigger, Content, Item, Separator, etc. | Context/action menus. |
|
||||
| Popover | `popover.tsx` | PopoverTrigger, PopoverContent | Floating content panel. |
|
||||
| Tabs | `tabs.tsx` | `variant` (pill, line). TabsList, TabsTrigger, TabsContent | Tabbed navigation. Pill = default, line = underline style. |
|
||||
| Tooltip | `tooltip.tsx` | TooltipTrigger, TooltipContent | Hover tooltips. App is wrapped in TooltipProvider. |
|
||||
| ScrollArea | `scroll-area.tsx` | — | Custom scrollable container. |
|
||||
| Collapsible | `collapsible.tsx` | CollapsibleTrigger, CollapsibleContent | Expand/collapse sections. |
|
||||
| Skeleton | `skeleton.tsx` | className for sizing | Loading placeholder with shimmer. |
|
||||
| Sheet | `sheet.tsx` | SheetTrigger, SheetContent, SheetHeader, etc. | Side panel overlay. |
|
||||
|
||||
---
|
||||
|
||||
## Custom Components
|
||||
|
||||
Location: `ui/src/components/`
|
||||
|
||||
### StatusBadge
|
||||
|
||||
**File:** `StatusBadge.tsx`
|
||||
**Props:** `status: string`
|
||||
**Usage:** Colored pill showing entity status. Supports 20+ statuses with mapped colors.
|
||||
|
||||
```tsx
|
||||
<StatusBadge status="in_progress" />
|
||||
```
|
||||
|
||||
Use for displaying status in properties panels, entity rows, and list views. Never hardcode status colors — always use this component.
|
||||
|
||||
### StatusIcon
|
||||
|
||||
**File:** `StatusIcon.tsx`
|
||||
**Props:** `status: string`, `onChange?: (status: string) => void`
|
||||
**Usage:** Circle icon representing issue status. When `onChange` provided, opens a popover picker.
|
||||
|
||||
```tsx
|
||||
<StatusIcon status="todo" onChange={setStatus} />
|
||||
```
|
||||
|
||||
Supports: backlog, todo, in_progress, in_review, done, cancelled, blocked. Use in entity row leading slots and grouped list headers.
|
||||
|
||||
### PriorityIcon
|
||||
|
||||
**File:** `PriorityIcon.tsx`
|
||||
**Props:** `priority: string`, `onChange?: (priority: string) => void`
|
||||
**Usage:** Priority indicator icon. Interactive when `onChange` provided.
|
||||
|
||||
```tsx
|
||||
<PriorityIcon priority="high" onChange={setPriority} />
|
||||
```
|
||||
|
||||
Supports: critical, high, medium, low. Use alongside StatusIcon in entity row leading slots.
|
||||
|
||||
### EntityRow
|
||||
|
||||
**File:** `EntityRow.tsx`
|
||||
**Props:** `leading`, `identifier`, `title`, `subtitle?`, `trailing?`, `onClick?`, `selected?`
|
||||
**Usage:** Standard list row for issues, agents, projects. Supports hover highlight and selected state.
|
||||
|
||||
```tsx
|
||||
<EntityRow
|
||||
leading={<><StatusIcon status="todo" /><PriorityIcon priority="medium" /></>}
|
||||
identifier="PAP-003"
|
||||
title="Write API documentation"
|
||||
trailing={<StatusBadge status="todo" />}
|
||||
onClick={() => navigate(`/issues/${id}`)}
|
||||
/>
|
||||
```
|
||||
|
||||
Wrap multiple EntityRows in a `border border-border rounded-md` container.
|
||||
|
||||
### MetricCard
|
||||
|
||||
**File:** `MetricCard.tsx`
|
||||
**Props:** `icon: LucideIcon`, `value: string | number`, `label: string`, `description?: string`
|
||||
**Usage:** Dashboard stat card with icon, large value, label, and optional description.
|
||||
|
||||
```tsx
|
||||
<MetricCard icon={Bot} value={12} label="Active Agents" description="+3 this week" />
|
||||
```
|
||||
|
||||
Always use in a responsive grid: `grid md:grid-cols-2 xl:grid-cols-4 gap-4`.
|
||||
|
||||
### EmptyState
|
||||
|
||||
**File:** `EmptyState.tsx`
|
||||
**Props:** `icon: LucideIcon`, `message: string`, `action?: string`, `onAction?: () => void`
|
||||
**Usage:** Empty list placeholder with icon, message, and optional CTA button.
|
||||
|
||||
```tsx
|
||||
<EmptyState icon={Inbox} message="No items yet." action="Create Item" onAction={handleCreate} />
|
||||
```
|
||||
|
||||
### FilterBar
|
||||
|
||||
**File:** `FilterBar.tsx`
|
||||
**Props:** `filters: FilterValue[]`, `onRemove: (key) => void`, `onClear: () => void`
|
||||
**Type:** `FilterValue = { key: string; label: string; value: string }`
|
||||
**Usage:** Filter chip display with remove buttons and clear all.
|
||||
|
||||
```tsx
|
||||
<FilterBar filters={filters} onRemove={handleRemove} onClear={() => setFilters([])} />
|
||||
```
|
||||
|
||||
### InlineEditor
|
||||
|
||||
**File:** `InlineEditor.tsx`
|
||||
**Props:** `value: string`, `onSave: (val: string) => void`, `as?: string`, `className?: string`
|
||||
**Usage:** Click-to-edit text. Renders as display text, clicking enters edit mode. Enter saves, Escape cancels.
|
||||
|
||||
```tsx
|
||||
<InlineEditor value={title} onSave={updateTitle} as="h2" className="text-xl font-bold" />
|
||||
```
|
||||
|
||||
### PageSkeleton
|
||||
|
||||
**File:** `PageSkeleton.tsx`
|
||||
**Props:** `variant: "list" | "detail"`
|
||||
**Usage:** Full-page loading skeleton matching list or detail layout.
|
||||
|
||||
```tsx
|
||||
<PageSkeleton variant="list" />
|
||||
```
|
||||
|
||||
### CommentThread
|
||||
|
||||
**File:** `CommentThread.tsx`
|
||||
**Usage:** Comment list with add-comment form. Used on issue and entity detail views.
|
||||
|
||||
### GoalTree
|
||||
|
||||
**File:** `GoalTree.tsx`
|
||||
**Usage:** Hierarchical goal tree with expand/collapse. Used on the goals page.
|
||||
|
||||
### CompanySwitcher
|
||||
|
||||
**File:** `CompanySwitcher.tsx`
|
||||
**Usage:** Company selector dropdown in sidebar header.
|
||||
|
||||
---
|
||||
|
||||
## Layout Components
|
||||
|
||||
### Layout
|
||||
|
||||
**File:** `Layout.tsx`
|
||||
**Usage:** Main app shell. Three-zone layout: Sidebar + Main content + Properties panel. Wraps all routes.
|
||||
|
||||
### Sidebar
|
||||
|
||||
**File:** `Sidebar.tsx`
|
||||
**Usage:** Left navigation sidebar (`w-60`). Contains CompanySwitcher, search button, new issue button, and SidebarSections.
|
||||
|
||||
### SidebarSection
|
||||
|
||||
**File:** `SidebarSection.tsx`
|
||||
**Usage:** Collapsible sidebar group with header label and chevron toggle.
|
||||
|
||||
### SidebarNavItem
|
||||
|
||||
**File:** `SidebarNavItem.tsx`
|
||||
**Props:** Icon, label, optional badge count
|
||||
**Usage:** Individual nav item within a SidebarSection.
|
||||
|
||||
### BreadcrumbBar
|
||||
|
||||
**File:** `BreadcrumbBar.tsx`
|
||||
**Usage:** Top breadcrumb navigation spanning main content + properties panel.
|
||||
|
||||
### PropertiesPanel
|
||||
|
||||
**File:** `PropertiesPanel.tsx`
|
||||
**Usage:** Right-side properties panel (`w-80`). Closeable. Shown on detail views.
|
||||
|
||||
### CommandPalette
|
||||
|
||||
**File:** `CommandPalette.tsx`
|
||||
**Usage:** Cmd+K global search modal. Searches issues, projects, agents.
|
||||
|
||||
---
|
||||
|
||||
## Dialog & Form Components
|
||||
|
||||
### NewIssueDialog
|
||||
|
||||
**File:** `NewIssueDialog.tsx`
|
||||
**Usage:** Create new issue with project/assignee/priority selection. Supports draft saving.
|
||||
|
||||
### NewProjectDialog
|
||||
|
||||
**File:** `NewProjectDialog.tsx`
|
||||
**Usage:** Create new project dialog.
|
||||
|
||||
### NewAgentDialog
|
||||
|
||||
**File:** `NewAgentDialog.tsx`
|
||||
**Usage:** Create new agent dialog.
|
||||
|
||||
### OnboardingWizard
|
||||
|
||||
**File:** `OnboardingWizard.tsx`
|
||||
**Usage:** Multi-step onboarding flow for new users/companies.
|
||||
|
||||
---
|
||||
|
||||
## Property Panel Components
|
||||
|
||||
These render inside the PropertiesPanel for different entity types:
|
||||
|
||||
| Component | File | Entity |
|
||||
|-----------|------|--------|
|
||||
| IssueProperties | `IssueProperties.tsx` | Issues |
|
||||
| AgentProperties | `AgentProperties.tsx` | Agents |
|
||||
| ProjectProperties | `ProjectProperties.tsx` | Projects |
|
||||
| GoalProperties | `GoalProperties.tsx` | Goals |
|
||||
|
||||
All follow the property row pattern: `text-xs text-muted-foreground` label on left, value on right, `py-1.5` spacing.
|
||||
|
||||
---
|
||||
|
||||
## Agent Configuration
|
||||
|
||||
### agent-config-primitives
|
||||
|
||||
**File:** `agent-config-primitives.tsx`
|
||||
**Exports:** Field, ToggleField, ToggleWithNumber, CollapsibleSection, AutoExpandTextarea, DraftInput
|
||||
**Usage:** Reusable form field primitives for agent configuration forms.
|
||||
|
||||
### AgentConfigForm
|
||||
|
||||
**File:** `AgentConfigForm.tsx`
|
||||
**Usage:** Full agent creation/editing form with adapter type selection.
|
||||
|
||||
---
|
||||
|
||||
## Utilities & Hooks
|
||||
|
||||
### cn() — Class Name Merger
|
||||
|
||||
**File:** `ui/src/lib/utils.ts`
|
||||
**Usage:** Merges class names with clsx + tailwind-merge. Use in every component.
|
||||
|
||||
```tsx
|
||||
import { cn } from "@/lib/utils";
|
||||
<div className={cn("base-classes", conditional && "extra", className)} />
|
||||
```
|
||||
|
||||
### Formatting Utilities
|
||||
|
||||
**File:** `ui/src/lib/utils.ts`
|
||||
|
||||
| Function | Usage |
|
||||
|----------|-------|
|
||||
| `formatCents(cents)` | Money display: `$12.34` |
|
||||
| `formatDate(date)` | Date display: `Jan 15, 2025` |
|
||||
| `relativeTime(date)` | Relative time: `2m ago`, `Jan 15` |
|
||||
| `formatTokens(count)` | Token counts: `1.2M`, `500k` |
|
||||
|
||||
### useKeyboardShortcuts
|
||||
|
||||
**File:** `ui/src/hooks/useKeyboardShortcuts.ts`
|
||||
**Usage:** Global keyboard shortcut handler. Registers Cmd+K, C, [, ], Cmd+Enter.
|
||||
|
||||
### Query Keys
|
||||
|
||||
**File:** `ui/src/lib/queryKeys.ts`
|
||||
**Usage:** Structured React Query key factories for cache management.
|
||||
|
||||
### groupBy
|
||||
|
||||
**File:** `ui/src/lib/groupBy.ts`
|
||||
**Usage:** Generic array grouping utility.
|
||||
Reference in New Issue
Block a user