checkpoint: pre-split branch cleanup
This commit is contained in:
parent
4c2ae2e5b7
commit
b5db7a7753
276 changed files with 35912 additions and 60119 deletions
1
.agent/skills/shadcn-ui
Symbolic link
1
.agent/skills/shadcn-ui
Symbolic link
|
|
@ -0,0 +1 @@
|
|||
/mnt/c/Users/Zenchant/codex/beadboard/.agents/skills/shadcn-ui/
|
||||
File diff suppressed because it is too large
Load diff
|
|
@ -1,306 +0,0 @@
|
|||
### shadcn/ui Chart Component - Installation
|
||||
|
||||
Source: https://ui.shadcn.com/docs/components/chart
|
||||
|
||||
The chart component in shadcn/ui is built on Recharts, providing direct access to all Recharts capabilities with consistent theming.
|
||||
|
||||
```bash
|
||||
npx shadcn@latest add chart
|
||||
```
|
||||
|
||||
--------------------------------
|
||||
|
||||
### shadcn/ui Chart Component - Basic Usage
|
||||
|
||||
Source: https://ui.shadcn.com/docs/components/chart
|
||||
|
||||
The ChartContainer wraps your Recharts component and accepts a config prop for theming. Requires `min-h-[value]` for responsiveness.
|
||||
|
||||
```tsx
|
||||
import { Bar, BarChart, CartesianGrid, XAxis, YAxis } from "recharts"
|
||||
import { ChartContainer, ChartTooltipContent } from "@/components/ui/chart"
|
||||
|
||||
const chartConfig = {
|
||||
desktop: {
|
||||
label: "Desktop",
|
||||
color: "var(--chart-1)",
|
||||
},
|
||||
mobile: {
|
||||
label: "Mobile",
|
||||
color: "var(--chart-2)",
|
||||
},
|
||||
} satisfies import("@/components/ui/chart").ChartConfig
|
||||
|
||||
const chartData = [
|
||||
{ month: "January", desktop: 186, mobile: 80 },
|
||||
{ month: "February", desktop: 305, mobile: 200 },
|
||||
{ month: "March", desktop: 237, mobile: 120 },
|
||||
]
|
||||
|
||||
export function BarChartDemo() {
|
||||
return (
|
||||
<ChartContainer config={chartConfig} className="min-h-[200px] w-full">
|
||||
<BarChart data={chartData}>
|
||||
<CartesianGrid vertical={false} />
|
||||
<XAxis dataKey="month" tickLine={false} axisLine={false} />
|
||||
<Bar dataKey="desktop" fill="var(--color-desktop)" radius={4} />
|
||||
<Bar dataKey="mobile" fill="var(--color-mobile)" radius={4} />
|
||||
<ChartTooltip content={<ChartTooltipContent />} />
|
||||
</BarChart>
|
||||
</ChartContainer>
|
||||
)
|
||||
}
|
||||
```
|
||||
|
||||
--------------------------------
|
||||
|
||||
### shadcn/ui Chart Component - ChartConfig with Custom Colors
|
||||
|
||||
Source: https://ui.shadcn.com/docs/components/chart
|
||||
|
||||
You can define custom colors directly in the configuration using hex values or CSS variables.
|
||||
|
||||
```tsx
|
||||
const chartConfig = {
|
||||
desktop: {
|
||||
label: "Desktop",
|
||||
color: "#2563eb",
|
||||
theme: {
|
||||
light: "#2563eb",
|
||||
dark: "#60a5fa",
|
||||
},
|
||||
},
|
||||
mobile: {
|
||||
label: "Mobile",
|
||||
color: "var(--chart-2)",
|
||||
},
|
||||
} satisfies import("@/components/ui/chart").ChartConfig
|
||||
```
|
||||
|
||||
--------------------------------
|
||||
|
||||
### shadcn/ui Chart Component - CSS Variables
|
||||
|
||||
Source: https://ui.shadcn.com/docs/components/chart
|
||||
|
||||
Add chart color variables to your globals.css for consistent theming.
|
||||
|
||||
```css
|
||||
:root {
|
||||
/* Chart colors */
|
||||
--chart-1: oklch(0.646 0.222 41.116);
|
||||
--chart-2: oklch(0.6 0.118 184.704);
|
||||
--chart-3: oklch(0.546 0.198 38.228);
|
||||
--chart-4: oklch(0.596 0.151 343.253);
|
||||
--chart-5: oklch(0.546 0.158 49.157);
|
||||
}
|
||||
|
||||
.dark {
|
||||
--chart-1: oklch(0.488 0.243 264.376);
|
||||
--chart-2: oklch(0.696 0.17 162.48);
|
||||
--chart-3: oklch(0.698 0.141 24.311);
|
||||
--chart-4: oklch(0.676 0.172 171.196);
|
||||
--chart-5: oklch(0.578 0.192 302.85);
|
||||
}
|
||||
```
|
||||
|
||||
--------------------------------
|
||||
|
||||
### shadcn/ui Chart Component - Line Chart Example
|
||||
|
||||
Source: https://ui.shadcn.com/docs/components/chart
|
||||
|
||||
Creating a line chart with shadcn/ui charts component.
|
||||
|
||||
```tsx
|
||||
import { Line, LineChart, CartesianGrid, XAxis, YAxis } from "recharts"
|
||||
import { ChartContainer, ChartTooltipContent } from "@/components/ui/chart"
|
||||
|
||||
const chartConfig = {
|
||||
price: {
|
||||
label: "Price",
|
||||
color: "var(--chart-1)",
|
||||
},
|
||||
} satisfies import("@/components/ui/chart").ChartConfig
|
||||
|
||||
const chartData = [
|
||||
{ month: "January", price: 186 },
|
||||
{ month: "February", price: 305 },
|
||||
{ month: "March", price: 237 },
|
||||
{ month: "April", price: 203 },
|
||||
{ month: "May", price: 276 },
|
||||
]
|
||||
|
||||
export function LineChartDemo() {
|
||||
return (
|
||||
<ChartContainer config={chartConfig} className="min-h-[200px]">
|
||||
<LineChart data={chartData}>
|
||||
<CartesianGrid vertical={false} />
|
||||
<XAxis dataKey="month" tickLine={false} axisLine={false} />
|
||||
<YAxis tickLine={false} axisLine={false} tickFormatter={(value) => `$${value}`} />
|
||||
<Line
|
||||
dataKey="price"
|
||||
stroke="var(--color-price)"
|
||||
strokeWidth={2}
|
||||
dot={false}
|
||||
/>
|
||||
<ChartTooltip content={<ChartTooltipContent />} />
|
||||
</LineChart>
|
||||
</ChartContainer>
|
||||
)
|
||||
}
|
||||
```
|
||||
|
||||
--------------------------------
|
||||
|
||||
### shadcn/ui Chart Component - Area Chart Example
|
||||
|
||||
Source: https://ui.shadcn.com/docs/components/chart
|
||||
|
||||
Creating an area chart with gradient fill and legend.
|
||||
|
||||
```tsx
|
||||
import { Area, AreaChart, XAxis, YAxis } from "recharts"
|
||||
import {
|
||||
ChartContainer,
|
||||
ChartLegend,
|
||||
ChartLegendContent,
|
||||
ChartTooltipContent,
|
||||
} from "@/components/ui/chart"
|
||||
|
||||
const chartConfig = {
|
||||
desktop: { label: "Desktop", color: "var(--chart-1)" },
|
||||
mobile: { label: "Mobile", color: "var(--chart-2)" },
|
||||
} satisfies import("@/components/ui/chart").ChartConfig
|
||||
|
||||
export function AreaChartDemo() {
|
||||
return (
|
||||
<ChartContainer config={chartConfig} className="min-h-[200px]">
|
||||
<AreaChart data={chartData}>
|
||||
<XAxis dataKey="month" tickLine={false} axisLine={false} />
|
||||
<YAxis tickLine={false} axisLine={false} />
|
||||
<Area
|
||||
dataKey="desktop"
|
||||
fill="var(--color-desktop)"
|
||||
stroke="var(--color-desktop)"
|
||||
fillOpacity={0.3}
|
||||
/>
|
||||
<Area
|
||||
dataKey="mobile"
|
||||
fill="var(--color-mobile)"
|
||||
stroke="var(--color-mobile)"
|
||||
fillOpacity={0.3}
|
||||
/>
|
||||
<ChartTooltip content={<ChartTooltipContent />} />
|
||||
<ChartLegend content={<ChartLegendContent />} />
|
||||
</AreaChart>
|
||||
</ChartContainer>
|
||||
)
|
||||
}
|
||||
```
|
||||
|
||||
--------------------------------
|
||||
|
||||
### shadcn/ui Chart Component - Pie Chart Example
|
||||
|
||||
Source: https://ui.shadcn.com/docs/components/chart
|
||||
|
||||
Creating a pie/donut chart with shadcn/ui.
|
||||
|
||||
```tsx
|
||||
import { Pie, PieChart } from "recharts"
|
||||
import {
|
||||
ChartContainer,
|
||||
ChartLegend,
|
||||
ChartLegendContent,
|
||||
ChartTooltipContent,
|
||||
} from "@/components/ui/chart"
|
||||
|
||||
const chartConfig = {
|
||||
chrome: { label: "Chrome", color: "var(--chart-1)" },
|
||||
safari: { label: "Safari", color: "var(--chart-2)" },
|
||||
firefox: { label: "Firefox", color: "var(--chart-3)" },
|
||||
} satisfies import("@/components/ui/chart").ChartConfig
|
||||
|
||||
const pieData = [
|
||||
{ browser: "Chrome", visitors: 275, fill: "var(--color-chrome)" },
|
||||
{ browser: "Safari", visitors: 200, fill: "var(--color-safari)" },
|
||||
{ browser: "Firefox", visitors: 187, fill: "var(--color-firefox)" },
|
||||
]
|
||||
|
||||
export function PieChartDemo() {
|
||||
return (
|
||||
<ChartContainer config={chartConfig} className="min-h-[200px]">
|
||||
<PieChart>
|
||||
<Pie
|
||||
data={pieData}
|
||||
dataKey="visitors"
|
||||
nameKey="browser"
|
||||
cx="50%"
|
||||
cy="50%"
|
||||
outerRadius={80}
|
||||
/>
|
||||
<ChartTooltip content={<ChartTooltipContent />} />
|
||||
<ChartLegend content={<ChartLegendContent />} />
|
||||
</PieChart>
|
||||
</ChartContainer>
|
||||
)
|
||||
}
|
||||
```
|
||||
|
||||
--------------------------------
|
||||
|
||||
### shadcn/ui ChartTooltipContent Props
|
||||
|
||||
Source: https://ui.shadcn.com/docs/components/chart
|
||||
|
||||
The ChartTooltipContent component accepts these props for customizing tooltip behavior.
|
||||
|
||||
| Prop | Type | Default | Description |
|
||||
|------|------|---------|-------------|
|
||||
| `labelKey` | string | "label" | Key for tooltip label |
|
||||
| `nameKey` | string | "name" | Key for tooltip name |
|
||||
| `indicator` | "dot" \| "line" \| "dashed" | "dot" | Indicator style |
|
||||
| `hideLabel` | boolean | false | Hide label |
|
||||
| `hideIndicator` | boolean | false | Hide indicator |
|
||||
|
||||
--------------------------------
|
||||
|
||||
### shadcn/ui Chart Component - Accessibility
|
||||
|
||||
Source: https://ui.shadcn.com/docs/components/chart
|
||||
|
||||
Enable keyboard navigation and screen reader support by adding the accessibilityLayer prop.
|
||||
|
||||
```tsx
|
||||
<BarChart accessibilityLayer data={chartData}>
|
||||
<CartesianGrid vertical={false} />
|
||||
<XAxis dataKey="month" />
|
||||
<Bar dataKey="desktop" fill="var(--color-desktop)" />
|
||||
<ChartTooltip content={<ChartTooltipContent />} />
|
||||
</BarChart>
|
||||
```
|
||||
|
||||
This adds:
|
||||
- Keyboard arrow key navigation
|
||||
- ARIA labels for chart elements
|
||||
- Screen reader announcements for data values
|
||||
|
||||
--------------------------------
|
||||
|
||||
### shadcn/ui Chart Component - Recharts Dependencies
|
||||
|
||||
Source: https://ui.shadcn.com/docs/components/chart
|
||||
|
||||
The chart component requires the following Recharts dependencies to be installed.
|
||||
|
||||
```bash
|
||||
pnpm add recharts
|
||||
npm install recharts
|
||||
yarn add recharts
|
||||
```
|
||||
|
||||
Recharts provides the following chart types:
|
||||
- Area, Bar, Line, Pie, Composed
|
||||
- Radar, RadialBar, Scatter
|
||||
- Funnel, Treemap
|
||||
|
|
@ -1,145 +0,0 @@
|
|||
# shadcn/ui Learning Guide
|
||||
|
||||
This guide helps you learn shadcn/ui from basics to advanced patterns.
|
||||
|
||||
## Learning Path
|
||||
|
||||
### 1. Understanding the Philosophy
|
||||
|
||||
shadcn/ui is different from traditional component libraries:
|
||||
|
||||
- **Copy-paste components**: Components are copied into your project, not installed as packages
|
||||
- **Full customization**: You own the code and can modify it freely
|
||||
- **Built on Radix UI**: Provides accessibility primitives
|
||||
- **Styled with Tailwind**: Uses utility classes for consistent styling
|
||||
|
||||
### 2. Core Concepts to Master
|
||||
|
||||
#### Class Variance Authority (CVA)
|
||||
Most components use CVA for variant management:
|
||||
|
||||
```tsx
|
||||
const buttonVariants = cva(
|
||||
"base-classes",
|
||||
{
|
||||
variants: {
|
||||
variant: {
|
||||
default: "variant-classes",
|
||||
destructive: "destructive-classes",
|
||||
},
|
||||
size: {
|
||||
default: "size-classes",
|
||||
sm: "small-classes",
|
||||
},
|
||||
},
|
||||
defaultVariants: {
|
||||
variant: "default",
|
||||
size: "default",
|
||||
},
|
||||
}
|
||||
)
|
||||
```
|
||||
|
||||
#### cn Utility Function
|
||||
The `cn` function combines classes and resolves conflicts:
|
||||
|
||||
```tsx
|
||||
import { clsx, type ClassValue } from "clsx"
|
||||
import { twMerge } from "tailwind-merge"
|
||||
|
||||
export function cn(...inputs: ClassValue[]) {
|
||||
return twMerge(clsx(inputs))
|
||||
}
|
||||
```
|
||||
|
||||
### 3. Installation Checklist
|
||||
|
||||
- [ ] Initialize a new project (Next.js, Vite, or Remix)
|
||||
- [ ] Install Tailwind CSS
|
||||
- [ ] Run `npx shadcn@latest init`
|
||||
- [ ] Configure CSS variables
|
||||
- [ ] Install first component: `npx shadcn@latest add button`
|
||||
|
||||
### 4. Essential Components to Learn First
|
||||
|
||||
1. **Button** - Learn variants and sizes
|
||||
2. **Input** - Form inputs with labels
|
||||
3. **Card** - Container components
|
||||
4. **Form** - Form handling with React Hook Form
|
||||
5. **Dialog** - Modal windows
|
||||
6. **Select** - Dropdown selections
|
||||
7. **Toast** - Notifications
|
||||
|
||||
### 5. Common Patterns
|
||||
|
||||
#### Form Pattern
|
||||
Every form follows this structure:
|
||||
|
||||
```tsx
|
||||
1. Define Zod schema
|
||||
2. Create form with useForm
|
||||
3. Wrap with Form component
|
||||
4. Add FormField for each input
|
||||
5. Handle submission
|
||||
```
|
||||
|
||||
#### Component Customization Pattern
|
||||
To customize a component:
|
||||
|
||||
1. Copy component to your project
|
||||
2. Modify the variants
|
||||
3. Add new props if needed
|
||||
4. Update types
|
||||
|
||||
### 6. Best Practices
|
||||
|
||||
- Always use TypeScript
|
||||
- Follow the existing component structure
|
||||
- Use semantic HTML when possible
|
||||
- Test with screen readers for accessibility
|
||||
- Keep components small and focused
|
||||
|
||||
### 7. Advanced Topics
|
||||
|
||||
- Creating custom components from scratch
|
||||
- Building complex forms with validation
|
||||
- Implementing dark mode
|
||||
- Optimizing for performance
|
||||
- Testing components
|
||||
|
||||
## Practice Exercises
|
||||
|
||||
### Exercise 1: Basic Setup
|
||||
1. Create a new Next.js project
|
||||
2. Set up shadcn/ui
|
||||
3. Install and customize a Button component
|
||||
4. Add a new variant "gradient"
|
||||
|
||||
### Exercise 2: Form Building
|
||||
1. Create a contact form with:
|
||||
- Name input (required)
|
||||
- Email input (email validation)
|
||||
- Message textarea (min length)
|
||||
- Submit button with loading state
|
||||
|
||||
### Exercise 3: Component Combination
|
||||
1. Build a settings page using:
|
||||
- Card for layout
|
||||
- Sheet for mobile menu
|
||||
- Select for dropdowns
|
||||
- Switch for toggles
|
||||
- Toast for notifications
|
||||
|
||||
### Exercise 4: Custom Component
|
||||
1. Create a custom Badge component
|
||||
2. Support variants: default, secondary, destructive, outline
|
||||
3. Support sizes: sm, default, lg
|
||||
4. Add icon support
|
||||
|
||||
## Resources
|
||||
|
||||
- [Official Documentation](https://ui.shadcn.com)
|
||||
- [GitHub Repository](https://github.com/shadcn/ui)
|
||||
- [Examples Gallery](https://ui.shadcn.com/examples)
|
||||
- [Radix UI Primitives](https://www.radix-ui.com/primitives)
|
||||
- [Tailwind CSS Documentation](https://tailwindcss.com/docs)
|
||||
File diff suppressed because it is too large
Load diff
|
|
@ -1,586 +0,0 @@
|
|||
# shadcn.io Component Library
|
||||
|
||||
shadcn.io is a comprehensive React UI component library built on shadcn/ui principles, providing developers with production-ready, composable components for modern web applications. The library serves as a centralized resource for React developers who need high-quality UI components with TypeScript support, ranging from basic interactive elements to advanced AI-powered integrations. Unlike traditional component libraries that require package installations, shadcn.io components are designed to be copied directly into your project, giving you full control and customization capabilities.
|
||||
|
||||
The library encompasses four major categories: composable UI components (terminal, dock, credit cards, QR codes, color pickers), chart components built with Recharts, animation components with Tailwind CSS integration, and custom React hooks for state management and lifecycle operations. Each component follows best practices for accessibility, performance, and developer experience, with comprehensive TypeScript definitions and Next.js compatibility. The platform emphasizes flexibility and customization, allowing developers to modify components at the source level rather than being constrained by package APIs.
|
||||
|
||||
## Core Components
|
||||
|
||||
### Terminal Component
|
||||
Interactive terminal emulator with typing animations and command execution simulation for developer-focused interfaces.
|
||||
|
||||
```tsx
|
||||
import { Terminal } from "@/components/ui/terminal"
|
||||
|
||||
export default function DemoTerminal() {
|
||||
return (
|
||||
npm install @repo/terminalInstalling dependencies...npm start
|
||||
)
|
||||
}
|
||||
```
|
||||
|
||||
### Dock Component
|
||||
macOS-style application dock with smooth magnification effects on hover, perfect for navigation menus.
|
||||
|
||||
```tsx
|
||||
import { Dock, DockIcon } from "@/components/ui/dock"
|
||||
import { Home, Settings, User, Mail } from "lucide-react"
|
||||
|
||||
export default function AppDock() {
|
||||
return (
|
||||
|
||||
)
|
||||
}
|
||||
```
|
||||
|
||||
### Credit Card Component
|
||||
Interactive 3D credit card component with flip animations for payment forms and card displays.
|
||||
|
||||
```tsx
|
||||
import { CreditCard } from "@/components/ui/credit-card"
|
||||
import { useState } from "react"
|
||||
|
||||
export default function PaymentForm() {
|
||||
const [cardData, setCardData] = useState({
|
||||
number: "4532 1234 5678 9010",
|
||||
holder: "JOHN DOE",
|
||||
expiry: "12/28",
|
||||
cvv: "123"
|
||||
})
|
||||
|
||||
return (
|
||||
console.log("Card flipped:", flipped)}
|
||||
/>
|
||||
)
|
||||
}
|
||||
```
|
||||
|
||||
### Image Zoom Component
|
||||
Zoomable image component with smooth modal transitions for image galleries and product displays.
|
||||
|
||||
```tsx
|
||||
import { ImageZoom } from "@/components/ui/image-zoom"
|
||||
|
||||
export default function ProductGallery() {
|
||||
return (
|
||||
|
||||
|
||||
)
|
||||
}
|
||||
```
|
||||
|
||||
### QR Code Component
|
||||
Generate and display customizable QR codes with styling options for links, contact information, and authentication.
|
||||
|
||||
```tsx
|
||||
import { QRCode } from "@/components/ui/qr-code"
|
||||
|
||||
export default function ShareDialog() {
|
||||
const shareUrl = "https://shadcn.io"
|
||||
|
||||
return (
|
||||
|
||||
|
||||
Scan to visit shadcn.io
|
||||
|
||||
|
||||
)
|
||||
}
|
||||
```
|
||||
|
||||
### Color Picker Component
|
||||
Advanced color selection component supporting multiple color formats (HEX, RGB, HSL) with preview.
|
||||
|
||||
```tsx
|
||||
import { ColorPicker } from "@/components/ui/color-picker"
|
||||
import { useState } from "react"
|
||||
|
||||
export default function ThemeCustomizer() {
|
||||
const [color, setColor] = useState("#3b82f6")
|
||||
|
||||
return (
|
||||
|
||||
|
||||
Selected: {color}
|
||||
|
||||
)
|
||||
}
|
||||
```
|
||||
|
||||
## Chart Components
|
||||
|
||||
### Bar Chart Component
|
||||
Clean bar chart component for data comparison and categorical analysis using Recharts.
|
||||
|
||||
```tsx
|
||||
import { BarChart } from "@/components/ui/bar-chart"
|
||||
|
||||
export default function SalesChart() {
|
||||
const data = [
|
||||
{ month: "Jan", sales: 4000, revenue: 2400 },
|
||||
{ month: "Feb", sales: 3000, revenue: 1398 },
|
||||
{ month: "Mar", sales: 2000, revenue: 9800 },
|
||||
{ month: "Apr", sales: 2780, revenue: 3908 },
|
||||
{ month: "May", sales: 1890, revenue: 4800 },
|
||||
{ month: "Jun", sales: 2390, revenue: 3800 }
|
||||
]
|
||||
|
||||
return (
|
||||
`$${value.toLocaleString()}`}
|
||||
yAxisWidth={60}
|
||||
/>
|
||||
)
|
||||
}
|
||||
```
|
||||
|
||||
### Line Chart Component
|
||||
Smooth line chart for visualizing trends and time-series data with multiple data series support.
|
||||
|
||||
```tsx
|
||||
import { LineChart } from "@/components/ui/line-chart"
|
||||
|
||||
export default function MetricsChart() {
|
||||
const data = [
|
||||
{ date: "2024-01", users: 1200, sessions: 3400 },
|
||||
{ date: "2024-02", users: 1800, sessions: 4200 },
|
||||
{ date: "2024-03", users: 2400, sessions: 5800 },
|
||||
{ date: "2024-04", users: 3100, sessions: 7200 },
|
||||
{ date: "2024-05", users: 3800, sessions: 8900 }
|
||||
]
|
||||
|
||||
return (
|
||||
|
||||
)
|
||||
}
|
||||
```
|
||||
|
||||
### Pie Chart Component
|
||||
Donut chart component for displaying proportional data and percentage distributions.
|
||||
|
||||
```tsx
|
||||
import { PieChart } from "@/components/ui/pie-chart"
|
||||
|
||||
export default function MarketShareChart() {
|
||||
const data = [
|
||||
{ name: "Product A", value: 400, fill: "#3b82f6" },
|
||||
{ name: "Product B", value: 300, fill: "#10b981" },
|
||||
{ name: "Product C", value: 300, fill: "#f59e0b" },
|
||||
{ name: "Product D", value: 200, fill: "#ef4444" }
|
||||
]
|
||||
|
||||
return (
|
||||
`${entry.name}: ${entry.value}`}
|
||||
/>
|
||||
)
|
||||
}
|
||||
```
|
||||
|
||||
### Area Chart Component
|
||||
Stacked area chart for visualizing volume changes over time with multiple data series.
|
||||
|
||||
```tsx
|
||||
import { AreaChart } from "@/components/ui/area-chart"
|
||||
|
||||
export default function TrafficChart() {
|
||||
const data = [
|
||||
{ month: "Jan", mobile: 2000, desktop: 3000, tablet: 1000 },
|
||||
{ month: "Feb", mobile: 2200, desktop: 3200, tablet: 1100 },
|
||||
{ month: "Mar", mobile: 2800, desktop: 3800, tablet: 1300 },
|
||||
{ month: "Apr", mobile: 3200, desktop: 4200, tablet: 1500 },
|
||||
{ month: "May", mobile: 3800, desktop: 4800, tablet: 1800 }
|
||||
]
|
||||
|
||||
return (
|
||||
|
||||
)
|
||||
}
|
||||
```
|
||||
|
||||
### Radar Chart Component
|
||||
Multi-axis chart for comparing multiple variables across different categories simultaneously.
|
||||
|
||||
```tsx
|
||||
import { RadarChart } from "@/components/ui/radar-chart"
|
||||
|
||||
export default function SkillsChart() {
|
||||
const data = [
|
||||
{ skill: "JavaScript", score: 85, industry: 75 },
|
||||
{ skill: "TypeScript", score: 80, industry: 70 },
|
||||
{ skill: "React", score: 90, industry: 80 },
|
||||
{ skill: "Node.js", score: 75, industry: 72 },
|
||||
{ skill: "CSS", score: 88, industry: 78 }
|
||||
]
|
||||
|
||||
return (
|
||||
|
||||
)
|
||||
}
|
||||
```
|
||||
|
||||
### Mixed Chart Component
|
||||
Combined bar and line chart for displaying multiple data types with different visualization methods.
|
||||
|
||||
```tsx
|
||||
import { MixedChart } from "@/components/ui/mixed-chart"
|
||||
|
||||
export default function PerformanceChart() {
|
||||
const data = [
|
||||
{ month: "Jan", revenue: 4000, growth: 5.2 },
|
||||
{ month: "Feb", revenue: 4200, growth: 5.0 },
|
||||
{ month: "Mar", revenue: 4800, growth: 14.3 },
|
||||
{ month: "Apr", revenue: 5200, growth: 8.3 },
|
||||
{ month: "May", revenue: 5800, growth: 11.5 }
|
||||
]
|
||||
|
||||
return (
|
||||
|
||||
)
|
||||
}
|
||||
```
|
||||
|
||||
## Animation Components
|
||||
|
||||
### Magnetic Effect Component
|
||||
Magnetic hover effect that smoothly follows cursor movement for interactive buttons and cards.
|
||||
|
||||
```tsx
|
||||
import { Magnetic } from "@/components/ui/magnetic"
|
||||
|
||||
export default function InteractiveButton() {
|
||||
return (
|
||||
|
||||
Hover me
|
||||
|
||||
)
|
||||
}
|
||||
```
|
||||
|
||||
### Animated Cursor Component
|
||||
Custom animated cursor with interactive effects and particle trails for immersive experiences.
|
||||
|
||||
```tsx
|
||||
import { AnimatedCursor } from "@/components/ui/animated-cursor"
|
||||
|
||||
export default function Layout({ children }) {
|
||||
return (
|
||||
<>
|
||||
|
||||
{children}
|
||||
|
||||
)
|
||||
}
|
||||
```
|
||||
|
||||
### Apple Hello Effect Component
|
||||
Recreation of Apple's iconic "hello" animation with multi-language text transitions.
|
||||
|
||||
```tsx
|
||||
import { AppleHello } from "@/components/ui/apple-hello"
|
||||
|
||||
export default function WelcomeScreen() {
|
||||
const greetings = [
|
||||
{ text: "Hello", lang: "en" },
|
||||
{ text: "Bonjour", lang: "fr" },
|
||||
{ text: "こんにちは", lang: "ja" },
|
||||
{ text: "Hola", lang: "es" },
|
||||
{ text: "你好", lang: "zh" }
|
||||
]
|
||||
|
||||
return (
|
||||
|
||||
)
|
||||
}
|
||||
```
|
||||
|
||||
### Liquid Button Component
|
||||
Button with fluid liquid animation effect on hover for engaging call-to-action elements.
|
||||
|
||||
```tsx
|
||||
import { LiquidButton } from "@/components/ui/liquid-button"
|
||||
|
||||
export default function CTASection() {
|
||||
return (
|
||||
console.log("CTA clicked")}
|
||||
>
|
||||
Get Started
|
||||
|
||||
)
|
||||
}
|
||||
```
|
||||
|
||||
### Rolling Text Component
|
||||
Text animation that creates a rolling effect with smooth character transitions.
|
||||
|
||||
```tsx
|
||||
import { RollingText } from "@/components/ui/rolling-text"
|
||||
|
||||
export default function AnimatedHeading() {
|
||||
return (
|
||||
|
||||
)
|
||||
}
|
||||
```
|
||||
|
||||
### Shimmering Text Component
|
||||
Text with animated shimmer effect for attention-grabbing headings and highlights.
|
||||
|
||||
```tsx
|
||||
import { ShimmeringText } from "@/components/ui/shimmering-text"
|
||||
|
||||
export default function Hero() {
|
||||
return (
|
||||
|
||||
)
|
||||
}
|
||||
```
|
||||
|
||||
## React Hooks
|
||||
|
||||
### useBoolean Hook
|
||||
Enhanced boolean state management with toggle, enable, and disable methods for cleaner component logic.
|
||||
|
||||
```tsx
|
||||
import { useBoolean } from "@/hooks/use-boolean"
|
||||
|
||||
export default function TogglePanel() {
|
||||
const modal = useBoolean(false)
|
||||
const loading = useBoolean(false)
|
||||
|
||||
const handleSubmit = async () => {
|
||||
loading.setTrue()
|
||||
try {
|
||||
await submitForm()
|
||||
modal.setFalse()
|
||||
} finally {
|
||||
loading.setFalse()
|
||||
}
|
||||
}
|
||||
|
||||
return (
|
||||
<>
|
||||
Toggle Modal
|
||||
{modal.value && (
|
||||
|
||||
|
||||
Status: {loading.value ? "Saving..." : "Ready"}
|
||||
|
||||
Submit
|
||||
|
||||
|
||||
)}
|
||||
|
||||
)
|
||||
}
|
||||
```
|
||||
|
||||
### useCounter Hook
|
||||
Counter hook with increment, decrement, reset, and set functionality for numeric state management.
|
||||
|
||||
```tsx
|
||||
import { useCounter } from "@/hooks/use-counter"
|
||||
|
||||
export default function CartCounter() {
|
||||
const quantity = useCounter(0, { min: 0, max: 99 })
|
||||
|
||||
return (
|
||||
|
||||
|
||||
-
|
||||
{quantity.value}
|
||||
+
|
||||
|
||||
Reset
|
||||
|
||||
|
||||
)
|
||||
}
|
||||
```
|
||||
|
||||
### useLocalStorage Hook
|
||||
Persist state in browser localStorage with automatic serialization and deserialization.
|
||||
|
||||
```tsx
|
||||
import { useLocalStorage } from "@/hooks/use-local-storage"
|
||||
|
||||
export default function UserPreferences() {
|
||||
const [theme, setTheme] = useLocalStorage("theme", "light")
|
||||
const [settings, setSettings] = useLocalStorage("settings", {
|
||||
notifications: true,
|
||||
emailUpdates: false
|
||||
})
|
||||
|
||||
return (
|
||||
|
||||
|
||||
setTheme(e.target.value)}>
|
||||
LightDark setSettings({
|
||||
...settings,
|
||||
notifications: e.target.checked
|
||||
})}
|
||||
/>
|
||||
Enable Notifications
|
||||
|
||||
|
||||
)
|
||||
}
|
||||
```
|
||||
|
||||
### useDebounceValue Hook
|
||||
Debounce values to prevent excessive updates and API calls during rapid user input.
|
||||
|
||||
```tsx
|
||||
import { useDebounceValue } from "@/hooks/use-debounce-value"
|
||||
import { useState, useEffect } from "react"
|
||||
|
||||
export default function SearchBox() {
|
||||
const [search, setSearch] = useState("")
|
||||
const debouncedSearch = useDebounceValue(search, 500)
|
||||
const [results, setResults] = useState([])
|
||||
const [apiCalls, setApiCalls] = useState(0)
|
||||
|
||||
useEffect(() => {
|
||||
if (debouncedSearch) {
|
||||
setApiCalls(prev => prev + 1)
|
||||
fetch(`/api/search?q=${debouncedSearch}`)
|
||||
.then(res => res.json())
|
||||
.then(setResults)
|
||||
}
|
||||
}, [debouncedSearch])
|
||||
|
||||
return (
|
||||
|
||||
|
||||
setSearch(e.target.value)}
|
||||
placeholder="Search..."
|
||||
/>
|
||||
|
||||
|
||||
API calls: {apiCalls}
|
||||
|
||||
|
||||
)
|
||||
}
|
||||
```
|
||||
|
||||
### useHover Hook
|
||||
Track hover state on elements with customizable enter and leave delays for tooltip and preview functionality.
|
||||
|
||||
```tsx
|
||||
import { useHover } from "@/hooks/use-hover"
|
||||
import { useRef } from "react"
|
||||
|
||||
export default function ImagePreview() {
|
||||
const hoverRef = useRef(null)
|
||||
const isHovering = useHover(hoverRef, {
|
||||
enterDelay: 200,
|
||||
leaveDelay: 100
|
||||
})
|
||||
|
||||
return (
|
||||
|
||||
|
||||

|
||||
{isHovering && (
|
||||
|
||||
|
||||

|
||||
|
||||
)}
|
||||
|
||||
|
||||
)
|
||||
}
|
||||
```
|
||||
|
||||
### useCountdown Hook
|
||||
Countdown timer with play, pause, reset controls and completion callbacks for time-limited features.
|
||||
|
||||
```tsx
|
||||
import { useCountdown } from "@/hooks/use-countdown"
|
||||
|
||||
export default function OTPTimer() {
|
||||
const countdown = useCountdown({
|
||||
initialSeconds: 60,
|
||||
onComplete: () => alert("OTP expired! Request a new code.")
|
||||
})
|
||||
|
||||
return (
|
||||
|
||||
|
||||
{countdown.seconds}s
|
||||
|
||||
{!countdown.isRunning ? (
|
||||
Start
|
||||
) : (
|
||||
Pause
|
||||
)}
|
||||
Reset
|
||||
|
||||
Status: {countdown.isComplete ? "Expired" : countdown.isRunning ? "Active" : "Paused"}
|
||||
|
||||
|
||||
)
|
||||
}
|
||||
```
|
||||
|
||||
## Installation and Usage
|
||||
|
||||
### CLI Installation
|
||||
Install components directly into your project using the shadcn CLI for instant integration.
|
||||
|
||||
```bash
|
||||
# Initialize shadcn in your project
|
||||
npx shadcn@latest init
|
||||
|
||||
# Add individual components
|
||||
npx shadcn@latest add terminal
|
||||
npx shadcn@latest add dock
|
||||
npx shadcn@latest add credit-card
|
||||
|
||||
# Add multiple components at once
|
||||
npx shadcn@latest add bar-chart line-chart pie-chart
|
||||
|
||||
# Add hooks
|
||||
npx shadcn@latest add use-boolean use-counter use-local-storage
|
||||
```
|
||||
|
||||
### Project Configuration
|
||||
Configure your project to work with shadcn.io components using TypeScript and Tailwind CSS.
|
||||
|
||||
```typescript
|
||||
// tailwind.config.ts
|
||||
import type { Config } from "tailwindcss"
|
||||
|
||||
const config: Config = {
|
||||
darkMode: ["class"],
|
||||
content: [
|
||||
"./pages/**/*.{ts,tsx}",
|
||||
"./components/**/*.{ts,tsx}",
|
||||
"./app/**/*.{ts,tsx}",
|
||||
],
|
||||
theme: {
|
||||
extend: {
|
||||
colors: {
|
||||
border: "hsl(var(--border))",
|
||||
input: "hsl(var(--input))",
|
||||
ring: "hsl(var(--ring))",
|
||||
background: "hsl(var(--background))",
|
||||
foreground: "hsl(var(--foreground))",
|
||||
primary: {
|
||||
DEFAULT: "hsl(var(--primary))",
|
||||
foreground: "hsl(var(--primary-foreground))",
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
plugins: [require("tailwindcss-animate")],
|
||||
}
|
||||
|
||||
export default config
|
||||
```
|
||||
|
||||
## Summary
|
||||
|
||||
The shadcn.io component library serves as a comprehensive toolkit for React developers building modern web applications with Next.js and TypeScript. The library's primary use cases include rapid prototyping of user interfaces, building data-rich dashboards with interactive charts, creating engaging user experiences with animations and effects, and implementing common UI patterns without writing boilerplate code. The copy-paste approach gives developers complete ownership of their components, allowing for deep customization while maintaining consistency with shadcn/ui design principles. Components are particularly well-suited for SaaS applications, admin panels, marketing websites, and e-commerce platforms that require professional, accessible UI elements.
|
||||
|
||||
Integration patterns center around composability and customization rather than rigid package dependencies. Developers can cherry-pick individual components using the CLI, modify them at the source level to match their design system, and combine them with existing shadcn/ui components for a cohesive interface. The library supports both light and dark themes through CSS variables, integrates seamlessly with Tailwind CSS utility classes, and follows React best practices for performance and accessibility. Custom hooks provide reusable logic patterns that complement the visual components, creating a complete ecosystem for building feature-rich applications. The TypeScript-first approach ensures type safety throughout the development process, while the Recharts integration for data visualization provides powerful charting capabilities without additional configuration overhead.
|
||||
File diff suppressed because it is too large
Load diff
1
.augment/skills/shadcn-ui
Symbolic link
1
.augment/skills/shadcn-ui
Symbolic link
|
|
@ -0,0 +1 @@
|
|||
/mnt/c/Users/Zenchant/codex/beadboard/.agents/skills/shadcn-ui/
|
||||
File diff suppressed because it is too large
Load diff
|
|
@ -1,306 +0,0 @@
|
|||
### shadcn/ui Chart Component - Installation
|
||||
|
||||
Source: https://ui.shadcn.com/docs/components/chart
|
||||
|
||||
The chart component in shadcn/ui is built on Recharts, providing direct access to all Recharts capabilities with consistent theming.
|
||||
|
||||
```bash
|
||||
npx shadcn@latest add chart
|
||||
```
|
||||
|
||||
--------------------------------
|
||||
|
||||
### shadcn/ui Chart Component - Basic Usage
|
||||
|
||||
Source: https://ui.shadcn.com/docs/components/chart
|
||||
|
||||
The ChartContainer wraps your Recharts component and accepts a config prop for theming. Requires `min-h-[value]` for responsiveness.
|
||||
|
||||
```tsx
|
||||
import { Bar, BarChart, CartesianGrid, XAxis, YAxis } from "recharts"
|
||||
import { ChartContainer, ChartTooltipContent } from "@/components/ui/chart"
|
||||
|
||||
const chartConfig = {
|
||||
desktop: {
|
||||
label: "Desktop",
|
||||
color: "var(--chart-1)",
|
||||
},
|
||||
mobile: {
|
||||
label: "Mobile",
|
||||
color: "var(--chart-2)",
|
||||
},
|
||||
} satisfies import("@/components/ui/chart").ChartConfig
|
||||
|
||||
const chartData = [
|
||||
{ month: "January", desktop: 186, mobile: 80 },
|
||||
{ month: "February", desktop: 305, mobile: 200 },
|
||||
{ month: "March", desktop: 237, mobile: 120 },
|
||||
]
|
||||
|
||||
export function BarChartDemo() {
|
||||
return (
|
||||
<ChartContainer config={chartConfig} className="min-h-[200px] w-full">
|
||||
<BarChart data={chartData}>
|
||||
<CartesianGrid vertical={false} />
|
||||
<XAxis dataKey="month" tickLine={false} axisLine={false} />
|
||||
<Bar dataKey="desktop" fill="var(--color-desktop)" radius={4} />
|
||||
<Bar dataKey="mobile" fill="var(--color-mobile)" radius={4} />
|
||||
<ChartTooltip content={<ChartTooltipContent />} />
|
||||
</BarChart>
|
||||
</ChartContainer>
|
||||
)
|
||||
}
|
||||
```
|
||||
|
||||
--------------------------------
|
||||
|
||||
### shadcn/ui Chart Component - ChartConfig with Custom Colors
|
||||
|
||||
Source: https://ui.shadcn.com/docs/components/chart
|
||||
|
||||
You can define custom colors directly in the configuration using hex values or CSS variables.
|
||||
|
||||
```tsx
|
||||
const chartConfig = {
|
||||
desktop: {
|
||||
label: "Desktop",
|
||||
color: "#2563eb",
|
||||
theme: {
|
||||
light: "#2563eb",
|
||||
dark: "#60a5fa",
|
||||
},
|
||||
},
|
||||
mobile: {
|
||||
label: "Mobile",
|
||||
color: "var(--chart-2)",
|
||||
},
|
||||
} satisfies import("@/components/ui/chart").ChartConfig
|
||||
```
|
||||
|
||||
--------------------------------
|
||||
|
||||
### shadcn/ui Chart Component - CSS Variables
|
||||
|
||||
Source: https://ui.shadcn.com/docs/components/chart
|
||||
|
||||
Add chart color variables to your globals.css for consistent theming.
|
||||
|
||||
```css
|
||||
:root {
|
||||
/* Chart colors */
|
||||
--chart-1: oklch(0.646 0.222 41.116);
|
||||
--chart-2: oklch(0.6 0.118 184.704);
|
||||
--chart-3: oklch(0.546 0.198 38.228);
|
||||
--chart-4: oklch(0.596 0.151 343.253);
|
||||
--chart-5: oklch(0.546 0.158 49.157);
|
||||
}
|
||||
|
||||
.dark {
|
||||
--chart-1: oklch(0.488 0.243 264.376);
|
||||
--chart-2: oklch(0.696 0.17 162.48);
|
||||
--chart-3: oklch(0.698 0.141 24.311);
|
||||
--chart-4: oklch(0.676 0.172 171.196);
|
||||
--chart-5: oklch(0.578 0.192 302.85);
|
||||
}
|
||||
```
|
||||
|
||||
--------------------------------
|
||||
|
||||
### shadcn/ui Chart Component - Line Chart Example
|
||||
|
||||
Source: https://ui.shadcn.com/docs/components/chart
|
||||
|
||||
Creating a line chart with shadcn/ui charts component.
|
||||
|
||||
```tsx
|
||||
import { Line, LineChart, CartesianGrid, XAxis, YAxis } from "recharts"
|
||||
import { ChartContainer, ChartTooltipContent } from "@/components/ui/chart"
|
||||
|
||||
const chartConfig = {
|
||||
price: {
|
||||
label: "Price",
|
||||
color: "var(--chart-1)",
|
||||
},
|
||||
} satisfies import("@/components/ui/chart").ChartConfig
|
||||
|
||||
const chartData = [
|
||||
{ month: "January", price: 186 },
|
||||
{ month: "February", price: 305 },
|
||||
{ month: "March", price: 237 },
|
||||
{ month: "April", price: 203 },
|
||||
{ month: "May", price: 276 },
|
||||
]
|
||||
|
||||
export function LineChartDemo() {
|
||||
return (
|
||||
<ChartContainer config={chartConfig} className="min-h-[200px]">
|
||||
<LineChart data={chartData}>
|
||||
<CartesianGrid vertical={false} />
|
||||
<XAxis dataKey="month" tickLine={false} axisLine={false} />
|
||||
<YAxis tickLine={false} axisLine={false} tickFormatter={(value) => `$${value}`} />
|
||||
<Line
|
||||
dataKey="price"
|
||||
stroke="var(--color-price)"
|
||||
strokeWidth={2}
|
||||
dot={false}
|
||||
/>
|
||||
<ChartTooltip content={<ChartTooltipContent />} />
|
||||
</LineChart>
|
||||
</ChartContainer>
|
||||
)
|
||||
}
|
||||
```
|
||||
|
||||
--------------------------------
|
||||
|
||||
### shadcn/ui Chart Component - Area Chart Example
|
||||
|
||||
Source: https://ui.shadcn.com/docs/components/chart
|
||||
|
||||
Creating an area chart with gradient fill and legend.
|
||||
|
||||
```tsx
|
||||
import { Area, AreaChart, XAxis, YAxis } from "recharts"
|
||||
import {
|
||||
ChartContainer,
|
||||
ChartLegend,
|
||||
ChartLegendContent,
|
||||
ChartTooltipContent,
|
||||
} from "@/components/ui/chart"
|
||||
|
||||
const chartConfig = {
|
||||
desktop: { label: "Desktop", color: "var(--chart-1)" },
|
||||
mobile: { label: "Mobile", color: "var(--chart-2)" },
|
||||
} satisfies import("@/components/ui/chart").ChartConfig
|
||||
|
||||
export function AreaChartDemo() {
|
||||
return (
|
||||
<ChartContainer config={chartConfig} className="min-h-[200px]">
|
||||
<AreaChart data={chartData}>
|
||||
<XAxis dataKey="month" tickLine={false} axisLine={false} />
|
||||
<YAxis tickLine={false} axisLine={false} />
|
||||
<Area
|
||||
dataKey="desktop"
|
||||
fill="var(--color-desktop)"
|
||||
stroke="var(--color-desktop)"
|
||||
fillOpacity={0.3}
|
||||
/>
|
||||
<Area
|
||||
dataKey="mobile"
|
||||
fill="var(--color-mobile)"
|
||||
stroke="var(--color-mobile)"
|
||||
fillOpacity={0.3}
|
||||
/>
|
||||
<ChartTooltip content={<ChartTooltipContent />} />
|
||||
<ChartLegend content={<ChartLegendContent />} />
|
||||
</AreaChart>
|
||||
</ChartContainer>
|
||||
)
|
||||
}
|
||||
```
|
||||
|
||||
--------------------------------
|
||||
|
||||
### shadcn/ui Chart Component - Pie Chart Example
|
||||
|
||||
Source: https://ui.shadcn.com/docs/components/chart
|
||||
|
||||
Creating a pie/donut chart with shadcn/ui.
|
||||
|
||||
```tsx
|
||||
import { Pie, PieChart } from "recharts"
|
||||
import {
|
||||
ChartContainer,
|
||||
ChartLegend,
|
||||
ChartLegendContent,
|
||||
ChartTooltipContent,
|
||||
} from "@/components/ui/chart"
|
||||
|
||||
const chartConfig = {
|
||||
chrome: { label: "Chrome", color: "var(--chart-1)" },
|
||||
safari: { label: "Safari", color: "var(--chart-2)" },
|
||||
firefox: { label: "Firefox", color: "var(--chart-3)" },
|
||||
} satisfies import("@/components/ui/chart").ChartConfig
|
||||
|
||||
const pieData = [
|
||||
{ browser: "Chrome", visitors: 275, fill: "var(--color-chrome)" },
|
||||
{ browser: "Safari", visitors: 200, fill: "var(--color-safari)" },
|
||||
{ browser: "Firefox", visitors: 187, fill: "var(--color-firefox)" },
|
||||
]
|
||||
|
||||
export function PieChartDemo() {
|
||||
return (
|
||||
<ChartContainer config={chartConfig} className="min-h-[200px]">
|
||||
<PieChart>
|
||||
<Pie
|
||||
data={pieData}
|
||||
dataKey="visitors"
|
||||
nameKey="browser"
|
||||
cx="50%"
|
||||
cy="50%"
|
||||
outerRadius={80}
|
||||
/>
|
||||
<ChartTooltip content={<ChartTooltipContent />} />
|
||||
<ChartLegend content={<ChartLegendContent />} />
|
||||
</PieChart>
|
||||
</ChartContainer>
|
||||
)
|
||||
}
|
||||
```
|
||||
|
||||
--------------------------------
|
||||
|
||||
### shadcn/ui ChartTooltipContent Props
|
||||
|
||||
Source: https://ui.shadcn.com/docs/components/chart
|
||||
|
||||
The ChartTooltipContent component accepts these props for customizing tooltip behavior.
|
||||
|
||||
| Prop | Type | Default | Description |
|
||||
|------|------|---------|-------------|
|
||||
| `labelKey` | string | "label" | Key for tooltip label |
|
||||
| `nameKey` | string | "name" | Key for tooltip name |
|
||||
| `indicator` | "dot" \| "line" \| "dashed" | "dot" | Indicator style |
|
||||
| `hideLabel` | boolean | false | Hide label |
|
||||
| `hideIndicator` | boolean | false | Hide indicator |
|
||||
|
||||
--------------------------------
|
||||
|
||||
### shadcn/ui Chart Component - Accessibility
|
||||
|
||||
Source: https://ui.shadcn.com/docs/components/chart
|
||||
|
||||
Enable keyboard navigation and screen reader support by adding the accessibilityLayer prop.
|
||||
|
||||
```tsx
|
||||
<BarChart accessibilityLayer data={chartData}>
|
||||
<CartesianGrid vertical={false} />
|
||||
<XAxis dataKey="month" />
|
||||
<Bar dataKey="desktop" fill="var(--color-desktop)" />
|
||||
<ChartTooltip content={<ChartTooltipContent />} />
|
||||
</BarChart>
|
||||
```
|
||||
|
||||
This adds:
|
||||
- Keyboard arrow key navigation
|
||||
- ARIA labels for chart elements
|
||||
- Screen reader announcements for data values
|
||||
|
||||
--------------------------------
|
||||
|
||||
### shadcn/ui Chart Component - Recharts Dependencies
|
||||
|
||||
Source: https://ui.shadcn.com/docs/components/chart
|
||||
|
||||
The chart component requires the following Recharts dependencies to be installed.
|
||||
|
||||
```bash
|
||||
pnpm add recharts
|
||||
npm install recharts
|
||||
yarn add recharts
|
||||
```
|
||||
|
||||
Recharts provides the following chart types:
|
||||
- Area, Bar, Line, Pie, Composed
|
||||
- Radar, RadialBar, Scatter
|
||||
- Funnel, Treemap
|
||||
|
|
@ -1,145 +0,0 @@
|
|||
# shadcn/ui Learning Guide
|
||||
|
||||
This guide helps you learn shadcn/ui from basics to advanced patterns.
|
||||
|
||||
## Learning Path
|
||||
|
||||
### 1. Understanding the Philosophy
|
||||
|
||||
shadcn/ui is different from traditional component libraries:
|
||||
|
||||
- **Copy-paste components**: Components are copied into your project, not installed as packages
|
||||
- **Full customization**: You own the code and can modify it freely
|
||||
- **Built on Radix UI**: Provides accessibility primitives
|
||||
- **Styled with Tailwind**: Uses utility classes for consistent styling
|
||||
|
||||
### 2. Core Concepts to Master
|
||||
|
||||
#### Class Variance Authority (CVA)
|
||||
Most components use CVA for variant management:
|
||||
|
||||
```tsx
|
||||
const buttonVariants = cva(
|
||||
"base-classes",
|
||||
{
|
||||
variants: {
|
||||
variant: {
|
||||
default: "variant-classes",
|
||||
destructive: "destructive-classes",
|
||||
},
|
||||
size: {
|
||||
default: "size-classes",
|
||||
sm: "small-classes",
|
||||
},
|
||||
},
|
||||
defaultVariants: {
|
||||
variant: "default",
|
||||
size: "default",
|
||||
},
|
||||
}
|
||||
)
|
||||
```
|
||||
|
||||
#### cn Utility Function
|
||||
The `cn` function combines classes and resolves conflicts:
|
||||
|
||||
```tsx
|
||||
import { clsx, type ClassValue } from "clsx"
|
||||
import { twMerge } from "tailwind-merge"
|
||||
|
||||
export function cn(...inputs: ClassValue[]) {
|
||||
return twMerge(clsx(inputs))
|
||||
}
|
||||
```
|
||||
|
||||
### 3. Installation Checklist
|
||||
|
||||
- [ ] Initialize a new project (Next.js, Vite, or Remix)
|
||||
- [ ] Install Tailwind CSS
|
||||
- [ ] Run `npx shadcn@latest init`
|
||||
- [ ] Configure CSS variables
|
||||
- [ ] Install first component: `npx shadcn@latest add button`
|
||||
|
||||
### 4. Essential Components to Learn First
|
||||
|
||||
1. **Button** - Learn variants and sizes
|
||||
2. **Input** - Form inputs with labels
|
||||
3. **Card** - Container components
|
||||
4. **Form** - Form handling with React Hook Form
|
||||
5. **Dialog** - Modal windows
|
||||
6. **Select** - Dropdown selections
|
||||
7. **Toast** - Notifications
|
||||
|
||||
### 5. Common Patterns
|
||||
|
||||
#### Form Pattern
|
||||
Every form follows this structure:
|
||||
|
||||
```tsx
|
||||
1. Define Zod schema
|
||||
2. Create form with useForm
|
||||
3. Wrap with Form component
|
||||
4. Add FormField for each input
|
||||
5. Handle submission
|
||||
```
|
||||
|
||||
#### Component Customization Pattern
|
||||
To customize a component:
|
||||
|
||||
1. Copy component to your project
|
||||
2. Modify the variants
|
||||
3. Add new props if needed
|
||||
4. Update types
|
||||
|
||||
### 6. Best Practices
|
||||
|
||||
- Always use TypeScript
|
||||
- Follow the existing component structure
|
||||
- Use semantic HTML when possible
|
||||
- Test with screen readers for accessibility
|
||||
- Keep components small and focused
|
||||
|
||||
### 7. Advanced Topics
|
||||
|
||||
- Creating custom components from scratch
|
||||
- Building complex forms with validation
|
||||
- Implementing dark mode
|
||||
- Optimizing for performance
|
||||
- Testing components
|
||||
|
||||
## Practice Exercises
|
||||
|
||||
### Exercise 1: Basic Setup
|
||||
1. Create a new Next.js project
|
||||
2. Set up shadcn/ui
|
||||
3. Install and customize a Button component
|
||||
4. Add a new variant "gradient"
|
||||
|
||||
### Exercise 2: Form Building
|
||||
1. Create a contact form with:
|
||||
- Name input (required)
|
||||
- Email input (email validation)
|
||||
- Message textarea (min length)
|
||||
- Submit button with loading state
|
||||
|
||||
### Exercise 3: Component Combination
|
||||
1. Build a settings page using:
|
||||
- Card for layout
|
||||
- Sheet for mobile menu
|
||||
- Select for dropdowns
|
||||
- Switch for toggles
|
||||
- Toast for notifications
|
||||
|
||||
### Exercise 4: Custom Component
|
||||
1. Create a custom Badge component
|
||||
2. Support variants: default, secondary, destructive, outline
|
||||
3. Support sizes: sm, default, lg
|
||||
4. Add icon support
|
||||
|
||||
## Resources
|
||||
|
||||
- [Official Documentation](https://ui.shadcn.com)
|
||||
- [GitHub Repository](https://github.com/shadcn/ui)
|
||||
- [Examples Gallery](https://ui.shadcn.com/examples)
|
||||
- [Radix UI Primitives](https://www.radix-ui.com/primitives)
|
||||
- [Tailwind CSS Documentation](https://tailwindcss.com/docs)
|
||||
File diff suppressed because it is too large
Load diff
|
|
@ -1,586 +0,0 @@
|
|||
# shadcn.io Component Library
|
||||
|
||||
shadcn.io is a comprehensive React UI component library built on shadcn/ui principles, providing developers with production-ready, composable components for modern web applications. The library serves as a centralized resource for React developers who need high-quality UI components with TypeScript support, ranging from basic interactive elements to advanced AI-powered integrations. Unlike traditional component libraries that require package installations, shadcn.io components are designed to be copied directly into your project, giving you full control and customization capabilities.
|
||||
|
||||
The library encompasses four major categories: composable UI components (terminal, dock, credit cards, QR codes, color pickers), chart components built with Recharts, animation components with Tailwind CSS integration, and custom React hooks for state management and lifecycle operations. Each component follows best practices for accessibility, performance, and developer experience, with comprehensive TypeScript definitions and Next.js compatibility. The platform emphasizes flexibility and customization, allowing developers to modify components at the source level rather than being constrained by package APIs.
|
||||
|
||||
## Core Components
|
||||
|
||||
### Terminal Component
|
||||
Interactive terminal emulator with typing animations and command execution simulation for developer-focused interfaces.
|
||||
|
||||
```tsx
|
||||
import { Terminal } from "@/components/ui/terminal"
|
||||
|
||||
export default function DemoTerminal() {
|
||||
return (
|
||||
npm install @repo/terminalInstalling dependencies...npm start
|
||||
)
|
||||
}
|
||||
```
|
||||
|
||||
### Dock Component
|
||||
macOS-style application dock with smooth magnification effects on hover, perfect for navigation menus.
|
||||
|
||||
```tsx
|
||||
import { Dock, DockIcon } from "@/components/ui/dock"
|
||||
import { Home, Settings, User, Mail } from "lucide-react"
|
||||
|
||||
export default function AppDock() {
|
||||
return (
|
||||
|
||||
)
|
||||
}
|
||||
```
|
||||
|
||||
### Credit Card Component
|
||||
Interactive 3D credit card component with flip animations for payment forms and card displays.
|
||||
|
||||
```tsx
|
||||
import { CreditCard } from "@/components/ui/credit-card"
|
||||
import { useState } from "react"
|
||||
|
||||
export default function PaymentForm() {
|
||||
const [cardData, setCardData] = useState({
|
||||
number: "4532 1234 5678 9010",
|
||||
holder: "JOHN DOE",
|
||||
expiry: "12/28",
|
||||
cvv: "123"
|
||||
})
|
||||
|
||||
return (
|
||||
console.log("Card flipped:", flipped)}
|
||||
/>
|
||||
)
|
||||
}
|
||||
```
|
||||
|
||||
### Image Zoom Component
|
||||
Zoomable image component with smooth modal transitions for image galleries and product displays.
|
||||
|
||||
```tsx
|
||||
import { ImageZoom } from "@/components/ui/image-zoom"
|
||||
|
||||
export default function ProductGallery() {
|
||||
return (
|
||||
|
||||
|
||||
)
|
||||
}
|
||||
```
|
||||
|
||||
### QR Code Component
|
||||
Generate and display customizable QR codes with styling options for links, contact information, and authentication.
|
||||
|
||||
```tsx
|
||||
import { QRCode } from "@/components/ui/qr-code"
|
||||
|
||||
export default function ShareDialog() {
|
||||
const shareUrl = "https://shadcn.io"
|
||||
|
||||
return (
|
||||
|
||||
|
||||
Scan to visit shadcn.io
|
||||
|
||||
|
||||
)
|
||||
}
|
||||
```
|
||||
|
||||
### Color Picker Component
|
||||
Advanced color selection component supporting multiple color formats (HEX, RGB, HSL) with preview.
|
||||
|
||||
```tsx
|
||||
import { ColorPicker } from "@/components/ui/color-picker"
|
||||
import { useState } from "react"
|
||||
|
||||
export default function ThemeCustomizer() {
|
||||
const [color, setColor] = useState("#3b82f6")
|
||||
|
||||
return (
|
||||
|
||||
|
||||
Selected: {color}
|
||||
|
||||
)
|
||||
}
|
||||
```
|
||||
|
||||
## Chart Components
|
||||
|
||||
### Bar Chart Component
|
||||
Clean bar chart component for data comparison and categorical analysis using Recharts.
|
||||
|
||||
```tsx
|
||||
import { BarChart } from "@/components/ui/bar-chart"
|
||||
|
||||
export default function SalesChart() {
|
||||
const data = [
|
||||
{ month: "Jan", sales: 4000, revenue: 2400 },
|
||||
{ month: "Feb", sales: 3000, revenue: 1398 },
|
||||
{ month: "Mar", sales: 2000, revenue: 9800 },
|
||||
{ month: "Apr", sales: 2780, revenue: 3908 },
|
||||
{ month: "May", sales: 1890, revenue: 4800 },
|
||||
{ month: "Jun", sales: 2390, revenue: 3800 }
|
||||
]
|
||||
|
||||
return (
|
||||
`$${value.toLocaleString()}`}
|
||||
yAxisWidth={60}
|
||||
/>
|
||||
)
|
||||
}
|
||||
```
|
||||
|
||||
### Line Chart Component
|
||||
Smooth line chart for visualizing trends and time-series data with multiple data series support.
|
||||
|
||||
```tsx
|
||||
import { LineChart } from "@/components/ui/line-chart"
|
||||
|
||||
export default function MetricsChart() {
|
||||
const data = [
|
||||
{ date: "2024-01", users: 1200, sessions: 3400 },
|
||||
{ date: "2024-02", users: 1800, sessions: 4200 },
|
||||
{ date: "2024-03", users: 2400, sessions: 5800 },
|
||||
{ date: "2024-04", users: 3100, sessions: 7200 },
|
||||
{ date: "2024-05", users: 3800, sessions: 8900 }
|
||||
]
|
||||
|
||||
return (
|
||||
|
||||
)
|
||||
}
|
||||
```
|
||||
|
||||
### Pie Chart Component
|
||||
Donut chart component for displaying proportional data and percentage distributions.
|
||||
|
||||
```tsx
|
||||
import { PieChart } from "@/components/ui/pie-chart"
|
||||
|
||||
export default function MarketShareChart() {
|
||||
const data = [
|
||||
{ name: "Product A", value: 400, fill: "#3b82f6" },
|
||||
{ name: "Product B", value: 300, fill: "#10b981" },
|
||||
{ name: "Product C", value: 300, fill: "#f59e0b" },
|
||||
{ name: "Product D", value: 200, fill: "#ef4444" }
|
||||
]
|
||||
|
||||
return (
|
||||
`${entry.name}: ${entry.value}`}
|
||||
/>
|
||||
)
|
||||
}
|
||||
```
|
||||
|
||||
### Area Chart Component
|
||||
Stacked area chart for visualizing volume changes over time with multiple data series.
|
||||
|
||||
```tsx
|
||||
import { AreaChart } from "@/components/ui/area-chart"
|
||||
|
||||
export default function TrafficChart() {
|
||||
const data = [
|
||||
{ month: "Jan", mobile: 2000, desktop: 3000, tablet: 1000 },
|
||||
{ month: "Feb", mobile: 2200, desktop: 3200, tablet: 1100 },
|
||||
{ month: "Mar", mobile: 2800, desktop: 3800, tablet: 1300 },
|
||||
{ month: "Apr", mobile: 3200, desktop: 4200, tablet: 1500 },
|
||||
{ month: "May", mobile: 3800, desktop: 4800, tablet: 1800 }
|
||||
]
|
||||
|
||||
return (
|
||||
|
||||
)
|
||||
}
|
||||
```
|
||||
|
||||
### Radar Chart Component
|
||||
Multi-axis chart for comparing multiple variables across different categories simultaneously.
|
||||
|
||||
```tsx
|
||||
import { RadarChart } from "@/components/ui/radar-chart"
|
||||
|
||||
export default function SkillsChart() {
|
||||
const data = [
|
||||
{ skill: "JavaScript", score: 85, industry: 75 },
|
||||
{ skill: "TypeScript", score: 80, industry: 70 },
|
||||
{ skill: "React", score: 90, industry: 80 },
|
||||
{ skill: "Node.js", score: 75, industry: 72 },
|
||||
{ skill: "CSS", score: 88, industry: 78 }
|
||||
]
|
||||
|
||||
return (
|
||||
|
||||
)
|
||||
}
|
||||
```
|
||||
|
||||
### Mixed Chart Component
|
||||
Combined bar and line chart for displaying multiple data types with different visualization methods.
|
||||
|
||||
```tsx
|
||||
import { MixedChart } from "@/components/ui/mixed-chart"
|
||||
|
||||
export default function PerformanceChart() {
|
||||
const data = [
|
||||
{ month: "Jan", revenue: 4000, growth: 5.2 },
|
||||
{ month: "Feb", revenue: 4200, growth: 5.0 },
|
||||
{ month: "Mar", revenue: 4800, growth: 14.3 },
|
||||
{ month: "Apr", revenue: 5200, growth: 8.3 },
|
||||
{ month: "May", revenue: 5800, growth: 11.5 }
|
||||
]
|
||||
|
||||
return (
|
||||
|
||||
)
|
||||
}
|
||||
```
|
||||
|
||||
## Animation Components
|
||||
|
||||
### Magnetic Effect Component
|
||||
Magnetic hover effect that smoothly follows cursor movement for interactive buttons and cards.
|
||||
|
||||
```tsx
|
||||
import { Magnetic } from "@/components/ui/magnetic"
|
||||
|
||||
export default function InteractiveButton() {
|
||||
return (
|
||||
|
||||
Hover me
|
||||
|
||||
)
|
||||
}
|
||||
```
|
||||
|
||||
### Animated Cursor Component
|
||||
Custom animated cursor with interactive effects and particle trails for immersive experiences.
|
||||
|
||||
```tsx
|
||||
import { AnimatedCursor } from "@/components/ui/animated-cursor"
|
||||
|
||||
export default function Layout({ children }) {
|
||||
return (
|
||||
<>
|
||||
|
||||
{children}
|
||||
|
||||
)
|
||||
}
|
||||
```
|
||||
|
||||
### Apple Hello Effect Component
|
||||
Recreation of Apple's iconic "hello" animation with multi-language text transitions.
|
||||
|
||||
```tsx
|
||||
import { AppleHello } from "@/components/ui/apple-hello"
|
||||
|
||||
export default function WelcomeScreen() {
|
||||
const greetings = [
|
||||
{ text: "Hello", lang: "en" },
|
||||
{ text: "Bonjour", lang: "fr" },
|
||||
{ text: "こんにちは", lang: "ja" },
|
||||
{ text: "Hola", lang: "es" },
|
||||
{ text: "你好", lang: "zh" }
|
||||
]
|
||||
|
||||
return (
|
||||
|
||||
)
|
||||
}
|
||||
```
|
||||
|
||||
### Liquid Button Component
|
||||
Button with fluid liquid animation effect on hover for engaging call-to-action elements.
|
||||
|
||||
```tsx
|
||||
import { LiquidButton } from "@/components/ui/liquid-button"
|
||||
|
||||
export default function CTASection() {
|
||||
return (
|
||||
console.log("CTA clicked")}
|
||||
>
|
||||
Get Started
|
||||
|
||||
)
|
||||
}
|
||||
```
|
||||
|
||||
### Rolling Text Component
|
||||
Text animation that creates a rolling effect with smooth character transitions.
|
||||
|
||||
```tsx
|
||||
import { RollingText } from "@/components/ui/rolling-text"
|
||||
|
||||
export default function AnimatedHeading() {
|
||||
return (
|
||||
|
||||
)
|
||||
}
|
||||
```
|
||||
|
||||
### Shimmering Text Component
|
||||
Text with animated shimmer effect for attention-grabbing headings and highlights.
|
||||
|
||||
```tsx
|
||||
import { ShimmeringText } from "@/components/ui/shimmering-text"
|
||||
|
||||
export default function Hero() {
|
||||
return (
|
||||
|
||||
)
|
||||
}
|
||||
```
|
||||
|
||||
## React Hooks
|
||||
|
||||
### useBoolean Hook
|
||||
Enhanced boolean state management with toggle, enable, and disable methods for cleaner component logic.
|
||||
|
||||
```tsx
|
||||
import { useBoolean } from "@/hooks/use-boolean"
|
||||
|
||||
export default function TogglePanel() {
|
||||
const modal = useBoolean(false)
|
||||
const loading = useBoolean(false)
|
||||
|
||||
const handleSubmit = async () => {
|
||||
loading.setTrue()
|
||||
try {
|
||||
await submitForm()
|
||||
modal.setFalse()
|
||||
} finally {
|
||||
loading.setFalse()
|
||||
}
|
||||
}
|
||||
|
||||
return (
|
||||
<>
|
||||
Toggle Modal
|
||||
{modal.value && (
|
||||
|
||||
|
||||
Status: {loading.value ? "Saving..." : "Ready"}
|
||||
|
||||
Submit
|
||||
|
||||
|
||||
)}
|
||||
|
||||
)
|
||||
}
|
||||
```
|
||||
|
||||
### useCounter Hook
|
||||
Counter hook with increment, decrement, reset, and set functionality for numeric state management.
|
||||
|
||||
```tsx
|
||||
import { useCounter } from "@/hooks/use-counter"
|
||||
|
||||
export default function CartCounter() {
|
||||
const quantity = useCounter(0, { min: 0, max: 99 })
|
||||
|
||||
return (
|
||||
|
||||
|
||||
-
|
||||
{quantity.value}
|
||||
+
|
||||
|
||||
Reset
|
||||
|
||||
|
||||
)
|
||||
}
|
||||
```
|
||||
|
||||
### useLocalStorage Hook
|
||||
Persist state in browser localStorage with automatic serialization and deserialization.
|
||||
|
||||
```tsx
|
||||
import { useLocalStorage } from "@/hooks/use-local-storage"
|
||||
|
||||
export default function UserPreferences() {
|
||||
const [theme, setTheme] = useLocalStorage("theme", "light")
|
||||
const [settings, setSettings] = useLocalStorage("settings", {
|
||||
notifications: true,
|
||||
emailUpdates: false
|
||||
})
|
||||
|
||||
return (
|
||||
|
||||
|
||||
setTheme(e.target.value)}>
|
||||
LightDark setSettings({
|
||||
...settings,
|
||||
notifications: e.target.checked
|
||||
})}
|
||||
/>
|
||||
Enable Notifications
|
||||
|
||||
|
||||
)
|
||||
}
|
||||
```
|
||||
|
||||
### useDebounceValue Hook
|
||||
Debounce values to prevent excessive updates and API calls during rapid user input.
|
||||
|
||||
```tsx
|
||||
import { useDebounceValue } from "@/hooks/use-debounce-value"
|
||||
import { useState, useEffect } from "react"
|
||||
|
||||
export default function SearchBox() {
|
||||
const [search, setSearch] = useState("")
|
||||
const debouncedSearch = useDebounceValue(search, 500)
|
||||
const [results, setResults] = useState([])
|
||||
const [apiCalls, setApiCalls] = useState(0)
|
||||
|
||||
useEffect(() => {
|
||||
if (debouncedSearch) {
|
||||
setApiCalls(prev => prev + 1)
|
||||
fetch(`/api/search?q=${debouncedSearch}`)
|
||||
.then(res => res.json())
|
||||
.then(setResults)
|
||||
}
|
||||
}, [debouncedSearch])
|
||||
|
||||
return (
|
||||
|
||||
|
||||
setSearch(e.target.value)}
|
||||
placeholder="Search..."
|
||||
/>
|
||||
|
||||
|
||||
API calls: {apiCalls}
|
||||
|
||||
|
||||
)
|
||||
}
|
||||
```
|
||||
|
||||
### useHover Hook
|
||||
Track hover state on elements with customizable enter and leave delays for tooltip and preview functionality.
|
||||
|
||||
```tsx
|
||||
import { useHover } from "@/hooks/use-hover"
|
||||
import { useRef } from "react"
|
||||
|
||||
export default function ImagePreview() {
|
||||
const hoverRef = useRef(null)
|
||||
const isHovering = useHover(hoverRef, {
|
||||
enterDelay: 200,
|
||||
leaveDelay: 100
|
||||
})
|
||||
|
||||
return (
|
||||
|
||||
|
||||

|
||||
{isHovering && (
|
||||
|
||||
|
||||

|
||||
|
||||
)}
|
||||
|
||||
|
||||
)
|
||||
}
|
||||
```
|
||||
|
||||
### useCountdown Hook
|
||||
Countdown timer with play, pause, reset controls and completion callbacks for time-limited features.
|
||||
|
||||
```tsx
|
||||
import { useCountdown } from "@/hooks/use-countdown"
|
||||
|
||||
export default function OTPTimer() {
|
||||
const countdown = useCountdown({
|
||||
initialSeconds: 60,
|
||||
onComplete: () => alert("OTP expired! Request a new code.")
|
||||
})
|
||||
|
||||
return (
|
||||
|
||||
|
||||
{countdown.seconds}s
|
||||
|
||||
{!countdown.isRunning ? (
|
||||
Start
|
||||
) : (
|
||||
Pause
|
||||
)}
|
||||
Reset
|
||||
|
||||
Status: {countdown.isComplete ? "Expired" : countdown.isRunning ? "Active" : "Paused"}
|
||||
|
||||
|
||||
)
|
||||
}
|
||||
```
|
||||
|
||||
## Installation and Usage
|
||||
|
||||
### CLI Installation
|
||||
Install components directly into your project using the shadcn CLI for instant integration.
|
||||
|
||||
```bash
|
||||
# Initialize shadcn in your project
|
||||
npx shadcn@latest init
|
||||
|
||||
# Add individual components
|
||||
npx shadcn@latest add terminal
|
||||
npx shadcn@latest add dock
|
||||
npx shadcn@latest add credit-card
|
||||
|
||||
# Add multiple components at once
|
||||
npx shadcn@latest add bar-chart line-chart pie-chart
|
||||
|
||||
# Add hooks
|
||||
npx shadcn@latest add use-boolean use-counter use-local-storage
|
||||
```
|
||||
|
||||
### Project Configuration
|
||||
Configure your project to work with shadcn.io components using TypeScript and Tailwind CSS.
|
||||
|
||||
```typescript
|
||||
// tailwind.config.ts
|
||||
import type { Config } from "tailwindcss"
|
||||
|
||||
const config: Config = {
|
||||
darkMode: ["class"],
|
||||
content: [
|
||||
"./pages/**/*.{ts,tsx}",
|
||||
"./components/**/*.{ts,tsx}",
|
||||
"./app/**/*.{ts,tsx}",
|
||||
],
|
||||
theme: {
|
||||
extend: {
|
||||
colors: {
|
||||
border: "hsl(var(--border))",
|
||||
input: "hsl(var(--input))",
|
||||
ring: "hsl(var(--ring))",
|
||||
background: "hsl(var(--background))",
|
||||
foreground: "hsl(var(--foreground))",
|
||||
primary: {
|
||||
DEFAULT: "hsl(var(--primary))",
|
||||
foreground: "hsl(var(--primary-foreground))",
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
plugins: [require("tailwindcss-animate")],
|
||||
}
|
||||
|
||||
export default config
|
||||
```
|
||||
|
||||
## Summary
|
||||
|
||||
The shadcn.io component library serves as a comprehensive toolkit for React developers building modern web applications with Next.js and TypeScript. The library's primary use cases include rapid prototyping of user interfaces, building data-rich dashboards with interactive charts, creating engaging user experiences with animations and effects, and implementing common UI patterns without writing boilerplate code. The copy-paste approach gives developers complete ownership of their components, allowing for deep customization while maintaining consistency with shadcn/ui design principles. Components are particularly well-suited for SaaS applications, admin panels, marketing websites, and e-commerce platforms that require professional, accessible UI elements.
|
||||
|
||||
Integration patterns center around composability and customization rather than rigid package dependencies. Developers can cherry-pick individual components using the CLI, modify them at the source level to match their design system, and combine them with existing shadcn/ui components for a cohesive interface. The library supports both light and dark themes through CSS variables, integrates seamlessly with Tailwind CSS utility classes, and follows React best practices for performance and accessibility. Custom hooks provide reusable logic patterns that complement the visual components, creating a complete ecosystem for building feature-rich applications. The TypeScript-first approach ensures type safety throughout the development process, while the Recharts integration for data visualization provides powerful charting capabilities without additional configuration overhead.
|
||||
File diff suppressed because it is too large
Load diff
|
|
@ -1,23 +1,23 @@
|
|||
#!/usr/bin/env sh
|
||||
# bd-shim v1
|
||||
# bd-hooks-version: 0.53.0
|
||||
#
|
||||
# bd (beads) post-checkout hook - thin shim
|
||||
#
|
||||
# This shim delegates to 'bd hook post-checkout' which contains
|
||||
# the actual hook logic. This pattern ensures hook behavior is always
|
||||
# in sync with the installed bd version - no manual updates needed.
|
||||
#
|
||||
# The 'bd hook' command (singular) supports:
|
||||
# - Guard against frequent firing (only imports if JSONL changed)
|
||||
# - Per-worktree state tracking
|
||||
# - Dolt branch-then-merge pattern
|
||||
# - Hook chaining configuration
|
||||
|
||||
# Check if bd is available
|
||||
if ! command -v bd >/dev/null 2>&1; then
|
||||
# Silently skip - post-checkout is called frequently
|
||||
exit 0
|
||||
fi
|
||||
|
||||
exec bd hook post-checkout "$@"
|
||||
#!/usr/bin/env sh
|
||||
# bd-shim v1
|
||||
# bd-hooks-version: 0.53.0
|
||||
#
|
||||
# bd (beads) post-checkout hook - thin shim
|
||||
#
|
||||
# This shim delegates to 'bd hook post-checkout' which contains
|
||||
# the actual hook logic. This pattern ensures hook behavior is always
|
||||
# in sync with the installed bd version - no manual updates needed.
|
||||
#
|
||||
# The 'bd hook' command (singular) supports:
|
||||
# - Guard against frequent firing (only imports if JSONL changed)
|
||||
# - Per-worktree state tracking
|
||||
# - Dolt branch-then-merge pattern
|
||||
# - Hook chaining configuration
|
||||
|
||||
# Check if bd is available
|
||||
if ! command -v bd >/dev/null 2>&1; then
|
||||
# Silently skip - post-checkout is called frequently
|
||||
exit 0
|
||||
fi
|
||||
|
||||
exec bd hook post-checkout "$@"
|
||||
|
|
|
|||
|
|
@ -1,24 +1,24 @@
|
|||
#!/usr/bin/env sh
|
||||
# bd-shim v1
|
||||
# bd-hooks-version: 0.53.0
|
||||
#
|
||||
# bd (beads) post-merge hook - thin shim
|
||||
#
|
||||
# This shim delegates to 'bd hook post-merge' which contains
|
||||
# the actual hook logic. This pattern ensures hook behavior is always
|
||||
# in sync with the installed bd version - no manual updates needed.
|
||||
#
|
||||
# The 'bd hook' command (singular) supports:
|
||||
# - Branch-then-merge pattern for Dolt (cell-level conflict resolution)
|
||||
# - Per-worktree state tracking
|
||||
# - Hook chaining configuration
|
||||
|
||||
# Check if bd is available
|
||||
if ! command -v bd >/dev/null 2>&1; then
|
||||
echo "Warning: bd command not found in PATH, skipping post-merge hook" >&2
|
||||
echo " Install bd: brew install beads" >&2
|
||||
echo " Or add bd to your PATH" >&2
|
||||
exit 0
|
||||
fi
|
||||
|
||||
exec bd hook post-merge "$@"
|
||||
#!/usr/bin/env sh
|
||||
# bd-shim v1
|
||||
# bd-hooks-version: 0.53.0
|
||||
#
|
||||
# bd (beads) post-merge hook - thin shim
|
||||
#
|
||||
# This shim delegates to 'bd hook post-merge' which contains
|
||||
# the actual hook logic. This pattern ensures hook behavior is always
|
||||
# in sync with the installed bd version - no manual updates needed.
|
||||
#
|
||||
# The 'bd hook' command (singular) supports:
|
||||
# - Branch-then-merge pattern for Dolt (cell-level conflict resolution)
|
||||
# - Per-worktree state tracking
|
||||
# - Hook chaining configuration
|
||||
|
||||
# Check if bd is available
|
||||
if ! command -v bd >/dev/null 2>&1; then
|
||||
echo "Warning: bd command not found in PATH, skipping post-merge hook" >&2
|
||||
echo " Install bd: brew install beads" >&2
|
||||
echo " Or add bd to your PATH" >&2
|
||||
exit 0
|
||||
fi
|
||||
|
||||
exec bd hook post-merge "$@"
|
||||
|
|
|
|||
|
|
@ -1,25 +1,25 @@
|
|||
#!/usr/bin/env sh
|
||||
# bd-shim v2
|
||||
# bd-hooks-version: 0.53.0
|
||||
#
|
||||
# bd (beads) pre-commit hook — thin shim
|
||||
#
|
||||
# Delegates to 'bd hook pre-commit' which contains the actual hook logic.
|
||||
# This pattern ensures hook behavior is always in sync with the installed
|
||||
# bd version — no manual updates needed.
|
||||
#
|
||||
# The 'bd hook' command supports:
|
||||
# - Per-worktree export state tracking
|
||||
# - Dolt in-process export (no lock deadlocks)
|
||||
# - Sync-branch routing
|
||||
# - Hook chaining configuration
|
||||
|
||||
# Check if bd is available
|
||||
if ! command -v bd >/dev/null 2>&1; then
|
||||
echo "Warning: bd command not found in PATH, skipping pre-commit hook" >&2
|
||||
echo " Install bd: brew install beads" >&2
|
||||
echo " Or add bd to your PATH" >&2
|
||||
exit 0
|
||||
fi
|
||||
|
||||
exec bd hook pre-commit "$@"
|
||||
#!/usr/bin/env sh
|
||||
# bd-shim v2
|
||||
# bd-hooks-version: 0.53.0
|
||||
#
|
||||
# bd (beads) pre-commit hook — thin shim
|
||||
#
|
||||
# Delegates to 'bd hook pre-commit' which contains the actual hook logic.
|
||||
# This pattern ensures hook behavior is always in sync with the installed
|
||||
# bd version — no manual updates needed.
|
||||
#
|
||||
# The 'bd hook' command supports:
|
||||
# - Per-worktree export state tracking
|
||||
# - Dolt in-process export (no lock deadlocks)
|
||||
# - Sync-branch routing
|
||||
# - Hook chaining configuration
|
||||
|
||||
# Check if bd is available
|
||||
if ! command -v bd >/dev/null 2>&1; then
|
||||
echo "Warning: bd command not found in PATH, skipping pre-commit hook" >&2
|
||||
echo " Install bd: brew install beads" >&2
|
||||
echo " Or add bd to your PATH" >&2
|
||||
exit 0
|
||||
fi
|
||||
|
||||
exec bd hook pre-commit "$@"
|
||||
|
|
|
|||
|
|
@ -1,19 +1,19 @@
|
|||
#!/usr/bin/env sh
|
||||
# bd-shim v1
|
||||
# bd-hooks-version: 0.53.0
|
||||
#
|
||||
# bd (beads) pre-push hook - thin shim
|
||||
#
|
||||
# This shim delegates to 'bd hooks run pre-push' which contains
|
||||
# the actual hook logic. This pattern ensures hook behavior is always
|
||||
# in sync with the installed bd version - no manual updates needed.
|
||||
|
||||
# Check if bd is available
|
||||
if ! command -v bd >/dev/null 2>&1; then
|
||||
echo "Warning: bd command not found in PATH, skipping pre-push hook" >&2
|
||||
echo " Install bd: brew install beads" >&2
|
||||
echo " Or add bd to your PATH" >&2
|
||||
exit 0
|
||||
fi
|
||||
|
||||
exec bd hooks run pre-push "$@"
|
||||
#!/usr/bin/env sh
|
||||
# bd-shim v1
|
||||
# bd-hooks-version: 0.53.0
|
||||
#
|
||||
# bd (beads) pre-push hook - thin shim
|
||||
#
|
||||
# This shim delegates to 'bd hooks run pre-push' which contains
|
||||
# the actual hook logic. This pattern ensures hook behavior is always
|
||||
# in sync with the installed bd version - no manual updates needed.
|
||||
|
||||
# Check if bd is available
|
||||
if ! command -v bd >/dev/null 2>&1; then
|
||||
echo "Warning: bd command not found in PATH, skipping pre-push hook" >&2
|
||||
echo " Install bd: brew install beads" >&2
|
||||
echo " Or add bd to your PATH" >&2
|
||||
exit 0
|
||||
fi
|
||||
|
||||
exec bd hooks run pre-push "$@"
|
||||
|
|
|
|||
|
|
@ -1,24 +1,24 @@
|
|||
#!/usr/bin/env sh
|
||||
# bd-shim v1
|
||||
# bd-hooks-version: 0.48.0
|
||||
#
|
||||
# bd (beads) prepare-commit-msg hook - thin shim
|
||||
#
|
||||
# This shim delegates to 'bd hooks run prepare-commit-msg' which contains
|
||||
# the actual hook logic. This pattern ensures hook behavior is always
|
||||
# in sync with the installed bd version - no manual updates needed.
|
||||
#
|
||||
# Arguments:
|
||||
# $1 = path to the commit message file
|
||||
# $2 = source of commit message (message, template, merge, squash, commit)
|
||||
# $3 = commit SHA-1 (if -c, -C, or --amend)
|
||||
|
||||
# Check if bd is available
|
||||
if ! command -v bd >/dev/null 2>&1; then
|
||||
echo "Warning: bd command not found in PATH, skipping prepare-commit-msg hook" >&2
|
||||
echo " Install bd: brew install beads" >&2
|
||||
echo " Or add bd to your PATH" >&2
|
||||
exit 0
|
||||
fi
|
||||
|
||||
exec bd hooks run prepare-commit-msg "$@"
|
||||
#!/usr/bin/env sh
|
||||
# bd-shim v1
|
||||
# bd-hooks-version: 0.48.0
|
||||
#
|
||||
# bd (beads) prepare-commit-msg hook - thin shim
|
||||
#
|
||||
# This shim delegates to 'bd hooks run prepare-commit-msg' which contains
|
||||
# the actual hook logic. This pattern ensures hook behavior is always
|
||||
# in sync with the installed bd version - no manual updates needed.
|
||||
#
|
||||
# Arguments:
|
||||
# $1 = path to the commit message file
|
||||
# $2 = source of commit message (message, template, merge, squash, commit)
|
||||
# $3 = commit SHA-1 (if -c, -C, or --amend)
|
||||
|
||||
# Check if bd is available
|
||||
if ! command -v bd >/dev/null 2>&1; then
|
||||
echo "Warning: bd command not found in PATH, skipping prepare-commit-msg hook" >&2
|
||||
echo " Install bd: brew install beads" >&2
|
||||
echo " Or add bd to your PATH" >&2
|
||||
exit 0
|
||||
fi
|
||||
|
||||
exec bd hooks run prepare-commit-msg "$@"
|
||||
|
|
|
|||
3
.beads/agent.txt
Normal file
3
.beads/agent.txt
Normal file
|
|
@ -0,0 +1,3 @@
|
|||
✓ Created issue: beadboard-8bs — Agent: Antigravity Graph Orchestrator
|
||||
Priority: P0
|
||||
Status: open
|
||||
61
.beads/create_help.txt
Normal file
61
.beads/create_help.txt
Normal file
|
|
@ -0,0 +1,61 @@
|
|||
Create a new issue (or multiple issues from markdown file)
|
||||
|
||||
Usage:
|
||||
bd create [title] [flags]
|
||||
|
||||
Aliases:
|
||||
create, new
|
||||
|
||||
Flags:
|
||||
--acceptance string Acceptance criteria
|
||||
--agent-rig string Agent's rig name (requires --type=agent)
|
||||
--append-notes string Append to existing notes (with newline separator)
|
||||
-a, --assignee string Assignee
|
||||
--body-file string Read description from file (use - for stdin)
|
||||
--defer string Defer until date (issue hidden from bd ready until then). Same formats as --due
|
||||
--deps strings Dependencies in format 'type:id' or 'id' (e.g., 'discovered-from:bd-20,blocks:bd-15' or 'bd-20')
|
||||
-d, --description string Issue description
|
||||
--design string Design notes
|
||||
--dry-run Preview what would be created without actually creating
|
||||
--due string Due date/time. Formats: +6h, +1d, +2w, tomorrow, next monday, 2025-01-15
|
||||
--ephemeral Create as ephemeral (short-lived, subject to TTL compaction)
|
||||
-e, --estimate int Time estimate in minutes (e.g., 60 for 1 hour)
|
||||
--event-actor string Entity URI who caused this event (requires --type=event)
|
||||
--event-category string Event category (e.g., patrol.muted, agent.started) (requires --type=event)
|
||||
--event-payload string Event-specific JSON data (requires --type=event)
|
||||
--event-target string Entity URI or bead ID affected (requires --type=event)
|
||||
--external-ref string External reference (e.g., 'gh-9', 'jira-ABC')
|
||||
-f, --file string Create multiple issues from markdown file
|
||||
--force Force creation even if prefix doesn't match database prefix
|
||||
-h, --help help for create
|
||||
--id string Explicit issue ID (e.g., 'bd-42' for partitioning)
|
||||
-l, --labels strings Labels (comma-separated)
|
||||
--metadata string Set custom metadata (JSON string or @file.json to read from file)
|
||||
--mol-type string Molecule type: swarm (multi-polecat), patrol (recurring ops), work (default)
|
||||
--no-inherit-labels Don't inherit labels from parent issue
|
||||
--notes string Additional notes
|
||||
--parent string Parent issue ID for hierarchical child (e.g., 'bd-a3f8e9')
|
||||
--prefix string Create issue in rig by prefix (e.g., --prefix bd- or --prefix bd or --prefix beads)
|
||||
-p, --priority string Priority (0-4 or P0-P4, 0=highest) (default "2")
|
||||
--repo string Target repository for issue (overrides auto-routing)
|
||||
--rig string Create issue in a different rig (e.g., --rig beads)
|
||||
--silent Output only the issue ID (for scripting)
|
||||
--spec-id string Link to specification document
|
||||
--title string Issue title (alternative to positional argument)
|
||||
-t, --type string Issue type (bug|feature|task|epic|chore|decision); custom types require types.custom config; aliases: enhancement/feat→feature, dec/adr→decision (default "task")
|
||||
--validate Validate description contains required sections for issue type
|
||||
--waits-for string Spawner issue ID to wait for (creates waits-for dependency for fanout gate)
|
||||
--waits-for-gate string Gate type: all-children (wait for all) or any-children (wait for first) (default "all-children")
|
||||
--wisp-type string Wisp type for TTL-based compaction: heartbeat, ping, patrol, gc_report, recovery, error, escalation
|
||||
|
||||
Global Flags:
|
||||
--actor string Actor name for audit trail (default: $BD_ACTOR, git user.name, $USER)
|
||||
--allow-stale Allow operations on potentially stale data (skip staleness check)
|
||||
--db string Database path (default: auto-discover .beads/*.db)
|
||||
--dolt-auto-commit string Dolt auto-commit policy (off|on|batch). 'on': commit after each write. 'batch': defer commits to bd sync / bd dolt commit; uncommitted changes persist in the working set until then. SIGTERM/SIGHUP flush pending batch commits. Default: off. Override via config key dolt.auto-commit
|
||||
--json Output in JSON format
|
||||
--profile Generate CPU profile for performance analysis
|
||||
-q, --quiet Suppress non-essential output (errors only)
|
||||
--readonly Read-only mode: block write operations (for worker sandboxes)
|
||||
--sandbox Sandbox mode: disables auto-sync
|
||||
-v, --verbose Enable verbose/debug output
|
||||
1
.beads/debug.txt
Normal file
1
.beads/debug.txt
Normal file
|
|
@ -0,0 +1 @@
|
|||
✓ Updated issue: beadboard-txj.2 — Apply Status Colors and Transitive Context to Graph Edges
|
||||
42
.beads/dep_help.txt
Normal file
42
.beads/dep_help.txt
Normal file
|
|
@ -0,0 +1,42 @@
|
|||
Manage dependencies between issues.
|
||||
|
||||
When called with an issue ID and --blocks flag, creates a blocking dependency:
|
||||
bd dep <blocker-id> --blocks <blocked-id>
|
||||
|
||||
This is equivalent to:
|
||||
bd dep add <blocked-id> <blocker-id>
|
||||
|
||||
Examples:
|
||||
bd dep bd-xyz --blocks bd-abc # bd-xyz blocks bd-abc
|
||||
bd dep add bd-abc bd-xyz # Same as above (bd-abc depends on bd-xyz)
|
||||
|
||||
Usage:
|
||||
bd dep [issue-id] [flags]
|
||||
bd dep [command]
|
||||
|
||||
Available Commands:
|
||||
add Add a dependency
|
||||
cycles Detect dependency cycles
|
||||
list List dependencies or dependents of an issue
|
||||
relate Create a bidirectional relates_to link between issues
|
||||
remove Remove a dependency
|
||||
tree Show dependency tree
|
||||
unrelate Remove a relates_to link between issues
|
||||
|
||||
Flags:
|
||||
-b, --blocks string Issue ID that this issue blocks (shorthand for: bd dep add <blocked> <blocker>)
|
||||
-h, --help help for dep
|
||||
|
||||
Global Flags:
|
||||
--actor string Actor name for audit trail (default: $BD_ACTOR, git user.name, $USER)
|
||||
--allow-stale Allow operations on potentially stale data (skip staleness check)
|
||||
--db string Database path (default: auto-discover .beads/*.db)
|
||||
--dolt-auto-commit string Dolt auto-commit policy (off|on|batch). 'on': commit after each write. 'batch': defer commits to bd sync / bd dolt commit; uncommitted changes persist in the working set until then. SIGTERM/SIGHUP flush pending batch commits. Default: off. Override via config key dolt.auto-commit
|
||||
--json Output in JSON format
|
||||
--profile Generate CPU profile for performance analysis
|
||||
-q, --quiet Suppress non-essential output (errors only)
|
||||
--readonly Read-only mode: block write operations (for worker sandboxes)
|
||||
--sandbox Sandbox mode: disables auto-sync
|
||||
-v, --verbose Enable verbose/debug output
|
||||
|
||||
Use "bd dep [command] --help" for more information about a command.
|
||||
|
|
@ -1 +1 @@
|
|||
3840
|
||||
1910
|
||||
|
|
@ -1 +0,0 @@
|
|||
1772407425
|
||||
File diff suppressed because it is too large
Load diff
|
|
@ -1 +0,0 @@
|
|||
60816
|
||||
|
|
@ -1 +0,0 @@
|
|||
3307
|
||||
3
.beads/epic_create.txt
Normal file
3
.beads/epic_create.txt
Normal file
|
|
@ -0,0 +1,3 @@
|
|||
✓ Created issue: beadboard-txj — Epic: Enhanced Graph Edge Visualization
|
||||
Priority: P0
|
||||
Status: open
|
||||
60
.beads/lint_output.txt
Normal file
60
.beads/lint_output.txt
Normal file
|
|
@ -0,0 +1,60 @@
|
|||
|
||||
> beadboard@0.1.0 lint
|
||||
> eslint .
|
||||
|
||||
|
||||
C:\Users\Zenchant\codex\beadboard\.beads\fix.js
|
||||
1:12 error A `require()` style import is forbidden @typescript-eslint/no-require-imports
|
||||
2:14 error A `require()` style import is forbidden @typescript-eslint/no-require-imports
|
||||
|
||||
C:\Users\Zenchant\codex\beadboard\.beads\fix2.js
|
||||
1:12 error A `require()` style import is forbidden @typescript-eslint/no-require-imports
|
||||
2:14 error A `require()` style import is forbidden @typescript-eslint/no-require-imports
|
||||
|
||||
C:\Users\Zenchant\codex\beadboard\src\components\activity\activity-panel.tsx
|
||||
285:16 warning 'e' is defined but never used @typescript-eslint/no-unused-vars
|
||||
|
||||
C:\Users\Zenchant\codex\beadboard\src\components\activity\swarm-command-feed.tsx
|
||||
83:22 warning 'e' is defined but never used @typescript-eslint/no-unused-vars
|
||||
|
||||
C:\Users\Zenchant\codex\beadboard\src\components\graph\dependency-graph-page.tsx
|
||||
641:17 warning 'unused_' is assigned a value but never used @typescript-eslint/no-unused-vars
|
||||
|
||||
C:\Users\Zenchant\codex\beadboard\src\components\graph\smart-dag.tsx
|
||||
38:15 warning 'hideClosedProp' is assigned a value but never used @typescript-eslint/no-unused-vars
|
||||
56:45 warning '_id' is defined but never used @typescript-eslint/no-unused-vars
|
||||
62:44 warning '_id' is defined but never used @typescript-eslint/no-unused-vars
|
||||
84:5 warning 'signalById' is assigned a value but never used @typescript-eslint/no-unused-vars
|
||||
85:5 warning 'cycleNodeIdSet' is assigned a value but never used @typescript-eslint/no-unused-vars
|
||||
87:5 warning 'blockerTooltipMap' is assigned a value but never used @typescript-eslint/no-unused-vars
|
||||
170:53 warning 'shouldOpenDrawer' is defined but never used @typescript-eslint/no-unused-vars
|
||||
176:9 warning 'selectedIssue' is assigned a value but never used @typescript-eslint/no-unused-vars
|
||||
|
||||
C:\Users\Zenchant\codex\beadboard\src\components\shared\top-bar.tsx
|
||||
93:82 warning 'toggleBlockedOnly' is assigned a value but never used @typescript-eslint/no-unused-vars
|
||||
|
||||
C:\Users\Zenchant\codex\beadboard\src\components\shared\unified-shell.tsx
|
||||
42:55 warning 'panel' is assigned a value but never used @typescript-eslint/no-unused-vars
|
||||
|
||||
C:\Users\Zenchant\codex\beadboard\src\components\shared\workflow-graph.tsx
|
||||
251:17 warning 'unused_' is assigned a value but never used @typescript-eslint/no-unused-vars
|
||||
|
||||
C:\Users\Zenchant\codex\beadboard\src\components\social\social-card.tsx
|
||||
116:3 warning 'onOpenThread' is defined but never used @typescript-eslint/no-unused-vars
|
||||
|
||||
C:\Users\Zenchant\codex\beadboard\src\components\swarm\swarm-detail.tsx
|
||||
4:15 warning 'SwarmCardData' is defined but never used @typescript-eslint/no-unused-vars
|
||||
6:10 warning 'cn' is defined but never used @typescript-eslint/no-unused-vars
|
||||
53:16 warning 'e' is defined but never used @typescript-eslint/no-unused-vars
|
||||
|
||||
C:\Users\Zenchant\codex\beadboard\src\components\swarm\swarm-page.tsx
|
||||
18:53 warning 'LayoutGrid' is defined but never used @typescript-eslint/no-unused-vars
|
||||
|
||||
C:\Users\Zenchant\codex\beadboard\src\hooks\use-mission-graph.ts
|
||||
33:16 warning '_e' is defined but never used @typescript-eslint/no-unused-vars
|
||||
|
||||
C:\Users\Zenchant\codex\beadboard\src\hooks\use-swarm-topology.ts
|
||||
35:16 warning '_err' is defined but never used @typescript-eslint/no-unused-vars
|
||||
|
||||
Γ£û 25 problems (4 errors, 21 warnings)
|
||||
|
||||
123
.beads/mem.txt
Normal file
123
.beads/mem.txt
Normal file
|
|
@ -0,0 +1,123 @@
|
|||
✓ beadboard-116 · [MEMORY][WORKFLOW][HARD] Evidence before completion claims [● P1 · CLOSED]
|
||||
Owner: ZenchantLive · Type: decision
|
||||
Created: 2026-03-02 · Updated: 2026-03-02
|
||||
Close reason: Ratified canonical memory
|
||||
|
||||
DESCRIPTION
|
||||
Scope: All new implementation tasks that change behavior or data flow.
|
||||
Out of Scope: Purely informational discussions without code or workflow changes.
|
||||
Rule: Start from explicit verification evidence and update work state in bd before claiming progress complete.
|
||||
Rationale: Prevents status drift and false completion claims.
|
||||
Failure Mode: Unverified completion claims lead to regressions and mistrust.
|
||||
|
||||
|
||||
NOTES
|
||||
Provenance linked: bb-92d.6, beadboard-jgy, beadboard-yz6
|
||||
|
||||
ACCEPTANCE CRITERIA
|
||||
Given an implementation task, when work begins and ends, then bd state transitions and verification command evidence are recorded.
|
||||
Verification command(s): bd show <task-id>; npm run typecheck; npm run lint; npm run test
|
||||
|
||||
LABELS: mem-canonical, mem-hard, memory, memory-workflow
|
||||
|
||||
METADATA
|
||||
domain: memory-workflow
|
||||
effective_date: 2026-03-02
|
||||
evidence_ids: bb-92d.6,beadboard-jgy,beadboard-yz6
|
||||
memory_strength: hard
|
||||
memory_version: 1
|
||||
owner: team
|
||||
plan_refs: docs/plans/2026-03-01-beads-native-memory.md,docs/plans/2026-03-02-bd-memory-fabric-design.md
|
||||
superseded_by: null
|
||||
supersedes: null
|
||||
|
||||
RELATED
|
||||
↔ ✓ bb-92d.6: Add guardrail test preventing direct writes to .beads/issues.jsonl ● P0
|
||||
↔ ✓ beadboard-jgy: Document memory workflow in help/memory and AGENTS manuals ● P1
|
||||
↔ ○ beadboard-nq9: (EPIC) [MEMORY-ANCHOR] Workflow Protocol ● P1
|
||||
↔ ✓ beadboard-yz6: Bootstrap Phase 1 Memory Fabric (anchors + canonical nodes) ● P1
|
||||
|
||||
|
||||
────────────────────────────────────────────────────────────
|
||||
|
||||
✓ beadboard-60a · [MEMORY][ARCH][HARD] Dependencies model execution order, not visual order [● P1 · CLOSED]
|
||||
Owner: ZenchantLive · Type: decision
|
||||
Created: 2026-03-02 · Updated: 2026-03-02
|
||||
Close reason: Ratified canonical memory
|
||||
|
||||
DESCRIPTION
|
||||
Scope: Dependency graph design and updates.
|
||||
Out of Scope: Visual layout decisions that do not alter execution semantics.
|
||||
Rule: Dependencies encode execution order and blocking semantics, never visual grouping.
|
||||
Rationale: Keeps ready/blocked states truthful and machine-reliable.
|
||||
Failure Mode: Incorrect dependency direction causes false blocking or unsafe parallelism.
|
||||
|
||||
|
||||
NOTES
|
||||
Provenance linked: bb-bvn, beadboard-r1i, beadboard-68k
|
||||
|
||||
ACCEPTANCE CRITERIA
|
||||
Given a dependency update, when graph state is queried, then blocked/ready outcomes match intended execution order.
|
||||
Verification command(s): bd dep tree <issue-id>; bd blocked; bd ready
|
||||
|
||||
LABELS: mem-canonical, mem-hard, memory, memory-arch
|
||||
|
||||
METADATA
|
||||
domain: memory-arch
|
||||
effective_date: 2026-03-02
|
||||
evidence_ids: bb-bvn,beadboard-r1i,beadboard-68k
|
||||
memory_strength: hard
|
||||
memory_version: 1
|
||||
owner: team
|
||||
plan_refs: docs/plans/2026-02-22-dag-views-ux-design.md
|
||||
superseded_by: null
|
||||
supersedes: null
|
||||
|
||||
RELATED
|
||||
↔ ✓ bb-bvn: Dependency Graph (React Flow) ● P0
|
||||
↔ ✓ beadboard-68k: Phase 0: UX Wiring Fixes ● P0
|
||||
↔ ○ beadboard-76p: (EPIC) [MEMORY-ANCHOR] Architecture ● P1
|
||||
↔ ✓ beadboard-r1i: Phase 1: Contextual Right Panel ● P0
|
||||
|
||||
|
||||
────────────────────────────────────────────────────────────
|
||||
|
||||
✓ beadboard-zas · [MEMORY][ARCH][HARD] Shared logic for cross-view behavior [● P1 · CLOSED]
|
||||
Owner: ZenchantLive · Type: decision
|
||||
Created: 2026-03-02 · Updated: 2026-03-02
|
||||
Close reason: Ratified canonical memory
|
||||
|
||||
DESCRIPTION
|
||||
Scope: Repeated logic used by multiple views or pages.
|
||||
Out of Scope: One-off prototypes and disposable experiments.
|
||||
Rule: Reuse shared paths/components for cross-view behavior; avoid one-off logic drift.
|
||||
Rationale: Prevents silent divergence between Kanban, Graph, and API views.
|
||||
Failure Mode: Patching one surface only creates inconsistent user behavior.
|
||||
|
||||
|
||||
NOTES
|
||||
Provenance linked: beadboard-68k.4, beadboard-68k.5, beadboard-r1i.1
|
||||
|
||||
ACCEPTANCE CRITERIA
|
||||
Given a behavior change touching multiple views, when implementation lands, then shared logic path is reused and covered by tests.
|
||||
Verification command(s): rg "<shared-function-or-hook>" src tests; npm run test
|
||||
|
||||
LABELS: mem-canonical, mem-hard, memory, memory-arch
|
||||
|
||||
METADATA
|
||||
domain: memory-arch
|
||||
effective_date: 2026-03-02
|
||||
evidence_ids: beadboard-68k.4,beadboard-68k.5,beadboard-r1i.1
|
||||
memory_strength: hard
|
||||
memory_version: 1
|
||||
owner: team
|
||||
plan_refs: docs/plans/2026-02-22-dag-views-ux-design.md,docs/plans/2026-02-15-unified-ux-prd.md
|
||||
superseded_by: null
|
||||
supersedes: null
|
||||
|
||||
RELATED
|
||||
↔ ✓ beadboard-68k.4: Fix thread drawer status badge (hardcoded 'In Progress') ● P0
|
||||
↔ ✓ beadboard-68k.5: Wire TopBar metric tiles from live issue data ● P0
|
||||
↔ ○ beadboard-76p: (EPIC) [MEMORY-ANCHOR] Architecture ● P1
|
||||
↔ ✓ beadboard-r1i.1: Extend ContextualRightPanel props and thread taskId/swarmId from shell ● P0
|
||||
|
||||
794
.beads/npm_test_output.txt
Normal file
794
.beads/npm_test_output.txt
Normal file
|
|
@ -0,0 +1,794 @@
|
|||
|
||||
> beadboard@0.1.0 test
|
||||
> node --test tests/bootstrap.test.mjs && node --import tsx --test tests/components/shared/base-card.test.tsx && node --import tsx --test tests/components/shared/agent-avatar.test.tsx && node --import tsx --test tests/components/sessions/sessions-header.test.ts && node --import tsx --test tests/components/sessions/agent-station-logic.test.ts && node --import tsx --test tests/lib/parser.test.ts && node --import tsx --test tests/lib/pathing.test.ts && node --import tsx --test tests/components/shared/left-panel.test.tsx && node --import tsx --test tests/components/shared/top-bar.test.tsx && node --import tsx --test tests/components/shared/mobile-nav.test.tsx && node --import tsx --test tests/components/swarm/swarm-card.test.tsx && node --import tsx --test tests/hooks/url-state-integration.test.ts && node --import tsx --test tests/hooks/use-graph-analysis.test.ts && node --import tsx --test tests/components/graph/smart-dag.test.tsx && node --import tsx --test tests/components/unified-shell.test.tsx && node --import tsx --test tests/components/blocked-triage-modal.test.tsx && node --import tsx --test tests/components/graph/graph-node-labels.test.tsx && node --import tsx --test tests/components/graph/graph-node-assign.test.tsx && node --import tsx --test tests/components/graph/graph-node-conversation.test.tsx && node --import tsx --test tests/lib/coord-schema.test.ts && node --import tsx --test tests/lib/install-manifest.test.ts && node --import tsx --test tests/lib/coord-events.test.ts && node --import tsx --test tests/api/coord-events-route.test.ts && node --import tsx --test tests/lib/coord-projections-inbox.test.ts && node --import tsx --test tests/lib/coord-projections-reservations.test.ts && node --import tsx --test tests/components/sessions/conversation-drawer-coord.test.tsx && node --import tsx --test tests/scripts/beadboard-launcher.test.ts && node --import tsx --test tests/scripts/install-wrappers-contract.test.ts && node --import tsx --test tests/scripts/install-sh-smoke.test.ts && node --import tsx --test tests/scripts/installer-ci-contract.test.ts && node --import tsx --test tests/docs/installer-quickstart-contract.test.ts && node --import tsx --test tests/skills/beadboard-driver/resolve-bb.test.ts && node --import tsx --test tests/skills/beadboard-driver/session-preflight.test.ts && node --import tsx --test tests/skills/beadboard-driver/generate-agent-name.test.ts && node --import tsx --test tests/skills/beadboard-driver/readiness-report.test.ts && node --import tsx --test tests/skills/beadboard-driver/skill-local-runner.test.ts && node --import tsx --test tests/skills/beadboard-driver/diagnose-env.test.ts && node --import tsx --test tests/skills/beadboard-driver/heal-common-issues.test.ts && node --import tsx --test tests/lib/epic-graph.test.ts && node --import tsx --test tests/components/shared/left-panel-filtering.test.ts && node --import tsx --test tests/hooks/use-beads-subscription-contract.test.ts && node --import tsx --test tests/components/graph/dependency-graph-hide-closed-contract.test.ts && node --import tsx --test tests/components/shared/unified-shell-hide-closed-contract.test.ts
|
||||
|
||||
TAP version 13
|
||||
# Subtest: bootstrap scaffold files exist
|
||||
ok 1 - bootstrap scaffold files exist
|
||||
---
|
||||
duration_ms: 1.5408
|
||||
...
|
||||
# Subtest: package.json has next/react/typescript scripts and deps
|
||||
ok 2 - package.json has next/react/typescript scripts and deps
|
||||
---
|
||||
duration_ms: 0.6082
|
||||
...
|
||||
1..2
|
||||
# tests 2
|
||||
# suites 0
|
||||
# pass 2
|
||||
# fail 0
|
||||
# cancelled 0
|
||||
# skipped 0
|
||||
# todo 0
|
||||
# duration_ms 89.6484
|
||||
TAP version 13
|
||||
# Subtest: BaseCard Component Contract
|
||||
# Subtest: exports BaseCard component
|
||||
ok 1 - exports BaseCard component
|
||||
---
|
||||
duration_ms: 48.4903
|
||||
...
|
||||
1..1
|
||||
ok 1 - BaseCard Component Contract
|
||||
---
|
||||
duration_ms: 49.1763
|
||||
type: 'suite'
|
||||
...
|
||||
# Subtest: BaseCard Styling Logic
|
||||
# Subtest: should be possible to import the component
|
||||
ok 1 - should be possible to import the component
|
||||
---
|
||||
duration_ms: 1.6433
|
||||
...
|
||||
# Subtest: applies correct status border class for "ready" status
|
||||
ok 2 - applies correct status border class for "ready" status
|
||||
---
|
||||
duration_ms: 8.9211
|
||||
...
|
||||
# Subtest: applies correct status border class for "blocked" status
|
||||
ok 3 - applies correct status border class for "blocked" status
|
||||
---
|
||||
duration_ms: 1.9781
|
||||
...
|
||||
# Subtest: applies selection ring when selected prop is true
|
||||
ok 4 - applies selection ring when selected prop is true
|
||||
---
|
||||
duration_ms: 1.3742
|
||||
...
|
||||
1..4
|
||||
ok 2 - BaseCard Styling Logic
|
||||
---
|
||||
duration_ms: 14.3343
|
||||
type: 'suite'
|
||||
...
|
||||
1..2
|
||||
# tests 5
|
||||
# suites 2
|
||||
# pass 5
|
||||
# fail 0
|
||||
# cancelled 0
|
||||
# skipped 0
|
||||
# todo 0
|
||||
# duration_ms 359.7963
|
||||
TAP version 13
|
||||
# Subtest: AgentAvatar Component Contract
|
||||
# Subtest: exports AgentAvatar component
|
||||
ok 1 - exports AgentAvatar component
|
||||
---
|
||||
duration_ms: 112.1114
|
||||
...
|
||||
1..1
|
||||
ok 1 - AgentAvatar Component Contract
|
||||
---
|
||||
duration_ms: 112.7409
|
||||
type: 'suite'
|
||||
...
|
||||
# Subtest: AgentAvatar Role Styling
|
||||
# Subtest: applies correct role color class for "ui" role
|
||||
ok 1 - applies correct role color class for "ui" role
|
||||
---
|
||||
duration_ms: 7.7314
|
||||
...
|
||||
# Subtest: applies correct role color class for "orchestrator" role
|
||||
ok 2 - applies correct role color class for "orchestrator" role
|
||||
---
|
||||
duration_ms: 2.3245
|
||||
...
|
||||
1..2
|
||||
ok 2 - AgentAvatar Role Styling
|
||||
---
|
||||
duration_ms: 10.3257
|
||||
type: 'suite'
|
||||
...
|
||||
# Subtest: AgentAvatar ZFC States
|
||||
# Subtest: applies working pulse glow
|
||||
ok 1 - applies working pulse glow
|
||||
---
|
||||
duration_ms: 1.7868
|
||||
...
|
||||
1..1
|
||||
ok 3 - AgentAvatar ZFC States
|
||||
---
|
||||
duration_ms: 2.1043
|
||||
type: 'suite'
|
||||
...
|
||||
1..3
|
||||
# tests 4
|
||||
# suites 3
|
||||
# pass 4
|
||||
# fail 0
|
||||
# cancelled 0
|
||||
# skipped 0
|
||||
# todo 0
|
||||
# duration_ms 414.8522
|
||||
TAP version 13
|
||||
# Subtest: SessionsHeader: Agent Grouping
|
||||
# Subtest: groups agents by swarm
|
||||
ok 1 - groups agents by swarm
|
||||
---
|
||||
duration_ms: 2.028
|
||||
...
|
||||
# Subtest: shows fallback bucket for unassigned agents
|
||||
ok 2 - shows fallback bucket for unassigned agents
|
||||
---
|
||||
duration_ms: 0.163
|
||||
...
|
||||
# Subtest: handles empty swarm groups
|
||||
ok 3 - handles empty swarm groups
|
||||
---
|
||||
duration_ms: 0.1271
|
||||
...
|
||||
1..3
|
||||
ok 1 - SessionsHeader: Agent Grouping
|
||||
---
|
||||
duration_ms: 3.2566
|
||||
type: 'suite'
|
||||
...
|
||||
1..1
|
||||
# tests 3
|
||||
# suites 1
|
||||
# pass 3
|
||||
# fail 0
|
||||
# cancelled 0
|
||||
# skipped 0
|
||||
# todo 0
|
||||
# duration_ms 259.5842
|
||||
TAP version 13
|
||||
# Subtest: getAgentRoleColor returns correct color for known roles
|
||||
ok 1 - getAgentRoleColor returns correct color for known roles
|
||||
---
|
||||
duration_ms: 0.7893
|
||||
...
|
||||
# Subtest: getAgentRoleColor returns default for unknown role
|
||||
ok 2 - getAgentRoleColor returns default for unknown role
|
||||
---
|
||||
duration_ms: 0.1416
|
||||
...
|
||||
1..2
|
||||
# tests 2
|
||||
# suites 0
|
||||
# pass 2
|
||||
# fail 0
|
||||
# cancelled 0
|
||||
# skipped 0
|
||||
# todo 0
|
||||
# duration_ms 260.6046
|
||||
TAP version 13
|
||||
# Subtest: parseIssuesJsonl applies defaults and preserves priority 0
|
||||
ok 1 - parseIssuesJsonl applies defaults and preserves priority 0
|
||||
---
|
||||
duration_ms: 1.1468
|
||||
...
|
||||
# Subtest: parseIssuesJsonl skips malformed and blank lines
|
||||
ok 2 - parseIssuesJsonl skips malformed and blank lines
|
||||
---
|
||||
duration_ms: 0.2118
|
||||
...
|
||||
# Subtest: parseIssuesJsonl filters tombstones by default
|
||||
ok 3 - parseIssuesJsonl filters tombstones by default
|
||||
---
|
||||
duration_ms: 0.1758
|
||||
...
|
||||
# Subtest: parseIssuesJsonl can include tombstones when requested
|
||||
ok 4 - parseIssuesJsonl can include tombstones when requested
|
||||
---
|
||||
duration_ms: 0.1626
|
||||
...
|
||||
# Subtest: parseIssuesJsonl supports beads dependency schema with depends_on_id and parent-child
|
||||
ok 5 - parseIssuesJsonl supports beads dependency schema with depends_on_id and parent-child
|
||||
---
|
||||
duration_ms: 0.7949
|
||||
...
|
||||
1..5
|
||||
# tests 5
|
||||
# suites 0
|
||||
# pass 5
|
||||
# fail 0
|
||||
# cancelled 0
|
||||
# skipped 0
|
||||
# todo 0
|
||||
# duration_ms 269.9367
|
||||
TAP version 13
|
||||
# Subtest: canonicalizeWindowsPath normalizes separators and drive casing
|
||||
ok 1 - canonicalizeWindowsPath normalizes separators and drive casing
|
||||
---
|
||||
duration_ms: 1.4342
|
||||
...
|
||||
# Subtest: windowsPathKey is case-insensitive stable key
|
||||
ok 2 - windowsPathKey is case-insensitive stable key
|
||||
---
|
||||
duration_ms: 0.4737
|
||||
...
|
||||
# Subtest: toDisplayPath renders forward slashes for UI readability
|
||||
ok 3 - toDisplayPath renders forward slashes for UI readability
|
||||
---
|
||||
duration_ms: 0.2287
|
||||
...
|
||||
# Subtest: sameWindowsPath handles case/separator differences
|
||||
ok 4 - sameWindowsPath handles case/separator differences
|
||||
---
|
||||
duration_ms: 0.2269
|
||||
...
|
||||
1..4
|
||||
# tests 4
|
||||
# suites 0
|
||||
# pass 4
|
||||
# fail 0
|
||||
# cancelled 0
|
||||
# skipped 0
|
||||
# todo 0
|
||||
# duration_ms 290.6242
|
||||
TAP version 13
|
||||
# Subtest: LeftPanel Component Contract
|
||||
# Subtest: exports LeftPanel component
|
||||
ok 1 - exports LeftPanel component
|
||||
---
|
||||
duration_ms: 291.6468
|
||||
...
|
||||
# Subtest: LeftPanel accepts issues and onEpicSelect props
|
||||
ok 2 - LeftPanel accepts issues and onEpicSelect props
|
||||
---
|
||||
duration_ms: 1.3553
|
||||
...
|
||||
1..2
|
||||
ok 1 - LeftPanel Component Contract
|
||||
---
|
||||
duration_ms: 294.0487
|
||||
type: 'suite'
|
||||
...
|
||||
# Subtest: LeftPanel Tree Structure
|
||||
# Subtest: renders epics as expandable tree items
|
||||
ok 1 - renders epics as expandable tree items
|
||||
---
|
||||
duration_ms: 1.1796
|
||||
...
|
||||
# Subtest: groups beads under their parent epic
|
||||
ok 2 - groups beads under their parent epic
|
||||
---
|
||||
duration_ms: 1.1357
|
||||
...
|
||||
1..2
|
||||
ok 2 - LeftPanel Tree Structure
|
||||
---
|
||||
duration_ms: 2.5592
|
||||
type: 'suite'
|
||||
...
|
||||
# Subtest: LeftPanel Responsive Behavior
|
||||
# Subtest: applies responsive classes for desktop, tablet, and mobile
|
||||
ok 1 - applies responsive classes for desktop, tablet, and mobile
|
||||
---
|
||||
duration_ms: 1.4154
|
||||
...
|
||||
1..1
|
||||
ok 3 - LeftPanel Responsive Behavior
|
||||
---
|
||||
duration_ms: 1.6082
|
||||
type: 'suite'
|
||||
...
|
||||
# Subtest: LeftPanel Scope Controls
|
||||
# Subtest: renders scope section
|
||||
ok 1 - renders scope section
|
||||
---
|
||||
duration_ms: 1.2414
|
||||
...
|
||||
1..1
|
||||
ok 4 - LeftPanel Scope Controls
|
||||
---
|
||||
duration_ms: 1.5705
|
||||
type: 'suite'
|
||||
...
|
||||
1..4
|
||||
# tests 6
|
||||
# suites 4
|
||||
# pass 6
|
||||
# fail 0
|
||||
# cancelled 0
|
||||
# skipped 0
|
||||
# todo 0
|
||||
# duration_ms 586.4632
|
||||
TAP version 13
|
||||
# Subtest: TopBar Component Contract
|
||||
# Subtest: exports TopBar component
|
||||
ok 1 - exports TopBar component
|
||||
---
|
||||
duration_ms: 576.3556
|
||||
...
|
||||
# Subtest: TopBar component can be imported without errors
|
||||
ok 2 - TopBar component can be imported without errors
|
||||
---
|
||||
duration_ms: 1.4049
|
||||
...
|
||||
1..2
|
||||
ok 1 - TopBar Component Contract
|
||||
---
|
||||
duration_ms: 578.6933
|
||||
type: 'suite'
|
||||
...
|
||||
# Subtest: TopBar View Tabs
|
||||
# Subtest: renders view tabs: Social, Graph
|
||||
ok 1 - renders view tabs: Social, Graph
|
||||
---
|
||||
duration_ms: 1.1653
|
||||
...
|
||||
# Subtest: active tab has bold text and accent underline
|
||||
ok 2 - active tab has bold text and accent underline
|
||||
---
|
||||
duration_ms: 1.0756
|
||||
...
|
||||
1..2
|
||||
ok 2 - TopBar View Tabs
|
||||
---
|
||||
duration_ms: 2.4564
|
||||
type: 'suite'
|
||||
...
|
||||
# Subtest: TopBar Filter and Controls
|
||||
# Subtest: renders filter/search input placeholder
|
||||
ok 1 - renders filter/search input placeholder
|
||||
---
|
||||
duration_ms: 1.2466
|
||||
...
|
||||
# Subtest: renders settings placeholder
|
||||
ok 2 - renders settings placeholder
|
||||
---
|
||||
duration_ms: 1.0997
|
||||
...
|
||||
1..2
|
||||
ok 3 - TopBar Filter and Controls
|
||||
---
|
||||
duration_ms: 2.7634
|
||||
type: 'suite'
|
||||
...
|
||||
1..3
|
||||
# tests 6
|
||||
# suites 3
|
||||
# pass 6
|
||||
# fail 0
|
||||
# cancelled 0
|
||||
# skipped 0
|
||||
# todo 0
|
||||
# duration_ms 843.1609
|
||||
TAP version 13
|
||||
# Subtest: Mobile Navigation - Hamburger Menu
|
||||
# Subtest: exports MobileNav component
|
||||
ok 1 - exports MobileNav component
|
||||
---
|
||||
duration_ms: 122.7061
|
||||
...
|
||||
# Subtest: renders tab buttons: Social, Graph
|
||||
ok 2 - renders tab buttons: Social, Graph
|
||||
---
|
||||
duration_ms: 1.5081
|
||||
...
|
||||
# Subtest: highlights active tab with accent color
|
||||
ok 3 - highlights active tab with accent color
|
||||
---
|
||||
duration_ms: 1.5626
|
||||
...
|
||||
# Subtest: uses setView from useUrlState on tab click
|
||||
ok 4 - uses setView from useUrlState on tab click
|
||||
---
|
||||
duration_ms: 1.3467
|
||||
...
|
||||
1..4
|
||||
ok 1 - Mobile Navigation - Hamburger Menu
|
||||
---
|
||||
duration_ms: 128.9482
|
||||
type: 'suite'
|
||||
...
|
||||
# Subtest: TopBar Hamburger Menu
|
||||
# Subtest: shows hamburger button on mobile and tablet
|
||||
ok 1 - shows hamburger button on mobile and tablet
|
||||
---
|
||||
duration_ms: 487.0038
|
||||
...
|
||||
# Subtest: hamburger button opens left panel drawer
|
||||
ok 2 - hamburger button opens left panel drawer
|
||||
---
|
||||
duration_ms: 1.478
|
||||
...
|
||||
# Subtest: hides hamburger on desktop
|
||||
ok 3 - hides hamburger on desktop
|
||||
---
|
||||
duration_ms: 1.1051
|
||||
...
|
||||
1..3
|
||||
ok 2 - TopBar Hamburger Menu
|
||||
---
|
||||
duration_ms: 490.1177
|
||||
type: 'suite'
|
||||
...
|
||||
1..2
|
||||
# tests 7
|
||||
# suites 2
|
||||
# pass 7
|
||||
# fail 0
|
||||
# cancelled 0
|
||||
# skipped 0
|
||||
# todo 0
|
||||
# duration_ms 899.3239
|
||||
TAP version 13
|
||||
# Subtest: SwarmCard Component Contract
|
||||
# Subtest: exports SwarmCard component
|
||||
ok 1 - exports SwarmCard component
|
||||
---
|
||||
duration_ms: 238.5797
|
||||
...
|
||||
# Subtest: SwarmCard component can be imported without errors
|
||||
ok 2 - SwarmCard component can be imported without errors
|
||||
---
|
||||
duration_ms: 1.6861
|
||||
...
|
||||
1..2
|
||||
ok 1 - SwarmCard Component Contract
|
||||
---
|
||||
duration_ms: 241.2828
|
||||
type: 'suite'
|
||||
...
|
||||
# Subtest: SwarmCard Agent Roster
|
||||
# Subtest: renders agent avatars with liveness glow
|
||||
ok 1 - renders agent avatars with liveness glow
|
||||
---
|
||||
duration_ms: 1.7451
|
||||
...
|
||||
# Subtest: displays agent current task when available
|
||||
ok 2 - displays agent current task when available
|
||||
---
|
||||
duration_ms: 1.4825
|
||||
...
|
||||
1..2
|
||||
ok 2 - SwarmCard Agent Roster
|
||||
---
|
||||
duration_ms: 3.5718
|
||||
type: 'suite'
|
||||
...
|
||||
# Subtest: SwarmCard Progress Bar
|
||||
# Subtest: renders progress bar showing completion percentage
|
||||
ok 1 - renders progress bar showing completion percentage
|
||||
---
|
||||
duration_ms: 1.6795
|
||||
...
|
||||
1..1
|
||||
ok 3 - SwarmCard Progress Bar
|
||||
---
|
||||
duration_ms: 1.8984
|
||||
type: 'suite'
|
||||
...
|
||||
# Subtest: SwarmCard Attention Items
|
||||
# Subtest: renders attention items with warning styling
|
||||
ok 1 - renders attention items with warning styling
|
||||
---
|
||||
duration_ms: 1.7077
|
||||
...
|
||||
1..1
|
||||
ok 4 - SwarmCard Attention Items
|
||||
---
|
||||
duration_ms: 2.1567
|
||||
type: 'suite'
|
||||
...
|
||||
# Subtest: SwarmCard View-Jump Icons
|
||||
# Subtest: renders view-jump icons for navigation
|
||||
ok 1 - renders view-jump icons for navigation
|
||||
---
|
||||
duration_ms: 1.7431
|
||||
...
|
||||
1..1
|
||||
ok 5 - SwarmCard View-Jump Icons
|
||||
---
|
||||
duration_ms: 2.0339
|
||||
type: 'suite'
|
||||
...
|
||||
1..5
|
||||
# tests 7
|
||||
# suites 5
|
||||
# pass 7
|
||||
# fail 0
|
||||
# cancelled 0
|
||||
# skipped 0
|
||||
# todo 0
|
||||
# duration_ms 515.754
|
||||
TAP version 13
|
||||
# Subtest: URL State Integration - bb-ui2.22
|
||||
# Subtest: Valid URL Patterns - Social View
|
||||
# Subtest: /?view=social - defaults to social view
|
||||
ok 1 - /?view=social - defaults to social view
|
||||
---
|
||||
duration_ms: 0.8379
|
||||
...
|
||||
# Subtest: /?view=social&task=bb-buff.1&panel=open - task selected, panel open
|
||||
ok 2 - /?view=social&task=bb-buff.1&panel=open - task selected, panel open
|
||||
---
|
||||
duration_ms: 0.2068
|
||||
...
|
||||
# Subtest: /?view=social&task=bb-ui2.22 - task with dots in ID
|
||||
ok 3 - /?view=social&task=bb-ui2.22 - task with dots in ID
|
||||
---
|
||||
duration_ms: 0.1241
|
||||
...
|
||||
1..3
|
||||
ok 1 - Valid URL Patterns - Social View
|
||||
---
|
||||
duration_ms: 1.803
|
||||
type: 'suite'
|
||||
...
|
||||
# Subtest: Valid URL Patterns - Graph View
|
||||
# Subtest: /?view=graph - graph view default
|
||||
not ok 1 - /?view=graph - graph view default
|
||||
---
|
||||
duration_ms: 3.2799
|
||||
location: 'C:\\Users\\Zenchant\\codex\\beadboard\\tests\\hooks\\url-state-integration.test.ts:2:2578'
|
||||
failureType: 'testCodeFailure'
|
||||
error: |-
|
||||
Expected values to be strictly equal:
|
||||
|
||||
'overview' !== 'flow'
|
||||
|
||||
code: 'ERR_ASSERTION'
|
||||
name: 'AssertionError'
|
||||
expected: 'flow'
|
||||
actual: 'overview'
|
||||
operator: 'strictEqual'
|
||||
stack: |-
|
||||
TestContext.<anonymous> (C:\Users\Zenchant\codex\beadboard\tests\hooks\url-state-integration.test.ts:53:14)
|
||||
Test.runInAsyncScope (node:async_hooks:211:14)
|
||||
Test.run (node:internal/test_runner/test:934:25)
|
||||
Test.start (node:internal/test_runner/test:833:17)
|
||||
node:internal/test_runner/test:1318:71
|
||||
node:internal/per_context/primordials:483:82
|
||||
new Promise (<anonymous>)
|
||||
new SafePromise (node:internal/per_context/primordials:451:29)
|
||||
node:internal/per_context/primordials:483:9
|
||||
Array.map (<anonymous>)
|
||||
...
|
||||
# Subtest: /?view=graph&task=bb-buff.1 - graph with task selected
|
||||
ok 2 - /?view=graph&task=bb-buff.1 - graph with task selected
|
||||
---
|
||||
duration_ms: 0.1241
|
||||
...
|
||||
# Subtest: /?view=graph&graphTab=flow - flow tab selected
|
||||
ok 3 - /?view=graph&graphTab=flow - flow tab selected
|
||||
---
|
||||
duration_ms: 0.2827
|
||||
...
|
||||
# Subtest: /?view=graph&graphTab=overview - overview tab selected
|
||||
ok 4 - /?view=graph&graphTab=overview - overview tab selected
|
||||
---
|
||||
duration_ms: 0.1152
|
||||
...
|
||||
# Subtest: /?view=graph&swarm=bb-buff - graph filtered by swarm
|
||||
ok 5 - /?view=graph&swarm=bb-buff - graph filtered by swarm
|
||||
---
|
||||
duration_ms: 0.3114
|
||||
...
|
||||
1..5
|
||||
not ok 2 - Valid URL Patterns - Graph View
|
||||
---
|
||||
duration_ms: 4.4826
|
||||
type: 'suite'
|
||||
location: 'C:\\Users\\Zenchant\\codex\\beadboard\\tests\\hooks\\url-state-integration.test.ts:2:2515'
|
||||
failureType: 'subtestsFailed'
|
||||
error: '1 subtest failed'
|
||||
code: 'ERR_TEST_FAILURE'
|
||||
...
|
||||
# Subtest: Deprecated Swarm View Fallback
|
||||
# Subtest: /?view=swarm - falls back to social (swarm view deprecated)
|
||||
ok 1 - /?view=swarm - falls back to social (swarm view deprecated)
|
||||
---
|
||||
duration_ms: 0.176
|
||||
...
|
||||
# Subtest: /?view=swarm&swarm=bb-buff - falls back to social but preserves swarmId
|
||||
ok 2 - /?view=swarm&swarm=bb-buff - falls back to social but preserves swarmId
|
||||
---
|
||||
duration_ms: 0.3375
|
||||
...
|
||||
# Subtest: /?view=swarm&swarm=bb-buff&panel=open - falls back to social with panel open
|
||||
ok 3 - /?view=swarm&swarm=bb-buff&panel=open - falls back to social with panel open
|
||||
---
|
||||
duration_ms: 0.1203
|
||||
...
|
||||
1..3
|
||||
ok 3 - Deprecated Swarm View Fallback
|
||||
---
|
||||
duration_ms: 0.8018
|
||||
type: 'suite'
|
||||
...
|
||||
# Subtest: Valid URL Patterns - Activity View
|
||||
# Subtest: /?view=activity - activity view default
|
||||
ok 1 - /?view=activity - activity view default
|
||||
---
|
||||
duration_ms: 0.1469
|
||||
...
|
||||
# Subtest: /?view=activity&agent=bb-silver-castle - filtered by agent
|
||||
ok 2 - /?view=activity&agent=bb-silver-castle - filtered by agent
|
||||
---
|
||||
duration_ms: 0.0856
|
||||
...
|
||||
# Subtest: /?view=activity&swarm=bb-buff - filtered by swarm
|
||||
ok 3 - /?view=activity&swarm=bb-buff - filtered by swarm
|
||||
---
|
||||
duration_ms: 0.0813
|
||||
...
|
||||
1..3
|
||||
ok 4 - Valid URL Patterns - Activity View
|
||||
---
|
||||
duration_ms: 0.4565
|
||||
type: 'suite'
|
||||
...
|
||||
# Subtest: Invalid Param Handling
|
||||
# Subtest: /?view=invalid - invalid view defaults to social
|
||||
ok 1 - /?view=invalid - invalid view defaults to social
|
||||
---
|
||||
duration_ms: 0.1489
|
||||
...
|
||||
# Subtest: /?view=graph&graphTab=invalid - invalid graphTab defaults to flow
|
||||
not ok 2 - /?view=graph&graphTab=invalid - invalid graphTab defaults to flow
|
||||
---
|
||||
duration_ms: 0.4762
|
||||
location: 'C:\\Users\\Zenchant\\codex\\beadboard\\tests\\hooks\\url-state-integration.test.ts:2:6479'
|
||||
failureType: 'testCodeFailure'
|
||||
error: |-
|
||||
Expected values to be strictly equal:
|
||||
|
||||
'overview' !== 'flow'
|
||||
|
||||
code: 'ERR_ASSERTION'
|
||||
name: 'AssertionError'
|
||||
expected: 'flow'
|
||||
actual: 'overview'
|
||||
operator: 'strictEqual'
|
||||
stack: |-
|
||||
TestContext.<anonymous> (C:\Users\Zenchant\codex\beadboard\tests\hooks\url-state-integration.test.ts:138:14)
|
||||
Test.runInAsyncScope (node:async_hooks:211:14)
|
||||
Test.run (node:internal/test_runner/test:934:25)
|
||||
Suite.processPendingSubtests (node:internal/test_runner/test:633:18)
|
||||
Test.postRun (node:internal/test_runner/test:1045:19)
|
||||
Test.run (node:internal/test_runner/test:973:12)
|
||||
async Promise.all (index 0)
|
||||
async Suite.run (node:internal/test_runner/test:1320:7)
|
||||
async Suite.processPendingSubtests (node:internal/test_runner/test:633:7)
|
||||
...
|
||||
# Subtest: /?panel=invalid - invalid panel defaults to open
|
||||
ok 3 - /?panel=invalid - invalid panel defaults to open
|
||||
---
|
||||
duration_ms: 0.1006
|
||||
...
|
||||
# Subtest: /?task=invalid-id - invalid task ID still parsed (no validation)
|
||||
ok 4 - /?task=invalid-id - invalid task ID still parsed (no validation)
|
||||
---
|
||||
duration_ms: 0.0841
|
||||
...
|
||||
1..4
|
||||
not ok 5 - Invalid Param Handling
|
||||
---
|
||||
duration_ms: 0.9701
|
||||
type: 'suite'
|
||||
location: 'C:\\Users\\Zenchant\\codex\\beadboard\\tests\\hooks\\url-state-integration.test.ts:2:6178'
|
||||
failureType: 'subtestsFailed'
|
||||
error: '1 subtest failed'
|
||||
code: 'ERR_TEST_FAILURE'
|
||||
...
|
||||
# Subtest: URL Building - State to URL
|
||||
# Subtest: builds social view URL
|
||||
ok 1 - builds social view URL
|
||||
---
|
||||
duration_ms: 0.2194
|
||||
...
|
||||
# Subtest: builds graph view with task URL
|
||||
ok 2 - builds graph view with task URL
|
||||
---
|
||||
duration_ms: 0.0932
|
||||
...
|
||||
# Subtest: builds swarm view with swarm param
|
||||
ok 3 - builds swarm view with swarm param
|
||||
---
|
||||
duration_ms: 0.085
|
||||
...
|
||||
# Subtest: builds activity view with agent filter
|
||||
ok 4 - builds activity view with agent filter
|
||||
---
|
||||
duration_ms: 0.1405
|
||||
...
|
||||
# Subtest: preserves existing params when adding new ones
|
||||
ok 5 - preserves existing params when adding new ones
|
||||
---
|
||||
duration_ms: 0.1868
|
||||
...
|
||||
# Subtest: removes params when set to null
|
||||
ok 6 - removes params when set to null
|
||||
---
|
||||
duration_ms: 0.1154
|
||||
...
|
||||
# Subtest: returns root when all params cleared
|
||||
ok 7 - returns root when all params cleared
|
||||
---
|
||||
duration_ms: 0.0926
|
||||
...
|
||||
1..7
|
||||
ok 6 - URL Building - State to URL
|
||||
---
|
||||
duration_ms: 1.1103
|
||||
type: 'suite'
|
||||
...
|
||||
# Subtest: Complex URL Scenarios
|
||||
# Subtest: handles all params together
|
||||
ok 1 - handles all params together
|
||||
---
|
||||
duration_ms: 0.123
|
||||
...
|
||||
# Subtest: empty string values treated as null/empty
|
||||
ok 2 - empty string values treated as null/empty
|
||||
---
|
||||
duration_ms: 0.0893
|
||||
...
|
||||
1..2
|
||||
ok 7 - Complex URL Scenarios
|
||||
---
|
||||
duration_ms: 0.351
|
||||
type: 'suite'
|
||||
...
|
||||
# Subtest: Deep Link Patterns - From Card Icons
|
||||
# Subtest: SocialCard Graph icon: /?view=graph&task={id}
|
||||
ok 1 - SocialCard Graph icon: /?view=graph&task={id}
|
||||
---
|
||||
duration_ms: 0.1287
|
||||
...
|
||||
# Subtest: SwarmCard Graph icon: /?view=graph&swarm={id}
|
||||
ok 2 - SwarmCard Graph icon: /?view=graph&swarm={id}
|
||||
---
|
||||
duration_ms: 0.0785
|
||||
...
|
||||
# Subtest: SwarmCard Timeline icon: /?view=activity&swarm={id}
|
||||
ok 3 - SwarmCard Timeline icon: /?view=activity&swarm={id}
|
||||
---
|
||||
duration_ms: 0.1411
|
||||
...
|
||||
# Subtest: Agent avatar click: /?view=activity&agent={id}
|
||||
ok 4 - Agent avatar click: /?view=activity&agent={id}
|
||||
---
|
||||
duration_ms: 0.076
|
||||
...
|
||||
1..4
|
||||
ok 8 - Deep Link Patterns - From Card Icons
|
||||
---
|
||||
duration_ms: 0.5678
|
||||
type: 'suite'
|
||||
...
|
||||
1..8
|
||||
not ok 1 - URL State Integration - bb-ui2.22
|
||||
---
|
||||
duration_ms: 11.4418
|
||||
type: 'suite'
|
||||
location: 'C:\\Users\\Zenchant\\codex\\beadboard\\tests\\hooks\\url-state-integration.test.ts:2:1269'
|
||||
failureType: 'subtestsFailed'
|
||||
error: '2 subtests failed'
|
||||
code: 'ERR_TEST_FAILURE'
|
||||
...
|
||||
1..1
|
||||
# tests 31
|
||||
# suites 9
|
||||
# pass 29
|
||||
# fail 2
|
||||
# cancelled 0
|
||||
# skipped 0
|
||||
# todo 0
|
||||
# duration_ms 447.3716
|
||||
919
.beads/npm_test_output2.txt
Normal file
919
.beads/npm_test_output2.txt
Normal file
|
|
@ -0,0 +1,919 @@
|
|||
|
||||
> beadboard@0.1.0 test
|
||||
> node --test tests/bootstrap.test.mjs && node --import tsx --test tests/components/shared/base-card.test.tsx && node --import tsx --test tests/components/shared/agent-avatar.test.tsx && node --import tsx --test tests/components/sessions/sessions-header.test.ts && node --import tsx --test tests/components/sessions/agent-station-logic.test.ts && node --import tsx --test tests/lib/parser.test.ts && node --import tsx --test tests/lib/pathing.test.ts && node --import tsx --test tests/components/shared/left-panel.test.tsx && node --import tsx --test tests/components/shared/top-bar.test.tsx && node --import tsx --test tests/components/shared/mobile-nav.test.tsx && node --import tsx --test tests/components/swarm/swarm-card.test.tsx && node --import tsx --test tests/hooks/url-state-integration.test.ts && node --import tsx --test tests/hooks/use-graph-analysis.test.ts && node --import tsx --test tests/components/graph/smart-dag.test.tsx && node --import tsx --test tests/components/unified-shell.test.tsx && node --import tsx --test tests/components/blocked-triage-modal.test.tsx && node --import tsx --test tests/components/graph/graph-node-labels.test.tsx && node --import tsx --test tests/components/graph/graph-node-assign.test.tsx && node --import tsx --test tests/components/graph/graph-node-conversation.test.tsx && node --import tsx --test tests/lib/coord-schema.test.ts && node --import tsx --test tests/lib/install-manifest.test.ts && node --import tsx --test tests/lib/coord-events.test.ts && node --import tsx --test tests/api/coord-events-route.test.ts && node --import tsx --test tests/lib/coord-projections-inbox.test.ts && node --import tsx --test tests/lib/coord-projections-reservations.test.ts && node --import tsx --test tests/components/sessions/conversation-drawer-coord.test.tsx && node --import tsx --test tests/scripts/beadboard-launcher.test.ts && node --import tsx --test tests/scripts/install-wrappers-contract.test.ts && node --import tsx --test tests/scripts/install-sh-smoke.test.ts && node --import tsx --test tests/scripts/installer-ci-contract.test.ts && node --import tsx --test tests/docs/installer-quickstart-contract.test.ts && node --import tsx --test tests/skills/beadboard-driver/resolve-bb.test.ts && node --import tsx --test tests/skills/beadboard-driver/session-preflight.test.ts && node --import tsx --test tests/skills/beadboard-driver/generate-agent-name.test.ts && node --import tsx --test tests/skills/beadboard-driver/readiness-report.test.ts && node --import tsx --test tests/skills/beadboard-driver/skill-local-runner.test.ts && node --import tsx --test tests/skills/beadboard-driver/diagnose-env.test.ts && node --import tsx --test tests/skills/beadboard-driver/heal-common-issues.test.ts && node --import tsx --test tests/lib/epic-graph.test.ts && node --import tsx --test tests/components/shared/left-panel-filtering.test.ts && node --import tsx --test tests/hooks/use-beads-subscription-contract.test.ts && node --import tsx --test tests/components/graph/dependency-graph-hide-closed-contract.test.ts && node --import tsx --test tests/components/shared/unified-shell-hide-closed-contract.test.ts
|
||||
|
||||
TAP version 13
|
||||
# Subtest: bootstrap scaffold files exist
|
||||
ok 1 - bootstrap scaffold files exist
|
||||
---
|
||||
duration_ms: 2.2085
|
||||
...
|
||||
# Subtest: package.json has next/react/typescript scripts and deps
|
||||
ok 2 - package.json has next/react/typescript scripts and deps
|
||||
---
|
||||
duration_ms: 0.5581
|
||||
...
|
||||
1..2
|
||||
# tests 2
|
||||
# suites 0
|
||||
# pass 2
|
||||
# fail 0
|
||||
# cancelled 0
|
||||
# skipped 0
|
||||
# todo 0
|
||||
# duration_ms 140.1608
|
||||
TAP version 13
|
||||
# Subtest: BaseCard Component Contract
|
||||
# Subtest: exports BaseCard component
|
||||
ok 1 - exports BaseCard component
|
||||
---
|
||||
duration_ms: 58.211
|
||||
...
|
||||
1..1
|
||||
ok 1 - BaseCard Component Contract
|
||||
---
|
||||
duration_ms: 58.9965
|
||||
type: 'suite'
|
||||
...
|
||||
# Subtest: BaseCard Styling Logic
|
||||
# Subtest: should be possible to import the component
|
||||
ok 1 - should be possible to import the component
|
||||
---
|
||||
duration_ms: 2.4528
|
||||
...
|
||||
# Subtest: applies correct status border class for "ready" status
|
||||
ok 2 - applies correct status border class for "ready" status
|
||||
---
|
||||
duration_ms: 10.367
|
||||
...
|
||||
# Subtest: applies correct status border class for "blocked" status
|
||||
ok 3 - applies correct status border class for "blocked" status
|
||||
---
|
||||
duration_ms: 2.0545
|
||||
...
|
||||
# Subtest: applies selection ring when selected prop is true
|
||||
ok 4 - applies selection ring when selected prop is true
|
||||
---
|
||||
duration_ms: 1.3688
|
||||
...
|
||||
1..4
|
||||
ok 2 - BaseCard Styling Logic
|
||||
---
|
||||
duration_ms: 16.6551
|
||||
type: 'suite'
|
||||
...
|
||||
1..2
|
||||
# tests 5
|
||||
# suites 2
|
||||
# pass 5
|
||||
# fail 0
|
||||
# cancelled 0
|
||||
# skipped 0
|
||||
# todo 0
|
||||
# duration_ms 447.2767
|
||||
TAP version 13
|
||||
# Subtest: AgentAvatar Component Contract
|
||||
# Subtest: exports AgentAvatar component
|
||||
ok 1 - exports AgentAvatar component
|
||||
---
|
||||
duration_ms: 154.6347
|
||||
...
|
||||
1..1
|
||||
ok 1 - AgentAvatar Component Contract
|
||||
---
|
||||
duration_ms: 155.6009
|
||||
type: 'suite'
|
||||
...
|
||||
# Subtest: AgentAvatar Role Styling
|
||||
# Subtest: applies correct role color class for "ui" role
|
||||
ok 1 - applies correct role color class for "ui" role
|
||||
---
|
||||
duration_ms: 11.7114
|
||||
...
|
||||
# Subtest: applies correct role color class for "orchestrator" role
|
||||
ok 2 - applies correct role color class for "orchestrator" role
|
||||
---
|
||||
duration_ms: 2.6704
|
||||
...
|
||||
1..2
|
||||
ok 2 - AgentAvatar Role Styling
|
||||
---
|
||||
duration_ms: 14.7057
|
||||
type: 'suite'
|
||||
...
|
||||
# Subtest: AgentAvatar ZFC States
|
||||
# Subtest: applies working pulse glow
|
||||
ok 1 - applies working pulse glow
|
||||
---
|
||||
duration_ms: 2.4504
|
||||
...
|
||||
1..1
|
||||
ok 3 - AgentAvatar ZFC States
|
||||
---
|
||||
duration_ms: 2.8198
|
||||
type: 'suite'
|
||||
...
|
||||
1..3
|
||||
# tests 4
|
||||
# suites 3
|
||||
# pass 4
|
||||
# fail 0
|
||||
# cancelled 0
|
||||
# skipped 0
|
||||
# todo 0
|
||||
# duration_ms 539.4517
|
||||
TAP version 13
|
||||
# Subtest: SessionsHeader: Agent Grouping
|
||||
# Subtest: groups agents by swarm
|
||||
ok 1 - groups agents by swarm
|
||||
---
|
||||
duration_ms: 2.114
|
||||
...
|
||||
# Subtest: shows fallback bucket for unassigned agents
|
||||
ok 2 - shows fallback bucket for unassigned agents
|
||||
---
|
||||
duration_ms: 0.1808
|
||||
...
|
||||
# Subtest: handles empty swarm groups
|
||||
ok 3 - handles empty swarm groups
|
||||
---
|
||||
duration_ms: 0.1339
|
||||
...
|
||||
1..3
|
||||
ok 1 - SessionsHeader: Agent Grouping
|
||||
---
|
||||
duration_ms: 3.4059
|
||||
type: 'suite'
|
||||
...
|
||||
1..1
|
||||
# tests 3
|
||||
# suites 1
|
||||
# pass 3
|
||||
# fail 0
|
||||
# cancelled 0
|
||||
# skipped 0
|
||||
# todo 0
|
||||
# duration_ms 283.1807
|
||||
TAP version 13
|
||||
# Subtest: getAgentRoleColor returns correct color for known roles
|
||||
ok 1 - getAgentRoleColor returns correct color for known roles
|
||||
---
|
||||
duration_ms: 0.8966
|
||||
...
|
||||
# Subtest: getAgentRoleColor returns default for unknown role
|
||||
ok 2 - getAgentRoleColor returns default for unknown role
|
||||
---
|
||||
duration_ms: 0.1598
|
||||
...
|
||||
1..2
|
||||
# tests 2
|
||||
# suites 0
|
||||
# pass 2
|
||||
# fail 0
|
||||
# cancelled 0
|
||||
# skipped 0
|
||||
# todo 0
|
||||
# duration_ms 309.895
|
||||
TAP version 13
|
||||
# Subtest: parseIssuesJsonl applies defaults and preserves priority 0
|
||||
ok 1 - parseIssuesJsonl applies defaults and preserves priority 0
|
||||
---
|
||||
duration_ms: 1.1101
|
||||
...
|
||||
# Subtest: parseIssuesJsonl skips malformed and blank lines
|
||||
ok 2 - parseIssuesJsonl skips malformed and blank lines
|
||||
---
|
||||
duration_ms: 0.1784
|
||||
...
|
||||
# Subtest: parseIssuesJsonl filters tombstones by default
|
||||
ok 3 - parseIssuesJsonl filters tombstones by default
|
||||
---
|
||||
duration_ms: 0.1475
|
||||
...
|
||||
# Subtest: parseIssuesJsonl can include tombstones when requested
|
||||
ok 4 - parseIssuesJsonl can include tombstones when requested
|
||||
---
|
||||
duration_ms: 0.1428
|
||||
...
|
||||
# Subtest: parseIssuesJsonl supports beads dependency schema with depends_on_id and parent-child
|
||||
ok 5 - parseIssuesJsonl supports beads dependency schema with depends_on_id and parent-child
|
||||
---
|
||||
duration_ms: 0.7034
|
||||
...
|
||||
1..5
|
||||
# tests 5
|
||||
# suites 0
|
||||
# pass 5
|
||||
# fail 0
|
||||
# cancelled 0
|
||||
# skipped 0
|
||||
# todo 0
|
||||
# duration_ms 279.9641
|
||||
TAP version 13
|
||||
# Subtest: canonicalizeWindowsPath normalizes separators and drive casing
|
||||
ok 1 - canonicalizeWindowsPath normalizes separators and drive casing
|
||||
---
|
||||
duration_ms: 0.9528
|
||||
...
|
||||
# Subtest: windowsPathKey is case-insensitive stable key
|
||||
ok 2 - windowsPathKey is case-insensitive stable key
|
||||
---
|
||||
duration_ms: 0.2036
|
||||
...
|
||||
# Subtest: toDisplayPath renders forward slashes for UI readability
|
||||
ok 3 - toDisplayPath renders forward slashes for UI readability
|
||||
---
|
||||
duration_ms: 0.1337
|
||||
...
|
||||
# Subtest: sameWindowsPath handles case/separator differences
|
||||
ok 4 - sameWindowsPath handles case/separator differences
|
||||
---
|
||||
duration_ms: 0.1696
|
||||
...
|
||||
1..4
|
||||
# tests 4
|
||||
# suites 0
|
||||
# pass 4
|
||||
# fail 0
|
||||
# cancelled 0
|
||||
# skipped 0
|
||||
# todo 0
|
||||
# duration_ms 300.62
|
||||
TAP version 13
|
||||
# Subtest: LeftPanel Component Contract
|
||||
# Subtest: exports LeftPanel component
|
||||
ok 1 - exports LeftPanel component
|
||||
---
|
||||
duration_ms: 306.6047
|
||||
...
|
||||
# Subtest: LeftPanel accepts issues and onEpicSelect props
|
||||
ok 2 - LeftPanel accepts issues and onEpicSelect props
|
||||
---
|
||||
duration_ms: 1.3879
|
||||
...
|
||||
1..2
|
||||
ok 1 - LeftPanel Component Contract
|
||||
---
|
||||
duration_ms: 309.0712
|
||||
type: 'suite'
|
||||
...
|
||||
# Subtest: LeftPanel Tree Structure
|
||||
# Subtest: renders epics as expandable tree items
|
||||
ok 1 - renders epics as expandable tree items
|
||||
---
|
||||
duration_ms: 1.345
|
||||
...
|
||||
# Subtest: groups beads under their parent epic
|
||||
ok 2 - groups beads under their parent epic
|
||||
---
|
||||
duration_ms: 1.7164
|
||||
...
|
||||
1..2
|
||||
ok 2 - LeftPanel Tree Structure
|
||||
---
|
||||
duration_ms: 3.332
|
||||
type: 'suite'
|
||||
...
|
||||
# Subtest: LeftPanel Responsive Behavior
|
||||
# Subtest: applies responsive classes for desktop, tablet, and mobile
|
||||
ok 1 - applies responsive classes for desktop, tablet, and mobile
|
||||
---
|
||||
duration_ms: 1.3508
|
||||
...
|
||||
1..1
|
||||
ok 3 - LeftPanel Responsive Behavior
|
||||
---
|
||||
duration_ms: 1.5231
|
||||
type: 'suite'
|
||||
...
|
||||
# Subtest: LeftPanel Scope Controls
|
||||
# Subtest: renders scope section
|
||||
ok 1 - renders scope section
|
||||
---
|
||||
duration_ms: 1.3167
|
||||
...
|
||||
1..1
|
||||
ok 4 - LeftPanel Scope Controls
|
||||
---
|
||||
duration_ms: 1.7059
|
||||
type: 'suite'
|
||||
...
|
||||
1..4
|
||||
# tests 6
|
||||
# suites 4
|
||||
# pass 6
|
||||
# fail 0
|
||||
# cancelled 0
|
||||
# skipped 0
|
||||
# todo 0
|
||||
# duration_ms 598.9805
|
||||
TAP version 13
|
||||
# Subtest: TopBar Component Contract
|
||||
# Subtest: exports TopBar component
|
||||
ok 1 - exports TopBar component
|
||||
---
|
||||
duration_ms: 683.336
|
||||
...
|
||||
# Subtest: TopBar component can be imported without errors
|
||||
ok 2 - TopBar component can be imported without errors
|
||||
---
|
||||
duration_ms: 1.848
|
||||
...
|
||||
1..2
|
||||
ok 1 - TopBar Component Contract
|
||||
---
|
||||
duration_ms: 686.5443
|
||||
type: 'suite'
|
||||
...
|
||||
# Subtest: TopBar View Tabs
|
||||
# Subtest: renders view tabs: Social, Graph
|
||||
ok 1 - renders view tabs: Social, Graph
|
||||
---
|
||||
duration_ms: 1.4361
|
||||
...
|
||||
# Subtest: active tab has bold text and accent underline
|
||||
ok 2 - active tab has bold text and accent underline
|
||||
---
|
||||
duration_ms: 1.6179
|
||||
...
|
||||
1..2
|
||||
ok 2 - TopBar View Tabs
|
||||
---
|
||||
duration_ms: 3.3478
|
||||
type: 'suite'
|
||||
...
|
||||
# Subtest: TopBar Filter and Controls
|
||||
# Subtest: renders filter/search input placeholder
|
||||
ok 1 - renders filter/search input placeholder
|
||||
---
|
||||
duration_ms: 1.7411
|
||||
...
|
||||
# Subtest: renders settings placeholder
|
||||
ok 2 - renders settings placeholder
|
||||
---
|
||||
duration_ms: 1.2955
|
||||
...
|
||||
1..2
|
||||
ok 3 - TopBar Filter and Controls
|
||||
---
|
||||
duration_ms: 3.5576
|
||||
type: 'suite'
|
||||
...
|
||||
1..3
|
||||
# tests 6
|
||||
# suites 3
|
||||
# pass 6
|
||||
# fail 0
|
||||
# cancelled 0
|
||||
# skipped 0
|
||||
# todo 0
|
||||
# duration_ms 991.5175
|
||||
TAP version 13
|
||||
# Subtest: Mobile Navigation - Hamburger Menu
|
||||
# Subtest: exports MobileNav component
|
||||
ok 1 - exports MobileNav component
|
||||
---
|
||||
duration_ms: 160.2862
|
||||
...
|
||||
# Subtest: renders tab buttons: Social, Graph
|
||||
ok 2 - renders tab buttons: Social, Graph
|
||||
---
|
||||
duration_ms: 1.5794
|
||||
...
|
||||
# Subtest: highlights active tab with accent color
|
||||
ok 3 - highlights active tab with accent color
|
||||
---
|
||||
duration_ms: 1.2026
|
||||
...
|
||||
# Subtest: uses setView from useUrlState on tab click
|
||||
ok 4 - uses setView from useUrlState on tab click
|
||||
---
|
||||
duration_ms: 1.1548
|
||||
...
|
||||
1..4
|
||||
ok 1 - Mobile Navigation - Hamburger Menu
|
||||
---
|
||||
duration_ms: 166.2933
|
||||
type: 'suite'
|
||||
...
|
||||
# Subtest: TopBar Hamburger Menu
|
||||
# Subtest: shows hamburger button on mobile and tablet
|
||||
ok 1 - shows hamburger button on mobile and tablet
|
||||
---
|
||||
duration_ms: 520.9119
|
||||
...
|
||||
# Subtest: hamburger button opens left panel drawer
|
||||
ok 2 - hamburger button opens left panel drawer
|
||||
---
|
||||
duration_ms: 1.9043
|
||||
...
|
||||
# Subtest: hides hamburger on desktop
|
||||
ok 3 - hides hamburger on desktop
|
||||
---
|
||||
duration_ms: 1.566
|
||||
...
|
||||
1..3
|
||||
ok 2 - TopBar Hamburger Menu
|
||||
---
|
||||
duration_ms: 525.0916
|
||||
type: 'suite'
|
||||
...
|
||||
1..2
|
||||
# tests 7
|
||||
# suites 2
|
||||
# pass 7
|
||||
# fail 0
|
||||
# cancelled 0
|
||||
# skipped 0
|
||||
# todo 0
|
||||
# duration_ms 1031.056
|
||||
TAP version 13
|
||||
# Subtest: SwarmCard Component Contract
|
||||
# Subtest: exports SwarmCard component
|
||||
ok 1 - exports SwarmCard component
|
||||
---
|
||||
duration_ms: 263.9758
|
||||
...
|
||||
# Subtest: SwarmCard component can be imported without errors
|
||||
ok 2 - SwarmCard component can be imported without errors
|
||||
---
|
||||
duration_ms: 1.4629
|
||||
...
|
||||
1..2
|
||||
ok 1 - SwarmCard Component Contract
|
||||
---
|
||||
duration_ms: 266.6715
|
||||
type: 'suite'
|
||||
...
|
||||
# Subtest: SwarmCard Agent Roster
|
||||
# Subtest: renders agent avatars with liveness glow
|
||||
ok 1 - renders agent avatars with liveness glow
|
||||
---
|
||||
duration_ms: 1.3692
|
||||
...
|
||||
# Subtest: displays agent current task when available
|
||||
ok 2 - displays agent current task when available
|
||||
---
|
||||
duration_ms: 1.5995
|
||||
...
|
||||
1..2
|
||||
ok 2 - SwarmCard Agent Roster
|
||||
---
|
||||
duration_ms: 3.3144
|
||||
type: 'suite'
|
||||
...
|
||||
# Subtest: SwarmCard Progress Bar
|
||||
# Subtest: renders progress bar showing completion percentage
|
||||
ok 1 - renders progress bar showing completion percentage
|
||||
---
|
||||
duration_ms: 1.8139
|
||||
...
|
||||
1..1
|
||||
ok 3 - SwarmCard Progress Bar
|
||||
---
|
||||
duration_ms: 2.0726
|
||||
type: 'suite'
|
||||
...
|
||||
# Subtest: SwarmCard Attention Items
|
||||
# Subtest: renders attention items with warning styling
|
||||
ok 1 - renders attention items with warning styling
|
||||
---
|
||||
duration_ms: 1.8572
|
||||
...
|
||||
1..1
|
||||
ok 4 - SwarmCard Attention Items
|
||||
---
|
||||
duration_ms: 2.3816
|
||||
type: 'suite'
|
||||
...
|
||||
# Subtest: SwarmCard View-Jump Icons
|
||||
# Subtest: renders view-jump icons for navigation
|
||||
ok 1 - renders view-jump icons for navigation
|
||||
---
|
||||
duration_ms: 1.7362
|
||||
...
|
||||
1..1
|
||||
ok 5 - SwarmCard View-Jump Icons
|
||||
---
|
||||
duration_ms: 1.9907
|
||||
type: 'suite'
|
||||
...
|
||||
1..5
|
||||
# tests 7
|
||||
# suites 5
|
||||
# pass 7
|
||||
# fail 0
|
||||
# cancelled 0
|
||||
# skipped 0
|
||||
# todo 0
|
||||
# duration_ms 586.4929
|
||||
TAP version 13
|
||||
# Subtest: URL State Integration - bb-ui2.22
|
||||
# Subtest: Valid URL Patterns - Social View
|
||||
# Subtest: /?view=social - defaults to social view
|
||||
ok 1 - /?view=social - defaults to social view
|
||||
---
|
||||
duration_ms: 0.8523
|
||||
...
|
||||
# Subtest: /?view=social&task=bb-buff.1&panel=open - task selected, panel open
|
||||
ok 2 - /?view=social&task=bb-buff.1&panel=open - task selected, panel open
|
||||
---
|
||||
duration_ms: 0.2088
|
||||
...
|
||||
# Subtest: /?view=social&task=bb-ui2.22 - task with dots in ID
|
||||
ok 3 - /?view=social&task=bb-ui2.22 - task with dots in ID
|
||||
---
|
||||
duration_ms: 0.1511
|
||||
...
|
||||
1..3
|
||||
ok 1 - Valid URL Patterns - Social View
|
||||
---
|
||||
duration_ms: 1.865
|
||||
type: 'suite'
|
||||
...
|
||||
# Subtest: Valid URL Patterns - Graph View
|
||||
# Subtest: /?view=graph - graph view default
|
||||
ok 1 - /?view=graph - graph view default
|
||||
---
|
||||
duration_ms: 0.2128
|
||||
...
|
||||
# Subtest: /?view=graph&task=bb-buff.1 - graph with task selected
|
||||
ok 2 - /?view=graph&task=bb-buff.1 - graph with task selected
|
||||
---
|
||||
duration_ms: 0.1196
|
||||
...
|
||||
# Subtest: /?view=graph&graphTab=flow - flow tab selected
|
||||
ok 3 - /?view=graph&graphTab=flow - flow tab selected
|
||||
---
|
||||
duration_ms: 0.1573
|
||||
...
|
||||
# Subtest: /?view=graph&graphTab=overview - overview tab selected
|
||||
ok 4 - /?view=graph&graphTab=overview - overview tab selected
|
||||
---
|
||||
duration_ms: 0.116
|
||||
...
|
||||
# Subtest: /?view=graph&swarm=bb-buff - graph filtered by swarm
|
||||
ok 5 - /?view=graph&swarm=bb-buff - graph filtered by swarm
|
||||
---
|
||||
duration_ms: 0.2221
|
||||
...
|
||||
1..5
|
||||
ok 2 - Valid URL Patterns - Graph View
|
||||
---
|
||||
duration_ms: 1.1579
|
||||
type: 'suite'
|
||||
...
|
||||
# Subtest: Deprecated Swarm View Fallback
|
||||
# Subtest: /?view=swarm - falls back to social (swarm view deprecated)
|
||||
ok 1 - /?view=swarm - falls back to social (swarm view deprecated)
|
||||
---
|
||||
duration_ms: 0.7522
|
||||
...
|
||||
# Subtest: /?view=swarm&swarm=bb-buff - falls back to social but preserves swarmId
|
||||
ok 2 - /?view=swarm&swarm=bb-buff - falls back to social but preserves swarmId
|
||||
---
|
||||
duration_ms: 0.2523
|
||||
...
|
||||
# Subtest: /?view=swarm&swarm=bb-buff&panel=open - falls back to social with panel open
|
||||
ok 3 - /?view=swarm&swarm=bb-buff&panel=open - falls back to social with panel open
|
||||
---
|
||||
duration_ms: 0.1228
|
||||
...
|
||||
1..3
|
||||
ok 3 - Deprecated Swarm View Fallback
|
||||
---
|
||||
duration_ms: 1.276
|
||||
type: 'suite'
|
||||
...
|
||||
# Subtest: Valid URL Patterns - Activity View
|
||||
# Subtest: /?view=activity - activity view default
|
||||
ok 1 - /?view=activity - activity view default
|
||||
---
|
||||
duration_ms: 0.1366
|
||||
...
|
||||
# Subtest: /?view=activity&agent=bb-silver-castle - filtered by agent
|
||||
ok 2 - /?view=activity&agent=bb-silver-castle - filtered by agent
|
||||
---
|
||||
duration_ms: 0.0823
|
||||
...
|
||||
# Subtest: /?view=activity&swarm=bb-buff - filtered by swarm
|
||||
ok 3 - /?view=activity&swarm=bb-buff - filtered by swarm
|
||||
---
|
||||
duration_ms: 0.0788
|
||||
...
|
||||
1..3
|
||||
ok 4 - Valid URL Patterns - Activity View
|
||||
---
|
||||
duration_ms: 0.4389
|
||||
type: 'suite'
|
||||
...
|
||||
# Subtest: Invalid Param Handling
|
||||
# Subtest: /?view=invalid - invalid view defaults to social
|
||||
ok 1 - /?view=invalid - invalid view defaults to social
|
||||
---
|
||||
duration_ms: 0.1141
|
||||
...
|
||||
# Subtest: /?view=graph&graphTab=invalid - invalid graphTab defaults to flow
|
||||
ok 2 - /?view=graph&graphTab=invalid - invalid graphTab defaults to flow
|
||||
---
|
||||
duration_ms: 0.0807
|
||||
...
|
||||
# Subtest: /?panel=invalid - invalid panel defaults to open
|
||||
ok 3 - /?panel=invalid - invalid panel defaults to open
|
||||
---
|
||||
duration_ms: 0.0801
|
||||
...
|
||||
# Subtest: /?task=invalid-id - invalid task ID still parsed (no validation)
|
||||
ok 4 - /?task=invalid-id - invalid task ID still parsed (no validation)
|
||||
---
|
||||
duration_ms: 0.086
|
||||
...
|
||||
1..4
|
||||
ok 5 - Invalid Param Handling
|
||||
---
|
||||
duration_ms: 0.4767
|
||||
type: 'suite'
|
||||
...
|
||||
# Subtest: URL Building - State to URL
|
||||
# Subtest: builds social view URL
|
||||
ok 1 - builds social view URL
|
||||
---
|
||||
duration_ms: 0.2155
|
||||
...
|
||||
# Subtest: builds graph view with task URL
|
||||
ok 2 - builds graph view with task URL
|
||||
---
|
||||
duration_ms: 0.1448
|
||||
...
|
||||
# Subtest: builds swarm view with swarm param
|
||||
ok 3 - builds swarm view with swarm param
|
||||
---
|
||||
duration_ms: 0.0849
|
||||
...
|
||||
# Subtest: builds activity view with agent filter
|
||||
ok 4 - builds activity view with agent filter
|
||||
---
|
||||
duration_ms: 0.0913
|
||||
...
|
||||
# Subtest: preserves existing params when adding new ones
|
||||
ok 5 - preserves existing params when adding new ones
|
||||
---
|
||||
duration_ms: 0.1507
|
||||
...
|
||||
# Subtest: removes params when set to null
|
||||
ok 6 - removes params when set to null
|
||||
---
|
||||
duration_ms: 0.1207
|
||||
...
|
||||
# Subtest: returns root when all params cleared
|
||||
ok 7 - returns root when all params cleared
|
||||
---
|
||||
duration_ms: 0.0871
|
||||
...
|
||||
1..7
|
||||
ok 6 - URL Building - State to URL
|
||||
---
|
||||
duration_ms: 1.0559
|
||||
type: 'suite'
|
||||
...
|
||||
# Subtest: Complex URL Scenarios
|
||||
# Subtest: handles all params together
|
||||
ok 1 - handles all params together
|
||||
---
|
||||
duration_ms: 0.1183
|
||||
...
|
||||
# Subtest: empty string values treated as null/empty
|
||||
ok 2 - empty string values treated as null/empty
|
||||
---
|
||||
duration_ms: 0.0817
|
||||
...
|
||||
1..2
|
||||
ok 7 - Complex URL Scenarios
|
||||
---
|
||||
duration_ms: 0.2733
|
||||
type: 'suite'
|
||||
...
|
||||
# Subtest: Deep Link Patterns - From Card Icons
|
||||
# Subtest: SocialCard Graph icon: /?view=graph&task={id}
|
||||
ok 1 - SocialCard Graph icon: /?view=graph&task={id}
|
||||
---
|
||||
duration_ms: 0.1285
|
||||
...
|
||||
# Subtest: SwarmCard Graph icon: /?view=graph&swarm={id}
|
||||
ok 2 - SwarmCard Graph icon: /?view=graph&swarm={id}
|
||||
---
|
||||
duration_ms: 0.1297
|
||||
...
|
||||
# Subtest: SwarmCard Timeline icon: /?view=activity&swarm={id}
|
||||
ok 3 - SwarmCard Timeline icon: /?view=activity&swarm={id}
|
||||
---
|
||||
duration_ms: 0.0782
|
||||
...
|
||||
# Subtest: Agent avatar click: /?view=activity&agent={id}
|
||||
ok 4 - Agent avatar click: /?view=activity&agent={id}
|
||||
---
|
||||
duration_ms: 0.0769
|
||||
...
|
||||
1..4
|
||||
ok 8 - Deep Link Patterns - From Card Icons
|
||||
---
|
||||
duration_ms: 0.5198
|
||||
type: 'suite'
|
||||
...
|
||||
1..8
|
||||
ok 1 - URL State Integration - bb-ui2.22
|
||||
---
|
||||
duration_ms: 7.8584
|
||||
type: 'suite'
|
||||
...
|
||||
1..1
|
||||
# tests 31
|
||||
# suites 9
|
||||
# pass 31
|
||||
# fail 0
|
||||
# cancelled 0
|
||||
# skipped 0
|
||||
# todo 0
|
||||
# duration_ms 435.1391
|
||||
TAP version 13
|
||||
# Subtest: useGraphAnalysis - module exports
|
||||
ok 1 - useGraphAnalysis - module exports
|
||||
---
|
||||
duration_ms: 29.8133
|
||||
...
|
||||
# Subtest: useGraphAnalysis underlying logic - graphModel is built correctly
|
||||
ok 2 - useGraphAnalysis underlying logic - graphModel is built correctly
|
||||
---
|
||||
duration_ms: 10.1561
|
||||
...
|
||||
# Subtest: useGraphAnalysis underlying logic - cycleNodeIdSet detects cycles
|
||||
ok 3 - useGraphAnalysis underlying logic - cycleNodeIdSet detects cycles
|
||||
---
|
||||
duration_ms: 0.5465
|
||||
...
|
||||
# Subtest: useGraphAnalysis underlying logic - cycleNodeIdSet empty for acyclic graph
|
||||
ok 4 - useGraphAnalysis underlying logic - cycleNodeIdSet empty for acyclic graph
|
||||
---
|
||||
duration_ms: 0.1687
|
||||
...
|
||||
# Subtest: useGraphAnalysis underlying logic - blockerAnalysis returns blockers
|
||||
ok 5 - useGraphAnalysis underlying logic - blockerAnalysis returns blockers
|
||||
---
|
||||
duration_ms: 0.4643
|
||||
...
|
||||
# Subtest: useGraphAnalysis underlying logic - blockerTooltipMap shows blocker info
|
||||
ok 6 - useGraphAnalysis underlying logic - blockerTooltipMap shows blocker info
|
||||
---
|
||||
duration_ms: 0.3071
|
||||
...
|
||||
1..6
|
||||
# tests 6
|
||||
# suites 0
|
||||
# pass 6
|
||||
# fail 0
|
||||
# cancelled 0
|
||||
# skipped 0
|
||||
# todo 0
|
||||
# duration_ms 559.0462
|
||||
TAP version 13
|
||||
# Subtest: SmartDag - file exists and exports
|
||||
ok 1 - SmartDag - file exists and exports
|
||||
---
|
||||
duration_ms: 4.3779
|
||||
...
|
||||
# Subtest: SmartDag - contains Filters toggle button
|
||||
ok 2 - SmartDag - contains Filters toggle button
|
||||
---
|
||||
duration_ms: 0.949
|
||||
...
|
||||
# Subtest: SmartDag - contains Assign toggle button
|
||||
ok 3 - SmartDag - contains Assign toggle button
|
||||
---
|
||||
duration_ms: 0.7066
|
||||
...
|
||||
# Subtest: SmartDag - contains WorkflowTabs
|
||||
ok 4 - SmartDag - contains WorkflowTabs
|
||||
---
|
||||
duration_ms: 1.1698
|
||||
...
|
||||
# Subtest: SmartDag - supports onAssignModeChange callback
|
||||
ok 5 - SmartDag - supports onAssignModeChange callback
|
||||
---
|
||||
duration_ms: 1.4824
|
||||
...
|
||||
# Subtest: SmartDag - supports onSelectedIssueChange callback
|
||||
ok 6 - SmartDag - supports onSelectedIssueChange callback
|
||||
---
|
||||
duration_ms: 0.8891
|
||||
...
|
||||
# Subtest: SmartDag - imports TaskCardGrid
|
||||
ok 7 - SmartDag - imports TaskCardGrid
|
||||
---
|
||||
duration_ms: 0.93
|
||||
...
|
||||
# Subtest: SmartDag - imports WorkflowGraph
|
||||
ok 8 - SmartDag - imports WorkflowGraph
|
||||
---
|
||||
duration_ms: 0.8032
|
||||
...
|
||||
# Subtest: SmartDag - passes assignMode to WorkflowGraph
|
||||
ok 9 - SmartDag - passes assignMode to WorkflowGraph
|
||||
---
|
||||
duration_ms: 0.9817
|
||||
...
|
||||
# Subtest: SmartDag - manages hideClosed filter
|
||||
ok 10 - SmartDag - manages hideClosed filter
|
||||
---
|
||||
duration_ms: 1.1005
|
||||
...
|
||||
# Subtest: SmartDag - manages sortReadyFirst filter
|
||||
ok 11 - SmartDag - manages sortReadyFirst filter
|
||||
---
|
||||
duration_ms: 0.7155
|
||||
...
|
||||
# Subtest: SmartDag - uses useGraphAnalysis hook
|
||||
ok 12 - SmartDag - uses useGraphAnalysis hook
|
||||
---
|
||||
duration_ms: 0.6575
|
||||
...
|
||||
1..12
|
||||
# tests 12
|
||||
# suites 0
|
||||
# pass 12
|
||||
# fail 0
|
||||
# cancelled 0
|
||||
# skipped 0
|
||||
# todo 0
|
||||
# duration_ms 326.9817
|
||||
TAP version 13
|
||||
# Subtest: UnifiedShell - file exists and exports
|
||||
ok 1 - UnifiedShell - file exists and exports
|
||||
---
|
||||
duration_ms: 4.1613
|
||||
...
|
||||
# Subtest: UnifiedShell - has assignMode state
|
||||
ok 2 - UnifiedShell - has assignMode state
|
||||
---
|
||||
duration_ms: 1.0953
|
||||
...
|
||||
# Subtest: UnifiedShell - has selectedAssignIssue state
|
||||
ok 3 - UnifiedShell - has selectedAssignIssue state
|
||||
---
|
||||
duration_ms: 0.7628
|
||||
...
|
||||
# Subtest: UnifiedShell - passes onAssignModeChange to SmartDag
|
||||
ok 4 - UnifiedShell - passes onAssignModeChange to SmartDag
|
||||
---
|
||||
duration_ms: 0.7559
|
||||
...
|
||||
# Subtest: UnifiedShell - passes onSelectedIssueChange to SmartDag
|
||||
ok 5 - UnifiedShell - passes onSelectedIssueChange to SmartDag
|
||||
---
|
||||
duration_ms: 1.3606
|
||||
...
|
||||
# Subtest: UnifiedShell - imports AssignmentPanel
|
||||
ok 6 - UnifiedShell - imports AssignmentPanel
|
||||
---
|
||||
duration_ms: 0.9392
|
||||
...
|
||||
# Subtest: UnifiedShell - checks bd health and renders setup warning
|
||||
ok 7 - UnifiedShell - checks bd health and renders setup warning
|
||||
---
|
||||
duration_ms: 0.7768
|
||||
...
|
||||
# Subtest: UnifiedShell - renders AssignmentPanel conditionally
|
||||
not ok 8 - UnifiedShell - renders AssignmentPanel conditionally
|
||||
---
|
||||
duration_ms: 1.9496
|
||||
location: 'C:\\Users\\Zenchant\\codex\\beadboard\\tests\\components\\unified-shell.test.tsx:2:3626'
|
||||
failureType: 'testCodeFailure'
|
||||
error: 'Should check view === graph && assignMode condition for AssignmentPanel'
|
||||
code: 'ERR_ASSERTION'
|
||||
name: 'AssertionError'
|
||||
expected: true
|
||||
actual: false
|
||||
operator: '=='
|
||||
stack: |-
|
||||
TestContext.<anonymous> (C:\Users\Zenchant\codex\beadboard\tests\components\unified-shell.test.tsx:53:10)
|
||||
async Test.run (node:internal/test_runner/test:935:9)
|
||||
async Test.processPendingSubtests (node:internal/test_runner/test:633:7)
|
||||
...
|
||||
# Subtest: UnifiedShell - does not import SwarmWorkspace
|
||||
ok 9 - UnifiedShell - does not import SwarmWorkspace
|
||||
---
|
||||
duration_ms: 1.647
|
||||
...
|
||||
# Subtest: UnifiedShell - does not import SwarmMissionPicker
|
||||
ok 10 - UnifiedShell - does not import SwarmMissionPicker
|
||||
---
|
||||
duration_ms: 1.0699
|
||||
...
|
||||
1..10
|
||||
# tests 10
|
||||
# suites 0
|
||||
# pass 9
|
||||
# fail 1
|
||||
# cancelled 0
|
||||
# skipped 0
|
||||
# todo 0
|
||||
# duration_ms 309.2239
|
||||
1395
.beads/npm_test_output3.txt
Normal file
1395
.beads/npm_test_output3.txt
Normal file
File diff suppressed because it is too large
Load diff
3
.beads/task1.txt
Normal file
3
.beads/task1.txt
Normal file
|
|
@ -0,0 +1,3 @@
|
|||
✓ Created issue: beadboard-txj.1 — Implement graph transitive reduction algorithm
|
||||
Priority: P0
|
||||
Status: open
|
||||
3
.beads/task2.txt
Normal file
3
.beads/task2.txt
Normal file
|
|
@ -0,0 +1,3 @@
|
|||
✓ Created issue: beadboard-txj.2 — Apply Status Colors and Transitive Context to Graph Edges
|
||||
Priority: P0
|
||||
Status: open
|
||||
3
.beads/task3.txt
Normal file
3
.beads/task3.txt
Normal file
|
|
@ -0,0 +1,3 @@
|
|||
✓ Created issue: beadboard-txj.3 — Implement Graph Focus (Selection) Interactivity
|
||||
Priority: P1
|
||||
Status: open
|
||||
790
.beads/test_output.txt
Normal file
790
.beads/test_output.txt
Normal file
|
|
@ -0,0 +1,790 @@
|
|||
TAP version 13
|
||||
# Subtest: bootstrap scaffold files exist
|
||||
ok 1 - bootstrap scaffold files exist
|
||||
---
|
||||
duration_ms: 1.7879
|
||||
...
|
||||
# Subtest: package.json has next/react/typescript scripts and deps
|
||||
ok 2 - package.json has next/react/typescript scripts and deps
|
||||
---
|
||||
duration_ms: 0.7269
|
||||
...
|
||||
1..2
|
||||
# tests 2
|
||||
# suites 0
|
||||
# pass 2
|
||||
# fail 0
|
||||
# cancelled 0
|
||||
# skipped 0
|
||||
# todo 0
|
||||
# duration_ms 109.641
|
||||
TAP version 13
|
||||
# Subtest: BaseCard Component Contract
|
||||
# Subtest: exports BaseCard component
|
||||
ok 1 - exports BaseCard component
|
||||
---
|
||||
duration_ms: 49.7712
|
||||
...
|
||||
1..1
|
||||
ok 1 - BaseCard Component Contract
|
||||
---
|
||||
duration_ms: 50.4334
|
||||
type: 'suite'
|
||||
...
|
||||
# Subtest: BaseCard Styling Logic
|
||||
# Subtest: should be possible to import the component
|
||||
ok 1 - should be possible to import the component
|
||||
---
|
||||
duration_ms: 1.6802
|
||||
...
|
||||
# Subtest: applies correct status border class for "ready" status
|
||||
ok 2 - applies correct status border class for "ready" status
|
||||
---
|
||||
duration_ms: 14.5164
|
||||
...
|
||||
# Subtest: applies correct status border class for "blocked" status
|
||||
ok 3 - applies correct status border class for "blocked" status
|
||||
---
|
||||
duration_ms: 5.9515
|
||||
...
|
||||
# Subtest: applies selection ring when selected prop is true
|
||||
ok 4 - applies selection ring when selected prop is true
|
||||
---
|
||||
duration_ms: 2.9283
|
||||
...
|
||||
1..4
|
||||
ok 2 - BaseCard Styling Logic
|
||||
---
|
||||
duration_ms: 25.6463
|
||||
type: 'suite'
|
||||
...
|
||||
1..2
|
||||
# tests 5
|
||||
# suites 2
|
||||
# pass 5
|
||||
# fail 0
|
||||
# cancelled 0
|
||||
# skipped 0
|
||||
# todo 0
|
||||
# duration_ms 387.1692
|
||||
TAP version 13
|
||||
# Subtest: AgentAvatar Component Contract
|
||||
# Subtest: exports AgentAvatar component
|
||||
ok 1 - exports AgentAvatar component
|
||||
---
|
||||
duration_ms: 116.5064
|
||||
...
|
||||
1..1
|
||||
ok 1 - AgentAvatar Component Contract
|
||||
---
|
||||
duration_ms: 117.1492
|
||||
type: 'suite'
|
||||
...
|
||||
# Subtest: AgentAvatar Role Styling
|
||||
# Subtest: applies correct role color class for "ui" role
|
||||
ok 1 - applies correct role color class for "ui" role
|
||||
---
|
||||
duration_ms: 7.4888
|
||||
...
|
||||
# Subtest: applies correct role color class for "orchestrator" role
|
||||
ok 2 - applies correct role color class for "orchestrator" role
|
||||
---
|
||||
duration_ms: 1.8762
|
||||
...
|
||||
1..2
|
||||
ok 2 - AgentAvatar Role Styling
|
||||
---
|
||||
duration_ms: 9.6138
|
||||
type: 'suite'
|
||||
...
|
||||
# Subtest: AgentAvatar ZFC States
|
||||
# Subtest: applies working pulse glow
|
||||
ok 1 - applies working pulse glow
|
||||
---
|
||||
duration_ms: 1.3946
|
||||
...
|
||||
1..1
|
||||
ok 3 - AgentAvatar ZFC States
|
||||
---
|
||||
duration_ms: 1.6685
|
||||
type: 'suite'
|
||||
...
|
||||
1..3
|
||||
# tests 4
|
||||
# suites 3
|
||||
# pass 4
|
||||
# fail 0
|
||||
# cancelled 0
|
||||
# skipped 0
|
||||
# todo 0
|
||||
# duration_ms 435.7079
|
||||
TAP version 13
|
||||
# Subtest: SessionsHeader: Agent Grouping
|
||||
# Subtest: groups agents by swarm
|
||||
ok 1 - groups agents by swarm
|
||||
---
|
||||
duration_ms: 2.0443
|
||||
...
|
||||
# Subtest: shows fallback bucket for unassigned agents
|
||||
ok 2 - shows fallback bucket for unassigned agents
|
||||
---
|
||||
duration_ms: 0.1574
|
||||
...
|
||||
# Subtest: handles empty swarm groups
|
||||
ok 3 - handles empty swarm groups
|
||||
---
|
||||
duration_ms: 0.1261
|
||||
...
|
||||
1..3
|
||||
ok 1 - SessionsHeader: Agent Grouping
|
||||
---
|
||||
duration_ms: 3.2814
|
||||
type: 'suite'
|
||||
...
|
||||
1..1
|
||||
# tests 3
|
||||
# suites 1
|
||||
# pass 3
|
||||
# fail 0
|
||||
# cancelled 0
|
||||
# skipped 0
|
||||
# todo 0
|
||||
# duration_ms 267.9904
|
||||
TAP version 13
|
||||
# Subtest: getAgentRoleColor returns correct color for known roles
|
||||
ok 1 - getAgentRoleColor returns correct color for known roles
|
||||
---
|
||||
duration_ms: 0.7796
|
||||
...
|
||||
# Subtest: getAgentRoleColor returns default for unknown role
|
||||
ok 2 - getAgentRoleColor returns default for unknown role
|
||||
---
|
||||
duration_ms: 0.1221
|
||||
...
|
||||
1..2
|
||||
# tests 2
|
||||
# suites 0
|
||||
# pass 2
|
||||
# fail 0
|
||||
# cancelled 0
|
||||
# skipped 0
|
||||
# todo 0
|
||||
# duration_ms 250.2131
|
||||
TAP version 13
|
||||
# Subtest: parseIssuesJsonl applies defaults and preserves priority 0
|
||||
ok 1 - parseIssuesJsonl applies defaults and preserves priority 0
|
||||
---
|
||||
duration_ms: 1.1101
|
||||
...
|
||||
# Subtest: parseIssuesJsonl skips malformed and blank lines
|
||||
ok 2 - parseIssuesJsonl skips malformed and blank lines
|
||||
---
|
||||
duration_ms: 0.1893
|
||||
...
|
||||
# Subtest: parseIssuesJsonl filters tombstones by default
|
||||
ok 3 - parseIssuesJsonl filters tombstones by default
|
||||
---
|
||||
duration_ms: 0.148
|
||||
...
|
||||
# Subtest: parseIssuesJsonl can include tombstones when requested
|
||||
ok 4 - parseIssuesJsonl can include tombstones when requested
|
||||
---
|
||||
duration_ms: 0.1451
|
||||
...
|
||||
# Subtest: parseIssuesJsonl supports beads dependency schema with depends_on_id and parent-child
|
||||
ok 5 - parseIssuesJsonl supports beads dependency schema with depends_on_id and parent-child
|
||||
---
|
||||
duration_ms: 0.7609
|
||||
...
|
||||
1..5
|
||||
# tests 5
|
||||
# suites 0
|
||||
# pass 5
|
||||
# fail 0
|
||||
# cancelled 0
|
||||
# skipped 0
|
||||
# todo 0
|
||||
# duration_ms 275.8118
|
||||
TAP version 13
|
||||
# Subtest: canonicalizeWindowsPath normalizes separators and drive casing
|
||||
ok 1 - canonicalizeWindowsPath normalizes separators and drive casing
|
||||
---
|
||||
duration_ms: 0.9571
|
||||
...
|
||||
# Subtest: windowsPathKey is case-insensitive stable key
|
||||
ok 2 - windowsPathKey is case-insensitive stable key
|
||||
---
|
||||
duration_ms: 0.2276
|
||||
...
|
||||
# Subtest: toDisplayPath renders forward slashes for UI readability
|
||||
ok 3 - toDisplayPath renders forward slashes for UI readability
|
||||
---
|
||||
duration_ms: 0.1456
|
||||
...
|
||||
# Subtest: sameWindowsPath handles case/separator differences
|
||||
ok 4 - sameWindowsPath handles case/separator differences
|
||||
---
|
||||
duration_ms: 0.1285
|
||||
...
|
||||
1..4
|
||||
# tests 4
|
||||
# suites 0
|
||||
# pass 4
|
||||
# fail 0
|
||||
# cancelled 0
|
||||
# skipped 0
|
||||
# todo 0
|
||||
# duration_ms 257.9372
|
||||
TAP version 13
|
||||
# Subtest: LeftPanel Component Contract
|
||||
# Subtest: exports LeftPanel component
|
||||
ok 1 - exports LeftPanel component
|
||||
---
|
||||
duration_ms: 476.382
|
||||
...
|
||||
# Subtest: LeftPanel accepts issues and onEpicSelect props
|
||||
ok 2 - LeftPanel accepts issues and onEpicSelect props
|
||||
---
|
||||
duration_ms: 2.427
|
||||
...
|
||||
1..2
|
||||
ok 1 - LeftPanel Component Contract
|
||||
---
|
||||
duration_ms: 480.2344
|
||||
type: 'suite'
|
||||
...
|
||||
# Subtest: LeftPanel Tree Structure
|
||||
# Subtest: renders epics as expandable tree items
|
||||
ok 1 - renders epics as expandable tree items
|
||||
---
|
||||
duration_ms: 2.4781
|
||||
...
|
||||
# Subtest: groups beads under their parent epic
|
||||
ok 2 - groups beads under their parent epic
|
||||
---
|
||||
duration_ms: 2.3032
|
||||
...
|
||||
1..2
|
||||
ok 2 - LeftPanel Tree Structure
|
||||
---
|
||||
duration_ms: 5.297
|
||||
type: 'suite'
|
||||
...
|
||||
# Subtest: LeftPanel Responsive Behavior
|
||||
# Subtest: applies responsive classes for desktop, tablet, and mobile
|
||||
ok 1 - applies responsive classes for desktop, tablet, and mobile
|
||||
---
|
||||
duration_ms: 2.5744
|
||||
...
|
||||
1..1
|
||||
ok 3 - LeftPanel Responsive Behavior
|
||||
---
|
||||
duration_ms: 2.8537
|
||||
type: 'suite'
|
||||
...
|
||||
# Subtest: LeftPanel Scope Controls
|
||||
# Subtest: renders scope section
|
||||
ok 1 - renders scope section
|
||||
---
|
||||
duration_ms: 2.4409
|
||||
...
|
||||
1..1
|
||||
ok 4 - LeftPanel Scope Controls
|
||||
---
|
||||
duration_ms: 3.207
|
||||
type: 'suite'
|
||||
...
|
||||
1..4
|
||||
# tests 6
|
||||
# suites 4
|
||||
# pass 6
|
||||
# fail 0
|
||||
# cancelled 0
|
||||
# skipped 0
|
||||
# todo 0
|
||||
# duration_ms 762.0118
|
||||
TAP version 13
|
||||
# Subtest: TopBar Component Contract
|
||||
# Subtest: exports TopBar component
|
||||
ok 1 - exports TopBar component
|
||||
---
|
||||
duration_ms: 928.6733
|
||||
...
|
||||
# Subtest: TopBar component can be imported without errors
|
||||
ok 2 - TopBar component can be imported without errors
|
||||
---
|
||||
duration_ms: 1.5359
|
||||
...
|
||||
1..2
|
||||
ok 1 - TopBar Component Contract
|
||||
---
|
||||
duration_ms: 931.4628
|
||||
type: 'suite'
|
||||
...
|
||||
# Subtest: TopBar View Tabs
|
||||
# Subtest: renders view tabs: Social, Graph
|
||||
ok 1 - renders view tabs: Social, Graph
|
||||
---
|
||||
duration_ms: 2.2099
|
||||
...
|
||||
# Subtest: active tab has bold text and accent underline
|
||||
ok 2 - active tab has bold text and accent underline
|
||||
---
|
||||
duration_ms: 1.9226
|
||||
...
|
||||
1..2
|
||||
ok 2 - TopBar View Tabs
|
||||
---
|
||||
duration_ms: 4.5329
|
||||
type: 'suite'
|
||||
...
|
||||
# Subtest: TopBar Filter and Controls
|
||||
# Subtest: renders filter/search input placeholder
|
||||
ok 1 - renders filter/search input placeholder
|
||||
---
|
||||
duration_ms: 1.6872
|
||||
...
|
||||
# Subtest: renders settings placeholder
|
||||
ok 2 - renders settings placeholder
|
||||
---
|
||||
duration_ms: 1.1945
|
||||
...
|
||||
1..2
|
||||
ok 3 - TopBar Filter and Controls
|
||||
---
|
||||
duration_ms: 3.3144
|
||||
type: 'suite'
|
||||
...
|
||||
1..3
|
||||
# tests 6
|
||||
# suites 3
|
||||
# pass 6
|
||||
# fail 0
|
||||
# cancelled 0
|
||||
# skipped 0
|
||||
# todo 0
|
||||
# duration_ms 1275.1308
|
||||
TAP version 13
|
||||
# Subtest: Mobile Navigation - Hamburger Menu
|
||||
# Subtest: exports MobileNav component
|
||||
ok 1 - exports MobileNav component
|
||||
---
|
||||
duration_ms: 146.0955
|
||||
...
|
||||
# Subtest: renders tab buttons: Social, Graph
|
||||
ok 2 - renders tab buttons: Social, Graph
|
||||
---
|
||||
duration_ms: 2.4626
|
||||
...
|
||||
# Subtest: highlights active tab with accent color
|
||||
ok 3 - highlights active tab with accent color
|
||||
---
|
||||
duration_ms: 2.4243
|
||||
...
|
||||
# Subtest: uses setView from useUrlState on tab click
|
||||
ok 4 - uses setView from useUrlState on tab click
|
||||
---
|
||||
duration_ms: 2.3011
|
||||
...
|
||||
1..4
|
||||
ok 1 - Mobile Navigation - Hamburger Menu
|
||||
---
|
||||
duration_ms: 155.4009
|
||||
type: 'suite'
|
||||
...
|
||||
# Subtest: TopBar Hamburger Menu
|
||||
# Subtest: shows hamburger button on mobile and tablet
|
||||
ok 1 - shows hamburger button on mobile and tablet
|
||||
---
|
||||
duration_ms: 594.7571
|
||||
...
|
||||
# Subtest: hamburger button opens left panel drawer
|
||||
ok 2 - hamburger button opens left panel drawer
|
||||
---
|
||||
duration_ms: 1.5433
|
||||
...
|
||||
# Subtest: hides hamburger on desktop
|
||||
ok 3 - hides hamburger on desktop
|
||||
---
|
||||
duration_ms: 1.3406
|
||||
...
|
||||
1..3
|
||||
ok 2 - TopBar Hamburger Menu
|
||||
---
|
||||
duration_ms: 598.2042
|
||||
type: 'suite'
|
||||
...
|
||||
1..2
|
||||
# tests 7
|
||||
# suites 2
|
||||
# pass 7
|
||||
# fail 0
|
||||
# cancelled 0
|
||||
# skipped 0
|
||||
# todo 0
|
||||
# duration_ms 1074.08
|
||||
TAP version 13
|
||||
# Subtest: SwarmCard Component Contract
|
||||
# Subtest: exports SwarmCard component
|
||||
ok 1 - exports SwarmCard component
|
||||
---
|
||||
duration_ms: 301.3252
|
||||
...
|
||||
# Subtest: SwarmCard component can be imported without errors
|
||||
ok 2 - SwarmCard component can be imported without errors
|
||||
---
|
||||
duration_ms: 1.6098
|
||||
...
|
||||
1..2
|
||||
ok 1 - SwarmCard Component Contract
|
||||
---
|
||||
duration_ms: 304.0952
|
||||
type: 'suite'
|
||||
...
|
||||
# Subtest: SwarmCard Agent Roster
|
||||
# Subtest: renders agent avatars with liveness glow
|
||||
ok 1 - renders agent avatars with liveness glow
|
||||
---
|
||||
duration_ms: 2.012
|
||||
...
|
||||
# Subtest: displays agent current task when available
|
||||
ok 2 - displays agent current task when available
|
||||
---
|
||||
duration_ms: 1.5509
|
||||
...
|
||||
1..2
|
||||
ok 2 - SwarmCard Agent Roster
|
||||
---
|
||||
duration_ms: 3.8907
|
||||
type: 'suite'
|
||||
...
|
||||
# Subtest: SwarmCard Progress Bar
|
||||
# Subtest: renders progress bar showing completion percentage
|
||||
ok 1 - renders progress bar showing completion percentage
|
||||
---
|
||||
duration_ms: 1.4962
|
||||
...
|
||||
1..1
|
||||
ok 3 - SwarmCard Progress Bar
|
||||
---
|
||||
duration_ms: 1.7516
|
||||
type: 'suite'
|
||||
...
|
||||
# Subtest: SwarmCard Attention Items
|
||||
# Subtest: renders attention items with warning styling
|
||||
ok 1 - renders attention items with warning styling
|
||||
---
|
||||
duration_ms: 2.1433
|
||||
...
|
||||
1..1
|
||||
ok 4 - SwarmCard Attention Items
|
||||
---
|
||||
duration_ms: 2.818
|
||||
type: 'suite'
|
||||
...
|
||||
# Subtest: SwarmCard View-Jump Icons
|
||||
# Subtest: renders view-jump icons for navigation
|
||||
ok 1 - renders view-jump icons for navigation
|
||||
---
|
||||
duration_ms: 2.1341
|
||||
...
|
||||
1..1
|
||||
ok 5 - SwarmCard View-Jump Icons
|
||||
---
|
||||
duration_ms: 2.4614
|
||||
type: 'suite'
|
||||
...
|
||||
1..5
|
||||
# tests 7
|
||||
# suites 5
|
||||
# pass 7
|
||||
# fail 0
|
||||
# cancelled 0
|
||||
# skipped 0
|
||||
# todo 0
|
||||
# duration_ms 612.9682
|
||||
TAP version 13
|
||||
# Subtest: URL State Integration - bb-ui2.22
|
||||
# Subtest: Valid URL Patterns - Social View
|
||||
# Subtest: /?view=social - defaults to social view
|
||||
ok 1 - /?view=social - defaults to social view
|
||||
---
|
||||
duration_ms: 0.9839
|
||||
...
|
||||
# Subtest: /?view=social&task=bb-buff.1&panel=open - task selected, panel open
|
||||
ok 2 - /?view=social&task=bb-buff.1&panel=open - task selected, panel open
|
||||
---
|
||||
duration_ms: 0.2403
|
||||
...
|
||||
# Subtest: /?view=social&task=bb-ui2.22 - task with dots in ID
|
||||
ok 3 - /?view=social&task=bb-ui2.22 - task with dots in ID
|
||||
---
|
||||
duration_ms: 0.1425
|
||||
...
|
||||
1..3
|
||||
ok 1 - Valid URL Patterns - Social View
|
||||
---
|
||||
duration_ms: 2.0615
|
||||
type: 'suite'
|
||||
...
|
||||
# Subtest: Valid URL Patterns - Graph View
|
||||
# Subtest: /?view=graph - graph view default
|
||||
not ok 1 - /?view=graph - graph view default
|
||||
---
|
||||
duration_ms: 3.8342
|
||||
location: 'C:\\Users\\Zenchant\\codex\\beadboard\\tests\\hooks\\url-state-integration.test.ts:2:2578'
|
||||
failureType: 'testCodeFailure'
|
||||
error: |-
|
||||
Expected values to be strictly equal:
|
||||
|
||||
'overview' !== 'flow'
|
||||
|
||||
code: 'ERR_ASSERTION'
|
||||
name: 'AssertionError'
|
||||
expected: 'flow'
|
||||
actual: 'overview'
|
||||
operator: 'strictEqual'
|
||||
stack: |-
|
||||
TestContext.<anonymous> (C:\Users\Zenchant\codex\beadboard\tests\hooks\url-state-integration.test.ts:53:14)
|
||||
Test.runInAsyncScope (node:async_hooks:211:14)
|
||||
Test.run (node:internal/test_runner/test:934:25)
|
||||
Test.start (node:internal/test_runner/test:833:17)
|
||||
node:internal/test_runner/test:1318:71
|
||||
node:internal/per_context/primordials:483:82
|
||||
new Promise (<anonymous>)
|
||||
new SafePromise (node:internal/per_context/primordials:451:29)
|
||||
node:internal/per_context/primordials:483:9
|
||||
Array.map (<anonymous>)
|
||||
...
|
||||
# Subtest: /?view=graph&task=bb-buff.1 - graph with task selected
|
||||
ok 2 - /?view=graph&task=bb-buff.1 - graph with task selected
|
||||
---
|
||||
duration_ms: 0.2386
|
||||
...
|
||||
# Subtest: /?view=graph&graphTab=flow - flow tab selected
|
||||
ok 3 - /?view=graph&graphTab=flow - flow tab selected
|
||||
---
|
||||
duration_ms: 0.1616
|
||||
...
|
||||
# Subtest: /?view=graph&graphTab=overview - overview tab selected
|
||||
ok 4 - /?view=graph&graphTab=overview - overview tab selected
|
||||
---
|
||||
duration_ms: 0.1198
|
||||
...
|
||||
# Subtest: /?view=graph&swarm=bb-buff - graph filtered by swarm
|
||||
ok 5 - /?view=graph&swarm=bb-buff - graph filtered by swarm
|
||||
---
|
||||
duration_ms: 0.2708
|
||||
...
|
||||
1..5
|
||||
not ok 2 - Valid URL Patterns - Graph View
|
||||
---
|
||||
duration_ms: 5.0492
|
||||
type: 'suite'
|
||||
location: 'C:\\Users\\Zenchant\\codex\\beadboard\\tests\\hooks\\url-state-integration.test.ts:2:2515'
|
||||
failureType: 'subtestsFailed'
|
||||
error: '1 subtest failed'
|
||||
code: 'ERR_TEST_FAILURE'
|
||||
...
|
||||
# Subtest: Deprecated Swarm View Fallback
|
||||
# Subtest: /?view=swarm - falls back to social (swarm view deprecated)
|
||||
ok 1 - /?view=swarm - falls back to social (swarm view deprecated)
|
||||
---
|
||||
duration_ms: 0.2049
|
||||
...
|
||||
# Subtest: /?view=swarm&swarm=bb-buff - falls back to social but preserves swarmId
|
||||
ok 2 - /?view=swarm&swarm=bb-buff - falls back to social but preserves swarmId
|
||||
---
|
||||
duration_ms: 0.271
|
||||
...
|
||||
# Subtest: /?view=swarm&swarm=bb-buff&panel=open - falls back to social with panel open
|
||||
ok 3 - /?view=swarm&swarm=bb-buff&panel=open - falls back to social with panel open
|
||||
---
|
||||
duration_ms: 0.1949
|
||||
...
|
||||
1..3
|
||||
ok 3 - Deprecated Swarm View Fallback
|
||||
---
|
||||
duration_ms: 0.8363
|
||||
type: 'suite'
|
||||
...
|
||||
# Subtest: Valid URL Patterns - Activity View
|
||||
# Subtest: /?view=activity - activity view default
|
||||
ok 1 - /?view=activity - activity view default
|
||||
---
|
||||
duration_ms: 0.1634
|
||||
...
|
||||
# Subtest: /?view=activity&agent=bb-silver-castle - filtered by agent
|
||||
ok 2 - /?view=activity&agent=bb-silver-castle - filtered by agent
|
||||
---
|
||||
duration_ms: 0.0883
|
||||
...
|
||||
# Subtest: /?view=activity&swarm=bb-buff - filtered by swarm
|
||||
ok 3 - /?view=activity&swarm=bb-buff - filtered by swarm
|
||||
---
|
||||
duration_ms: 0.0828
|
||||
...
|
||||
1..3
|
||||
ok 4 - Valid URL Patterns - Activity View
|
||||
---
|
||||
duration_ms: 0.5275
|
||||
type: 'suite'
|
||||
...
|
||||
# Subtest: Invalid Param Handling
|
||||
# Subtest: /?view=invalid - invalid view defaults to social
|
||||
ok 1 - /?view=invalid - invalid view defaults to social
|
||||
---
|
||||
duration_ms: 0.167
|
||||
...
|
||||
# Subtest: /?view=graph&graphTab=invalid - invalid graphTab defaults to flow
|
||||
not ok 2 - /?view=graph&graphTab=invalid - invalid graphTab defaults to flow
|
||||
---
|
||||
duration_ms: 0.3965
|
||||
location: 'C:\\Users\\Zenchant\\codex\\beadboard\\tests\\hooks\\url-state-integration.test.ts:2:6479'
|
||||
failureType: 'testCodeFailure'
|
||||
error: |-
|
||||
Expected values to be strictly equal:
|
||||
|
||||
'overview' !== 'flow'
|
||||
|
||||
code: 'ERR_ASSERTION'
|
||||
name: 'AssertionError'
|
||||
expected: 'flow'
|
||||
actual: 'overview'
|
||||
operator: 'strictEqual'
|
||||
stack: |-
|
||||
TestContext.<anonymous> (C:\Users\Zenchant\codex\beadboard\tests\hooks\url-state-integration.test.ts:138:14)
|
||||
Test.runInAsyncScope (node:async_hooks:211:14)
|
||||
Test.run (node:internal/test_runner/test:934:25)
|
||||
Suite.processPendingSubtests (node:internal/test_runner/test:633:18)
|
||||
Test.postRun (node:internal/test_runner/test:1045:19)
|
||||
Test.run (node:internal/test_runner/test:973:12)
|
||||
async Promise.all (index 0)
|
||||
async Suite.run (node:internal/test_runner/test:1320:7)
|
||||
async Suite.processPendingSubtests (node:internal/test_runner/test:633:7)
|
||||
...
|
||||
# Subtest: /?panel=invalid - invalid panel defaults to open
|
||||
ok 3 - /?panel=invalid - invalid panel defaults to open
|
||||
---
|
||||
duration_ms: 0.1068
|
||||
...
|
||||
# Subtest: /?task=invalid-id - invalid task ID still parsed (no validation)
|
||||
ok 4 - /?task=invalid-id - invalid task ID still parsed (no validation)
|
||||
---
|
||||
duration_ms: 0.0904
|
||||
...
|
||||
1..4
|
||||
not ok 5 - Invalid Param Handling
|
||||
---
|
||||
duration_ms: 0.9102
|
||||
type: 'suite'
|
||||
location: 'C:\\Users\\Zenchant\\codex\\beadboard\\tests\\hooks\\url-state-integration.test.ts:2:6178'
|
||||
failureType: 'subtestsFailed'
|
||||
error: '1 subtest failed'
|
||||
code: 'ERR_TEST_FAILURE'
|
||||
...
|
||||
# Subtest: URL Building - State to URL
|
||||
# Subtest: builds social view URL
|
||||
ok 1 - builds social view URL
|
||||
---
|
||||
duration_ms: 0.2367
|
||||
...
|
||||
# Subtest: builds graph view with task URL
|
||||
ok 2 - builds graph view with task URL
|
||||
---
|
||||
duration_ms: 0.0983
|
||||
...
|
||||
# Subtest: builds swarm view with swarm param
|
||||
ok 3 - builds swarm view with swarm param
|
||||
---
|
||||
duration_ms: 0.0888
|
||||
...
|
||||
# Subtest: builds activity view with agent filter
|
||||
ok 4 - builds activity view with agent filter
|
||||
---
|
||||
duration_ms: 0.159
|
||||
...
|
||||
# Subtest: preserves existing params when adding new ones
|
||||
ok 5 - preserves existing params when adding new ones
|
||||
---
|
||||
duration_ms: 0.1957
|
||||
...
|
||||
# Subtest: removes params when set to null
|
||||
ok 6 - removes params when set to null
|
||||
---
|
||||
duration_ms: 0.1242
|
||||
...
|
||||
# Subtest: returns root when all params cleared
|
||||
ok 7 - returns root when all params cleared
|
||||
---
|
||||
duration_ms: 0.0988
|
||||
...
|
||||
1..7
|
||||
ok 6 - URL Building - State to URL
|
||||
---
|
||||
duration_ms: 1.1817
|
||||
type: 'suite'
|
||||
...
|
||||
# Subtest: Complex URL Scenarios
|
||||
# Subtest: handles all params together
|
||||
ok 1 - handles all params together
|
||||
---
|
||||
duration_ms: 0.1361
|
||||
...
|
||||
# Subtest: empty string values treated as null/empty
|
||||
ok 2 - empty string values treated as null/empty
|
||||
---
|
||||
duration_ms: 0.0964
|
||||
...
|
||||
1..2
|
||||
ok 7 - Complex URL Scenarios
|
||||
---
|
||||
duration_ms: 0.317
|
||||
type: 'suite'
|
||||
...
|
||||
# Subtest: Deep Link Patterns - From Card Icons
|
||||
# Subtest: SocialCard Graph icon: /?view=graph&task={id}
|
||||
ok 1 - SocialCard Graph icon: /?view=graph&task={id}
|
||||
---
|
||||
duration_ms: 0.1474
|
||||
...
|
||||
# Subtest: SwarmCard Graph icon: /?view=graph&swarm={id}
|
||||
ok 2 - SwarmCard Graph icon: /?view=graph&swarm={id}
|
||||
---
|
||||
duration_ms: 0.086
|
||||
...
|
||||
# Subtest: SwarmCard Timeline icon: /?view=activity&swarm={id}
|
||||
ok 3 - SwarmCard Timeline icon: /?view=activity&swarm={id}
|
||||
---
|
||||
duration_ms: 0.2482
|
||||
...
|
||||
# Subtest: Agent avatar click: /?view=activity&agent={id}
|
||||
ok 4 - Agent avatar click: /?view=activity&agent={id}
|
||||
---
|
||||
duration_ms: 0.1616
|
||||
...
|
||||
1..4
|
||||
ok 8 - Deep Link Patterns - From Card Icons
|
||||
---
|
||||
duration_ms: 0.8134
|
||||
type: 'suite'
|
||||
...
|
||||
1..8
|
||||
not ok 1 - URL State Integration - bb-ui2.22
|
||||
---
|
||||
duration_ms: 12.6296
|
||||
type: 'suite'
|
||||
location: 'C:\\Users\\Zenchant\\codex\\beadboard\\tests\\hooks\\url-state-integration.test.ts:2:1269'
|
||||
failureType: 'subtestsFailed'
|
||||
error: '2 subtests failed'
|
||||
code: 'ERR_TEST_FAILURE'
|
||||
...
|
||||
1..1
|
||||
# tests 31
|
||||
# suites 9
|
||||
# pass 29
|
||||
# fail 2
|
||||
# cancelled 0
|
||||
# skipped 0
|
||||
# todo 0
|
||||
# duration_ms 481.6532
|
||||
1
.claude/skills/shadcn-ui
Symbolic link
1
.claude/skills/shadcn-ui
Symbolic link
|
|
@ -0,0 +1 @@
|
|||
/mnt/c/Users/Zenchant/codex/beadboard/.agents/skills/shadcn-ui/
|
||||
File diff suppressed because it is too large
Load diff
|
|
@ -1,306 +0,0 @@
|
|||
### shadcn/ui Chart Component - Installation
|
||||
|
||||
Source: https://ui.shadcn.com/docs/components/chart
|
||||
|
||||
The chart component in shadcn/ui is built on Recharts, providing direct access to all Recharts capabilities with consistent theming.
|
||||
|
||||
```bash
|
||||
npx shadcn@latest add chart
|
||||
```
|
||||
|
||||
--------------------------------
|
||||
|
||||
### shadcn/ui Chart Component - Basic Usage
|
||||
|
||||
Source: https://ui.shadcn.com/docs/components/chart
|
||||
|
||||
The ChartContainer wraps your Recharts component and accepts a config prop for theming. Requires `min-h-[value]` for responsiveness.
|
||||
|
||||
```tsx
|
||||
import { Bar, BarChart, CartesianGrid, XAxis, YAxis } from "recharts"
|
||||
import { ChartContainer, ChartTooltipContent } from "@/components/ui/chart"
|
||||
|
||||
const chartConfig = {
|
||||
desktop: {
|
||||
label: "Desktop",
|
||||
color: "var(--chart-1)",
|
||||
},
|
||||
mobile: {
|
||||
label: "Mobile",
|
||||
color: "var(--chart-2)",
|
||||
},
|
||||
} satisfies import("@/components/ui/chart").ChartConfig
|
||||
|
||||
const chartData = [
|
||||
{ month: "January", desktop: 186, mobile: 80 },
|
||||
{ month: "February", desktop: 305, mobile: 200 },
|
||||
{ month: "March", desktop: 237, mobile: 120 },
|
||||
]
|
||||
|
||||
export function BarChartDemo() {
|
||||
return (
|
||||
<ChartContainer config={chartConfig} className="min-h-[200px] w-full">
|
||||
<BarChart data={chartData}>
|
||||
<CartesianGrid vertical={false} />
|
||||
<XAxis dataKey="month" tickLine={false} axisLine={false} />
|
||||
<Bar dataKey="desktop" fill="var(--color-desktop)" radius={4} />
|
||||
<Bar dataKey="mobile" fill="var(--color-mobile)" radius={4} />
|
||||
<ChartTooltip content={<ChartTooltipContent />} />
|
||||
</BarChart>
|
||||
</ChartContainer>
|
||||
)
|
||||
}
|
||||
```
|
||||
|
||||
--------------------------------
|
||||
|
||||
### shadcn/ui Chart Component - ChartConfig with Custom Colors
|
||||
|
||||
Source: https://ui.shadcn.com/docs/components/chart
|
||||
|
||||
You can define custom colors directly in the configuration using hex values or CSS variables.
|
||||
|
||||
```tsx
|
||||
const chartConfig = {
|
||||
desktop: {
|
||||
label: "Desktop",
|
||||
color: "#2563eb",
|
||||
theme: {
|
||||
light: "#2563eb",
|
||||
dark: "#60a5fa",
|
||||
},
|
||||
},
|
||||
mobile: {
|
||||
label: "Mobile",
|
||||
color: "var(--chart-2)",
|
||||
},
|
||||
} satisfies import("@/components/ui/chart").ChartConfig
|
||||
```
|
||||
|
||||
--------------------------------
|
||||
|
||||
### shadcn/ui Chart Component - CSS Variables
|
||||
|
||||
Source: https://ui.shadcn.com/docs/components/chart
|
||||
|
||||
Add chart color variables to your globals.css for consistent theming.
|
||||
|
||||
```css
|
||||
:root {
|
||||
/* Chart colors */
|
||||
--chart-1: oklch(0.646 0.222 41.116);
|
||||
--chart-2: oklch(0.6 0.118 184.704);
|
||||
--chart-3: oklch(0.546 0.198 38.228);
|
||||
--chart-4: oklch(0.596 0.151 343.253);
|
||||
--chart-5: oklch(0.546 0.158 49.157);
|
||||
}
|
||||
|
||||
.dark {
|
||||
--chart-1: oklch(0.488 0.243 264.376);
|
||||
--chart-2: oklch(0.696 0.17 162.48);
|
||||
--chart-3: oklch(0.698 0.141 24.311);
|
||||
--chart-4: oklch(0.676 0.172 171.196);
|
||||
--chart-5: oklch(0.578 0.192 302.85);
|
||||
}
|
||||
```
|
||||
|
||||
--------------------------------
|
||||
|
||||
### shadcn/ui Chart Component - Line Chart Example
|
||||
|
||||
Source: https://ui.shadcn.com/docs/components/chart
|
||||
|
||||
Creating a line chart with shadcn/ui charts component.
|
||||
|
||||
```tsx
|
||||
import { Line, LineChart, CartesianGrid, XAxis, YAxis } from "recharts"
|
||||
import { ChartContainer, ChartTooltipContent } from "@/components/ui/chart"
|
||||
|
||||
const chartConfig = {
|
||||
price: {
|
||||
label: "Price",
|
||||
color: "var(--chart-1)",
|
||||
},
|
||||
} satisfies import("@/components/ui/chart").ChartConfig
|
||||
|
||||
const chartData = [
|
||||
{ month: "January", price: 186 },
|
||||
{ month: "February", price: 305 },
|
||||
{ month: "March", price: 237 },
|
||||
{ month: "April", price: 203 },
|
||||
{ month: "May", price: 276 },
|
||||
]
|
||||
|
||||
export function LineChartDemo() {
|
||||
return (
|
||||
<ChartContainer config={chartConfig} className="min-h-[200px]">
|
||||
<LineChart data={chartData}>
|
||||
<CartesianGrid vertical={false} />
|
||||
<XAxis dataKey="month" tickLine={false} axisLine={false} />
|
||||
<YAxis tickLine={false} axisLine={false} tickFormatter={(value) => `$${value}`} />
|
||||
<Line
|
||||
dataKey="price"
|
||||
stroke="var(--color-price)"
|
||||
strokeWidth={2}
|
||||
dot={false}
|
||||
/>
|
||||
<ChartTooltip content={<ChartTooltipContent />} />
|
||||
</LineChart>
|
||||
</ChartContainer>
|
||||
)
|
||||
}
|
||||
```
|
||||
|
||||
--------------------------------
|
||||
|
||||
### shadcn/ui Chart Component - Area Chart Example
|
||||
|
||||
Source: https://ui.shadcn.com/docs/components/chart
|
||||
|
||||
Creating an area chart with gradient fill and legend.
|
||||
|
||||
```tsx
|
||||
import { Area, AreaChart, XAxis, YAxis } from "recharts"
|
||||
import {
|
||||
ChartContainer,
|
||||
ChartLegend,
|
||||
ChartLegendContent,
|
||||
ChartTooltipContent,
|
||||
} from "@/components/ui/chart"
|
||||
|
||||
const chartConfig = {
|
||||
desktop: { label: "Desktop", color: "var(--chart-1)" },
|
||||
mobile: { label: "Mobile", color: "var(--chart-2)" },
|
||||
} satisfies import("@/components/ui/chart").ChartConfig
|
||||
|
||||
export function AreaChartDemo() {
|
||||
return (
|
||||
<ChartContainer config={chartConfig} className="min-h-[200px]">
|
||||
<AreaChart data={chartData}>
|
||||
<XAxis dataKey="month" tickLine={false} axisLine={false} />
|
||||
<YAxis tickLine={false} axisLine={false} />
|
||||
<Area
|
||||
dataKey="desktop"
|
||||
fill="var(--color-desktop)"
|
||||
stroke="var(--color-desktop)"
|
||||
fillOpacity={0.3}
|
||||
/>
|
||||
<Area
|
||||
dataKey="mobile"
|
||||
fill="var(--color-mobile)"
|
||||
stroke="var(--color-mobile)"
|
||||
fillOpacity={0.3}
|
||||
/>
|
||||
<ChartTooltip content={<ChartTooltipContent />} />
|
||||
<ChartLegend content={<ChartLegendContent />} />
|
||||
</AreaChart>
|
||||
</ChartContainer>
|
||||
)
|
||||
}
|
||||
```
|
||||
|
||||
--------------------------------
|
||||
|
||||
### shadcn/ui Chart Component - Pie Chart Example
|
||||
|
||||
Source: https://ui.shadcn.com/docs/components/chart
|
||||
|
||||
Creating a pie/donut chart with shadcn/ui.
|
||||
|
||||
```tsx
|
||||
import { Pie, PieChart } from "recharts"
|
||||
import {
|
||||
ChartContainer,
|
||||
ChartLegend,
|
||||
ChartLegendContent,
|
||||
ChartTooltipContent,
|
||||
} from "@/components/ui/chart"
|
||||
|
||||
const chartConfig = {
|
||||
chrome: { label: "Chrome", color: "var(--chart-1)" },
|
||||
safari: { label: "Safari", color: "var(--chart-2)" },
|
||||
firefox: { label: "Firefox", color: "var(--chart-3)" },
|
||||
} satisfies import("@/components/ui/chart").ChartConfig
|
||||
|
||||
const pieData = [
|
||||
{ browser: "Chrome", visitors: 275, fill: "var(--color-chrome)" },
|
||||
{ browser: "Safari", visitors: 200, fill: "var(--color-safari)" },
|
||||
{ browser: "Firefox", visitors: 187, fill: "var(--color-firefox)" },
|
||||
]
|
||||
|
||||
export function PieChartDemo() {
|
||||
return (
|
||||
<ChartContainer config={chartConfig} className="min-h-[200px]">
|
||||
<PieChart>
|
||||
<Pie
|
||||
data={pieData}
|
||||
dataKey="visitors"
|
||||
nameKey="browser"
|
||||
cx="50%"
|
||||
cy="50%"
|
||||
outerRadius={80}
|
||||
/>
|
||||
<ChartTooltip content={<ChartTooltipContent />} />
|
||||
<ChartLegend content={<ChartLegendContent />} />
|
||||
</PieChart>
|
||||
</ChartContainer>
|
||||
)
|
||||
}
|
||||
```
|
||||
|
||||
--------------------------------
|
||||
|
||||
### shadcn/ui ChartTooltipContent Props
|
||||
|
||||
Source: https://ui.shadcn.com/docs/components/chart
|
||||
|
||||
The ChartTooltipContent component accepts these props for customizing tooltip behavior.
|
||||
|
||||
| Prop | Type | Default | Description |
|
||||
|------|------|---------|-------------|
|
||||
| `labelKey` | string | "label" | Key for tooltip label |
|
||||
| `nameKey` | string | "name" | Key for tooltip name |
|
||||
| `indicator` | "dot" \| "line" \| "dashed" | "dot" | Indicator style |
|
||||
| `hideLabel` | boolean | false | Hide label |
|
||||
| `hideIndicator` | boolean | false | Hide indicator |
|
||||
|
||||
--------------------------------
|
||||
|
||||
### shadcn/ui Chart Component - Accessibility
|
||||
|
||||
Source: https://ui.shadcn.com/docs/components/chart
|
||||
|
||||
Enable keyboard navigation and screen reader support by adding the accessibilityLayer prop.
|
||||
|
||||
```tsx
|
||||
<BarChart accessibilityLayer data={chartData}>
|
||||
<CartesianGrid vertical={false} />
|
||||
<XAxis dataKey="month" />
|
||||
<Bar dataKey="desktop" fill="var(--color-desktop)" />
|
||||
<ChartTooltip content={<ChartTooltipContent />} />
|
||||
</BarChart>
|
||||
```
|
||||
|
||||
This adds:
|
||||
- Keyboard arrow key navigation
|
||||
- ARIA labels for chart elements
|
||||
- Screen reader announcements for data values
|
||||
|
||||
--------------------------------
|
||||
|
||||
### shadcn/ui Chart Component - Recharts Dependencies
|
||||
|
||||
Source: https://ui.shadcn.com/docs/components/chart
|
||||
|
||||
The chart component requires the following Recharts dependencies to be installed.
|
||||
|
||||
```bash
|
||||
pnpm add recharts
|
||||
npm install recharts
|
||||
yarn add recharts
|
||||
```
|
||||
|
||||
Recharts provides the following chart types:
|
||||
- Area, Bar, Line, Pie, Composed
|
||||
- Radar, RadialBar, Scatter
|
||||
- Funnel, Treemap
|
||||
|
|
@ -1,145 +0,0 @@
|
|||
# shadcn/ui Learning Guide
|
||||
|
||||
This guide helps you learn shadcn/ui from basics to advanced patterns.
|
||||
|
||||
## Learning Path
|
||||
|
||||
### 1. Understanding the Philosophy
|
||||
|
||||
shadcn/ui is different from traditional component libraries:
|
||||
|
||||
- **Copy-paste components**: Components are copied into your project, not installed as packages
|
||||
- **Full customization**: You own the code and can modify it freely
|
||||
- **Built on Radix UI**: Provides accessibility primitives
|
||||
- **Styled with Tailwind**: Uses utility classes for consistent styling
|
||||
|
||||
### 2. Core Concepts to Master
|
||||
|
||||
#### Class Variance Authority (CVA)
|
||||
Most components use CVA for variant management:
|
||||
|
||||
```tsx
|
||||
const buttonVariants = cva(
|
||||
"base-classes",
|
||||
{
|
||||
variants: {
|
||||
variant: {
|
||||
default: "variant-classes",
|
||||
destructive: "destructive-classes",
|
||||
},
|
||||
size: {
|
||||
default: "size-classes",
|
||||
sm: "small-classes",
|
||||
},
|
||||
},
|
||||
defaultVariants: {
|
||||
variant: "default",
|
||||
size: "default",
|
||||
},
|
||||
}
|
||||
)
|
||||
```
|
||||
|
||||
#### cn Utility Function
|
||||
The `cn` function combines classes and resolves conflicts:
|
||||
|
||||
```tsx
|
||||
import { clsx, type ClassValue } from "clsx"
|
||||
import { twMerge } from "tailwind-merge"
|
||||
|
||||
export function cn(...inputs: ClassValue[]) {
|
||||
return twMerge(clsx(inputs))
|
||||
}
|
||||
```
|
||||
|
||||
### 3. Installation Checklist
|
||||
|
||||
- [ ] Initialize a new project (Next.js, Vite, or Remix)
|
||||
- [ ] Install Tailwind CSS
|
||||
- [ ] Run `npx shadcn@latest init`
|
||||
- [ ] Configure CSS variables
|
||||
- [ ] Install first component: `npx shadcn@latest add button`
|
||||
|
||||
### 4. Essential Components to Learn First
|
||||
|
||||
1. **Button** - Learn variants and sizes
|
||||
2. **Input** - Form inputs with labels
|
||||
3. **Card** - Container components
|
||||
4. **Form** - Form handling with React Hook Form
|
||||
5. **Dialog** - Modal windows
|
||||
6. **Select** - Dropdown selections
|
||||
7. **Toast** - Notifications
|
||||
|
||||
### 5. Common Patterns
|
||||
|
||||
#### Form Pattern
|
||||
Every form follows this structure:
|
||||
|
||||
```tsx
|
||||
1. Define Zod schema
|
||||
2. Create form with useForm
|
||||
3. Wrap with Form component
|
||||
4. Add FormField for each input
|
||||
5. Handle submission
|
||||
```
|
||||
|
||||
#### Component Customization Pattern
|
||||
To customize a component:
|
||||
|
||||
1. Copy component to your project
|
||||
2. Modify the variants
|
||||
3. Add new props if needed
|
||||
4. Update types
|
||||
|
||||
### 6. Best Practices
|
||||
|
||||
- Always use TypeScript
|
||||
- Follow the existing component structure
|
||||
- Use semantic HTML when possible
|
||||
- Test with screen readers for accessibility
|
||||
- Keep components small and focused
|
||||
|
||||
### 7. Advanced Topics
|
||||
|
||||
- Creating custom components from scratch
|
||||
- Building complex forms with validation
|
||||
- Implementing dark mode
|
||||
- Optimizing for performance
|
||||
- Testing components
|
||||
|
||||
## Practice Exercises
|
||||
|
||||
### Exercise 1: Basic Setup
|
||||
1. Create a new Next.js project
|
||||
2. Set up shadcn/ui
|
||||
3. Install and customize a Button component
|
||||
4. Add a new variant "gradient"
|
||||
|
||||
### Exercise 2: Form Building
|
||||
1. Create a contact form with:
|
||||
- Name input (required)
|
||||
- Email input (email validation)
|
||||
- Message textarea (min length)
|
||||
- Submit button with loading state
|
||||
|
||||
### Exercise 3: Component Combination
|
||||
1. Build a settings page using:
|
||||
- Card for layout
|
||||
- Sheet for mobile menu
|
||||
- Select for dropdowns
|
||||
- Switch for toggles
|
||||
- Toast for notifications
|
||||
|
||||
### Exercise 4: Custom Component
|
||||
1. Create a custom Badge component
|
||||
2. Support variants: default, secondary, destructive, outline
|
||||
3. Support sizes: sm, default, lg
|
||||
4. Add icon support
|
||||
|
||||
## Resources
|
||||
|
||||
- [Official Documentation](https://ui.shadcn.com)
|
||||
- [GitHub Repository](https://github.com/shadcn/ui)
|
||||
- [Examples Gallery](https://ui.shadcn.com/examples)
|
||||
- [Radix UI Primitives](https://www.radix-ui.com/primitives)
|
||||
- [Tailwind CSS Documentation](https://tailwindcss.com/docs)
|
||||
File diff suppressed because it is too large
Load diff
|
|
@ -1,586 +0,0 @@
|
|||
# shadcn.io Component Library
|
||||
|
||||
shadcn.io is a comprehensive React UI component library built on shadcn/ui principles, providing developers with production-ready, composable components for modern web applications. The library serves as a centralized resource for React developers who need high-quality UI components with TypeScript support, ranging from basic interactive elements to advanced AI-powered integrations. Unlike traditional component libraries that require package installations, shadcn.io components are designed to be copied directly into your project, giving you full control and customization capabilities.
|
||||
|
||||
The library encompasses four major categories: composable UI components (terminal, dock, credit cards, QR codes, color pickers), chart components built with Recharts, animation components with Tailwind CSS integration, and custom React hooks for state management and lifecycle operations. Each component follows best practices for accessibility, performance, and developer experience, with comprehensive TypeScript definitions and Next.js compatibility. The platform emphasizes flexibility and customization, allowing developers to modify components at the source level rather than being constrained by package APIs.
|
||||
|
||||
## Core Components
|
||||
|
||||
### Terminal Component
|
||||
Interactive terminal emulator with typing animations and command execution simulation for developer-focused interfaces.
|
||||
|
||||
```tsx
|
||||
import { Terminal } from "@/components/ui/terminal"
|
||||
|
||||
export default function DemoTerminal() {
|
||||
return (
|
||||
npm install @repo/terminalInstalling dependencies...npm start
|
||||
)
|
||||
}
|
||||
```
|
||||
|
||||
### Dock Component
|
||||
macOS-style application dock with smooth magnification effects on hover, perfect for navigation menus.
|
||||
|
||||
```tsx
|
||||
import { Dock, DockIcon } from "@/components/ui/dock"
|
||||
import { Home, Settings, User, Mail } from "lucide-react"
|
||||
|
||||
export default function AppDock() {
|
||||
return (
|
||||
|
||||
)
|
||||
}
|
||||
```
|
||||
|
||||
### Credit Card Component
|
||||
Interactive 3D credit card component with flip animations for payment forms and card displays.
|
||||
|
||||
```tsx
|
||||
import { CreditCard } from "@/components/ui/credit-card"
|
||||
import { useState } from "react"
|
||||
|
||||
export default function PaymentForm() {
|
||||
const [cardData, setCardData] = useState({
|
||||
number: "4532 1234 5678 9010",
|
||||
holder: "JOHN DOE",
|
||||
expiry: "12/28",
|
||||
cvv: "123"
|
||||
})
|
||||
|
||||
return (
|
||||
console.log("Card flipped:", flipped)}
|
||||
/>
|
||||
)
|
||||
}
|
||||
```
|
||||
|
||||
### Image Zoom Component
|
||||
Zoomable image component with smooth modal transitions for image galleries and product displays.
|
||||
|
||||
```tsx
|
||||
import { ImageZoom } from "@/components/ui/image-zoom"
|
||||
|
||||
export default function ProductGallery() {
|
||||
return (
|
||||
|
||||
|
||||
)
|
||||
}
|
||||
```
|
||||
|
||||
### QR Code Component
|
||||
Generate and display customizable QR codes with styling options for links, contact information, and authentication.
|
||||
|
||||
```tsx
|
||||
import { QRCode } from "@/components/ui/qr-code"
|
||||
|
||||
export default function ShareDialog() {
|
||||
const shareUrl = "https://shadcn.io"
|
||||
|
||||
return (
|
||||
|
||||
|
||||
Scan to visit shadcn.io
|
||||
|
||||
|
||||
)
|
||||
}
|
||||
```
|
||||
|
||||
### Color Picker Component
|
||||
Advanced color selection component supporting multiple color formats (HEX, RGB, HSL) with preview.
|
||||
|
||||
```tsx
|
||||
import { ColorPicker } from "@/components/ui/color-picker"
|
||||
import { useState } from "react"
|
||||
|
||||
export default function ThemeCustomizer() {
|
||||
const [color, setColor] = useState("#3b82f6")
|
||||
|
||||
return (
|
||||
|
||||
|
||||
Selected: {color}
|
||||
|
||||
)
|
||||
}
|
||||
```
|
||||
|
||||
## Chart Components
|
||||
|
||||
### Bar Chart Component
|
||||
Clean bar chart component for data comparison and categorical analysis using Recharts.
|
||||
|
||||
```tsx
|
||||
import { BarChart } from "@/components/ui/bar-chart"
|
||||
|
||||
export default function SalesChart() {
|
||||
const data = [
|
||||
{ month: "Jan", sales: 4000, revenue: 2400 },
|
||||
{ month: "Feb", sales: 3000, revenue: 1398 },
|
||||
{ month: "Mar", sales: 2000, revenue: 9800 },
|
||||
{ month: "Apr", sales: 2780, revenue: 3908 },
|
||||
{ month: "May", sales: 1890, revenue: 4800 },
|
||||
{ month: "Jun", sales: 2390, revenue: 3800 }
|
||||
]
|
||||
|
||||
return (
|
||||
`$${value.toLocaleString()}`}
|
||||
yAxisWidth={60}
|
||||
/>
|
||||
)
|
||||
}
|
||||
```
|
||||
|
||||
### Line Chart Component
|
||||
Smooth line chart for visualizing trends and time-series data with multiple data series support.
|
||||
|
||||
```tsx
|
||||
import { LineChart } from "@/components/ui/line-chart"
|
||||
|
||||
export default function MetricsChart() {
|
||||
const data = [
|
||||
{ date: "2024-01", users: 1200, sessions: 3400 },
|
||||
{ date: "2024-02", users: 1800, sessions: 4200 },
|
||||
{ date: "2024-03", users: 2400, sessions: 5800 },
|
||||
{ date: "2024-04", users: 3100, sessions: 7200 },
|
||||
{ date: "2024-05", users: 3800, sessions: 8900 }
|
||||
]
|
||||
|
||||
return (
|
||||
|
||||
)
|
||||
}
|
||||
```
|
||||
|
||||
### Pie Chart Component
|
||||
Donut chart component for displaying proportional data and percentage distributions.
|
||||
|
||||
```tsx
|
||||
import { PieChart } from "@/components/ui/pie-chart"
|
||||
|
||||
export default function MarketShareChart() {
|
||||
const data = [
|
||||
{ name: "Product A", value: 400, fill: "#3b82f6" },
|
||||
{ name: "Product B", value: 300, fill: "#10b981" },
|
||||
{ name: "Product C", value: 300, fill: "#f59e0b" },
|
||||
{ name: "Product D", value: 200, fill: "#ef4444" }
|
||||
]
|
||||
|
||||
return (
|
||||
`${entry.name}: ${entry.value}`}
|
||||
/>
|
||||
)
|
||||
}
|
||||
```
|
||||
|
||||
### Area Chart Component
|
||||
Stacked area chart for visualizing volume changes over time with multiple data series.
|
||||
|
||||
```tsx
|
||||
import { AreaChart } from "@/components/ui/area-chart"
|
||||
|
||||
export default function TrafficChart() {
|
||||
const data = [
|
||||
{ month: "Jan", mobile: 2000, desktop: 3000, tablet: 1000 },
|
||||
{ month: "Feb", mobile: 2200, desktop: 3200, tablet: 1100 },
|
||||
{ month: "Mar", mobile: 2800, desktop: 3800, tablet: 1300 },
|
||||
{ month: "Apr", mobile: 3200, desktop: 4200, tablet: 1500 },
|
||||
{ month: "May", mobile: 3800, desktop: 4800, tablet: 1800 }
|
||||
]
|
||||
|
||||
return (
|
||||
|
||||
)
|
||||
}
|
||||
```
|
||||
|
||||
### Radar Chart Component
|
||||
Multi-axis chart for comparing multiple variables across different categories simultaneously.
|
||||
|
||||
```tsx
|
||||
import { RadarChart } from "@/components/ui/radar-chart"
|
||||
|
||||
export default function SkillsChart() {
|
||||
const data = [
|
||||
{ skill: "JavaScript", score: 85, industry: 75 },
|
||||
{ skill: "TypeScript", score: 80, industry: 70 },
|
||||
{ skill: "React", score: 90, industry: 80 },
|
||||
{ skill: "Node.js", score: 75, industry: 72 },
|
||||
{ skill: "CSS", score: 88, industry: 78 }
|
||||
]
|
||||
|
||||
return (
|
||||
|
||||
)
|
||||
}
|
||||
```
|
||||
|
||||
### Mixed Chart Component
|
||||
Combined bar and line chart for displaying multiple data types with different visualization methods.
|
||||
|
||||
```tsx
|
||||
import { MixedChart } from "@/components/ui/mixed-chart"
|
||||
|
||||
export default function PerformanceChart() {
|
||||
const data = [
|
||||
{ month: "Jan", revenue: 4000, growth: 5.2 },
|
||||
{ month: "Feb", revenue: 4200, growth: 5.0 },
|
||||
{ month: "Mar", revenue: 4800, growth: 14.3 },
|
||||
{ month: "Apr", revenue: 5200, growth: 8.3 },
|
||||
{ month: "May", revenue: 5800, growth: 11.5 }
|
||||
]
|
||||
|
||||
return (
|
||||
|
||||
)
|
||||
}
|
||||
```
|
||||
|
||||
## Animation Components
|
||||
|
||||
### Magnetic Effect Component
|
||||
Magnetic hover effect that smoothly follows cursor movement for interactive buttons and cards.
|
||||
|
||||
```tsx
|
||||
import { Magnetic } from "@/components/ui/magnetic"
|
||||
|
||||
export default function InteractiveButton() {
|
||||
return (
|
||||
|
||||
Hover me
|
||||
|
||||
)
|
||||
}
|
||||
```
|
||||
|
||||
### Animated Cursor Component
|
||||
Custom animated cursor with interactive effects and particle trails for immersive experiences.
|
||||
|
||||
```tsx
|
||||
import { AnimatedCursor } from "@/components/ui/animated-cursor"
|
||||
|
||||
export default function Layout({ children }) {
|
||||
return (
|
||||
<>
|
||||
|
||||
{children}
|
||||
|
||||
)
|
||||
}
|
||||
```
|
||||
|
||||
### Apple Hello Effect Component
|
||||
Recreation of Apple's iconic "hello" animation with multi-language text transitions.
|
||||
|
||||
```tsx
|
||||
import { AppleHello } from "@/components/ui/apple-hello"
|
||||
|
||||
export default function WelcomeScreen() {
|
||||
const greetings = [
|
||||
{ text: "Hello", lang: "en" },
|
||||
{ text: "Bonjour", lang: "fr" },
|
||||
{ text: "こんにちは", lang: "ja" },
|
||||
{ text: "Hola", lang: "es" },
|
||||
{ text: "你好", lang: "zh" }
|
||||
]
|
||||
|
||||
return (
|
||||
|
||||
)
|
||||
}
|
||||
```
|
||||
|
||||
### Liquid Button Component
|
||||
Button with fluid liquid animation effect on hover for engaging call-to-action elements.
|
||||
|
||||
```tsx
|
||||
import { LiquidButton } from "@/components/ui/liquid-button"
|
||||
|
||||
export default function CTASection() {
|
||||
return (
|
||||
console.log("CTA clicked")}
|
||||
>
|
||||
Get Started
|
||||
|
||||
)
|
||||
}
|
||||
```
|
||||
|
||||
### Rolling Text Component
|
||||
Text animation that creates a rolling effect with smooth character transitions.
|
||||
|
||||
```tsx
|
||||
import { RollingText } from "@/components/ui/rolling-text"
|
||||
|
||||
export default function AnimatedHeading() {
|
||||
return (
|
||||
|
||||
)
|
||||
}
|
||||
```
|
||||
|
||||
### Shimmering Text Component
|
||||
Text with animated shimmer effect for attention-grabbing headings and highlights.
|
||||
|
||||
```tsx
|
||||
import { ShimmeringText } from "@/components/ui/shimmering-text"
|
||||
|
||||
export default function Hero() {
|
||||
return (
|
||||
|
||||
)
|
||||
}
|
||||
```
|
||||
|
||||
## React Hooks
|
||||
|
||||
### useBoolean Hook
|
||||
Enhanced boolean state management with toggle, enable, and disable methods for cleaner component logic.
|
||||
|
||||
```tsx
|
||||
import { useBoolean } from "@/hooks/use-boolean"
|
||||
|
||||
export default function TogglePanel() {
|
||||
const modal = useBoolean(false)
|
||||
const loading = useBoolean(false)
|
||||
|
||||
const handleSubmit = async () => {
|
||||
loading.setTrue()
|
||||
try {
|
||||
await submitForm()
|
||||
modal.setFalse()
|
||||
} finally {
|
||||
loading.setFalse()
|
||||
}
|
||||
}
|
||||
|
||||
return (
|
||||
<>
|
||||
Toggle Modal
|
||||
{modal.value && (
|
||||
|
||||
|
||||
Status: {loading.value ? "Saving..." : "Ready"}
|
||||
|
||||
Submit
|
||||
|
||||
|
||||
)}
|
||||
|
||||
)
|
||||
}
|
||||
```
|
||||
|
||||
### useCounter Hook
|
||||
Counter hook with increment, decrement, reset, and set functionality for numeric state management.
|
||||
|
||||
```tsx
|
||||
import { useCounter } from "@/hooks/use-counter"
|
||||
|
||||
export default function CartCounter() {
|
||||
const quantity = useCounter(0, { min: 0, max: 99 })
|
||||
|
||||
return (
|
||||
|
||||
|
||||
-
|
||||
{quantity.value}
|
||||
+
|
||||
|
||||
Reset
|
||||
|
||||
|
||||
)
|
||||
}
|
||||
```
|
||||
|
||||
### useLocalStorage Hook
|
||||
Persist state in browser localStorage with automatic serialization and deserialization.
|
||||
|
||||
```tsx
|
||||
import { useLocalStorage } from "@/hooks/use-local-storage"
|
||||
|
||||
export default function UserPreferences() {
|
||||
const [theme, setTheme] = useLocalStorage("theme", "light")
|
||||
const [settings, setSettings] = useLocalStorage("settings", {
|
||||
notifications: true,
|
||||
emailUpdates: false
|
||||
})
|
||||
|
||||
return (
|
||||
|
||||
|
||||
setTheme(e.target.value)}>
|
||||
LightDark setSettings({
|
||||
...settings,
|
||||
notifications: e.target.checked
|
||||
})}
|
||||
/>
|
||||
Enable Notifications
|
||||
|
||||
|
||||
)
|
||||
}
|
||||
```
|
||||
|
||||
### useDebounceValue Hook
|
||||
Debounce values to prevent excessive updates and API calls during rapid user input.
|
||||
|
||||
```tsx
|
||||
import { useDebounceValue } from "@/hooks/use-debounce-value"
|
||||
import { useState, useEffect } from "react"
|
||||
|
||||
export default function SearchBox() {
|
||||
const [search, setSearch] = useState("")
|
||||
const debouncedSearch = useDebounceValue(search, 500)
|
||||
const [results, setResults] = useState([])
|
||||
const [apiCalls, setApiCalls] = useState(0)
|
||||
|
||||
useEffect(() => {
|
||||
if (debouncedSearch) {
|
||||
setApiCalls(prev => prev + 1)
|
||||
fetch(`/api/search?q=${debouncedSearch}`)
|
||||
.then(res => res.json())
|
||||
.then(setResults)
|
||||
}
|
||||
}, [debouncedSearch])
|
||||
|
||||
return (
|
||||
|
||||
|
||||
setSearch(e.target.value)}
|
||||
placeholder="Search..."
|
||||
/>
|
||||
|
||||
|
||||
API calls: {apiCalls}
|
||||
|
||||
|
||||
)
|
||||
}
|
||||
```
|
||||
|
||||
### useHover Hook
|
||||
Track hover state on elements with customizable enter and leave delays for tooltip and preview functionality.
|
||||
|
||||
```tsx
|
||||
import { useHover } from "@/hooks/use-hover"
|
||||
import { useRef } from "react"
|
||||
|
||||
export default function ImagePreview() {
|
||||
const hoverRef = useRef(null)
|
||||
const isHovering = useHover(hoverRef, {
|
||||
enterDelay: 200,
|
||||
leaveDelay: 100
|
||||
})
|
||||
|
||||
return (
|
||||
|
||||
|
||||

|
||||
{isHovering && (
|
||||
|
||||
|
||||

|
||||
|
||||
)}
|
||||
|
||||
|
||||
)
|
||||
}
|
||||
```
|
||||
|
||||
### useCountdown Hook
|
||||
Countdown timer with play, pause, reset controls and completion callbacks for time-limited features.
|
||||
|
||||
```tsx
|
||||
import { useCountdown } from "@/hooks/use-countdown"
|
||||
|
||||
export default function OTPTimer() {
|
||||
const countdown = useCountdown({
|
||||
initialSeconds: 60,
|
||||
onComplete: () => alert("OTP expired! Request a new code.")
|
||||
})
|
||||
|
||||
return (
|
||||
|
||||
|
||||
{countdown.seconds}s
|
||||
|
||||
{!countdown.isRunning ? (
|
||||
Start
|
||||
) : (
|
||||
Pause
|
||||
)}
|
||||
Reset
|
||||
|
||||
Status: {countdown.isComplete ? "Expired" : countdown.isRunning ? "Active" : "Paused"}
|
||||
|
||||
|
||||
)
|
||||
}
|
||||
```
|
||||
|
||||
## Installation and Usage
|
||||
|
||||
### CLI Installation
|
||||
Install components directly into your project using the shadcn CLI for instant integration.
|
||||
|
||||
```bash
|
||||
# Initialize shadcn in your project
|
||||
npx shadcn@latest init
|
||||
|
||||
# Add individual components
|
||||
npx shadcn@latest add terminal
|
||||
npx shadcn@latest add dock
|
||||
npx shadcn@latest add credit-card
|
||||
|
||||
# Add multiple components at once
|
||||
npx shadcn@latest add bar-chart line-chart pie-chart
|
||||
|
||||
# Add hooks
|
||||
npx shadcn@latest add use-boolean use-counter use-local-storage
|
||||
```
|
||||
|
||||
### Project Configuration
|
||||
Configure your project to work with shadcn.io components using TypeScript and Tailwind CSS.
|
||||
|
||||
```typescript
|
||||
// tailwind.config.ts
|
||||
import type { Config } from "tailwindcss"
|
||||
|
||||
const config: Config = {
|
||||
darkMode: ["class"],
|
||||
content: [
|
||||
"./pages/**/*.{ts,tsx}",
|
||||
"./components/**/*.{ts,tsx}",
|
||||
"./app/**/*.{ts,tsx}",
|
||||
],
|
||||
theme: {
|
||||
extend: {
|
||||
colors: {
|
||||
border: "hsl(var(--border))",
|
||||
input: "hsl(var(--input))",
|
||||
ring: "hsl(var(--ring))",
|
||||
background: "hsl(var(--background))",
|
||||
foreground: "hsl(var(--foreground))",
|
||||
primary: {
|
||||
DEFAULT: "hsl(var(--primary))",
|
||||
foreground: "hsl(var(--primary-foreground))",
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
plugins: [require("tailwindcss-animate")],
|
||||
}
|
||||
|
||||
export default config
|
||||
```
|
||||
|
||||
## Summary
|
||||
|
||||
The shadcn.io component library serves as a comprehensive toolkit for React developers building modern web applications with Next.js and TypeScript. The library's primary use cases include rapid prototyping of user interfaces, building data-rich dashboards with interactive charts, creating engaging user experiences with animations and effects, and implementing common UI patterns without writing boilerplate code. The copy-paste approach gives developers complete ownership of their components, allowing for deep customization while maintaining consistency with shadcn/ui design principles. Components are particularly well-suited for SaaS applications, admin panels, marketing websites, and e-commerce platforms that require professional, accessible UI elements.
|
||||
|
||||
Integration patterns center around composability and customization rather than rigid package dependencies. Developers can cherry-pick individual components using the CLI, modify them at the source level to match their design system, and combine them with existing shadcn/ui components for a cohesive interface. The library supports both light and dark themes through CSS variables, integrates seamlessly with Tailwind CSS utility classes, and follows React best practices for performance and accessibility. Custom hooks provide reusable logic patterns that complement the visual components, creating a complete ecosystem for building feature-rich applications. The TypeScript-first approach ensures type safety throughout the development process, while the Recharts integration for data visualization provides powerful charting capabilities without additional configuration overhead.
|
||||
File diff suppressed because it is too large
Load diff
1
.cline/skills/shadcn-ui
Symbolic link
1
.cline/skills/shadcn-ui
Symbolic link
|
|
@ -0,0 +1 @@
|
|||
/mnt/c/Users/Zenchant/codex/beadboard/.agents/skills/shadcn-ui/
|
||||
File diff suppressed because it is too large
Load diff
|
|
@ -1,306 +0,0 @@
|
|||
### shadcn/ui Chart Component - Installation
|
||||
|
||||
Source: https://ui.shadcn.com/docs/components/chart
|
||||
|
||||
The chart component in shadcn/ui is built on Recharts, providing direct access to all Recharts capabilities with consistent theming.
|
||||
|
||||
```bash
|
||||
npx shadcn@latest add chart
|
||||
```
|
||||
|
||||
--------------------------------
|
||||
|
||||
### shadcn/ui Chart Component - Basic Usage
|
||||
|
||||
Source: https://ui.shadcn.com/docs/components/chart
|
||||
|
||||
The ChartContainer wraps your Recharts component and accepts a config prop for theming. Requires `min-h-[value]` for responsiveness.
|
||||
|
||||
```tsx
|
||||
import { Bar, BarChart, CartesianGrid, XAxis, YAxis } from "recharts"
|
||||
import { ChartContainer, ChartTooltipContent } from "@/components/ui/chart"
|
||||
|
||||
const chartConfig = {
|
||||
desktop: {
|
||||
label: "Desktop",
|
||||
color: "var(--chart-1)",
|
||||
},
|
||||
mobile: {
|
||||
label: "Mobile",
|
||||
color: "var(--chart-2)",
|
||||
},
|
||||
} satisfies import("@/components/ui/chart").ChartConfig
|
||||
|
||||
const chartData = [
|
||||
{ month: "January", desktop: 186, mobile: 80 },
|
||||
{ month: "February", desktop: 305, mobile: 200 },
|
||||
{ month: "March", desktop: 237, mobile: 120 },
|
||||
]
|
||||
|
||||
export function BarChartDemo() {
|
||||
return (
|
||||
<ChartContainer config={chartConfig} className="min-h-[200px] w-full">
|
||||
<BarChart data={chartData}>
|
||||
<CartesianGrid vertical={false} />
|
||||
<XAxis dataKey="month" tickLine={false} axisLine={false} />
|
||||
<Bar dataKey="desktop" fill="var(--color-desktop)" radius={4} />
|
||||
<Bar dataKey="mobile" fill="var(--color-mobile)" radius={4} />
|
||||
<ChartTooltip content={<ChartTooltipContent />} />
|
||||
</BarChart>
|
||||
</ChartContainer>
|
||||
)
|
||||
}
|
||||
```
|
||||
|
||||
--------------------------------
|
||||
|
||||
### shadcn/ui Chart Component - ChartConfig with Custom Colors
|
||||
|
||||
Source: https://ui.shadcn.com/docs/components/chart
|
||||
|
||||
You can define custom colors directly in the configuration using hex values or CSS variables.
|
||||
|
||||
```tsx
|
||||
const chartConfig = {
|
||||
desktop: {
|
||||
label: "Desktop",
|
||||
color: "#2563eb",
|
||||
theme: {
|
||||
light: "#2563eb",
|
||||
dark: "#60a5fa",
|
||||
},
|
||||
},
|
||||
mobile: {
|
||||
label: "Mobile",
|
||||
color: "var(--chart-2)",
|
||||
},
|
||||
} satisfies import("@/components/ui/chart").ChartConfig
|
||||
```
|
||||
|
||||
--------------------------------
|
||||
|
||||
### shadcn/ui Chart Component - CSS Variables
|
||||
|
||||
Source: https://ui.shadcn.com/docs/components/chart
|
||||
|
||||
Add chart color variables to your globals.css for consistent theming.
|
||||
|
||||
```css
|
||||
:root {
|
||||
/* Chart colors */
|
||||
--chart-1: oklch(0.646 0.222 41.116);
|
||||
--chart-2: oklch(0.6 0.118 184.704);
|
||||
--chart-3: oklch(0.546 0.198 38.228);
|
||||
--chart-4: oklch(0.596 0.151 343.253);
|
||||
--chart-5: oklch(0.546 0.158 49.157);
|
||||
}
|
||||
|
||||
.dark {
|
||||
--chart-1: oklch(0.488 0.243 264.376);
|
||||
--chart-2: oklch(0.696 0.17 162.48);
|
||||
--chart-3: oklch(0.698 0.141 24.311);
|
||||
--chart-4: oklch(0.676 0.172 171.196);
|
||||
--chart-5: oklch(0.578 0.192 302.85);
|
||||
}
|
||||
```
|
||||
|
||||
--------------------------------
|
||||
|
||||
### shadcn/ui Chart Component - Line Chart Example
|
||||
|
||||
Source: https://ui.shadcn.com/docs/components/chart
|
||||
|
||||
Creating a line chart with shadcn/ui charts component.
|
||||
|
||||
```tsx
|
||||
import { Line, LineChart, CartesianGrid, XAxis, YAxis } from "recharts"
|
||||
import { ChartContainer, ChartTooltipContent } from "@/components/ui/chart"
|
||||
|
||||
const chartConfig = {
|
||||
price: {
|
||||
label: "Price",
|
||||
color: "var(--chart-1)",
|
||||
},
|
||||
} satisfies import("@/components/ui/chart").ChartConfig
|
||||
|
||||
const chartData = [
|
||||
{ month: "January", price: 186 },
|
||||
{ month: "February", price: 305 },
|
||||
{ month: "March", price: 237 },
|
||||
{ month: "April", price: 203 },
|
||||
{ month: "May", price: 276 },
|
||||
]
|
||||
|
||||
export function LineChartDemo() {
|
||||
return (
|
||||
<ChartContainer config={chartConfig} className="min-h-[200px]">
|
||||
<LineChart data={chartData}>
|
||||
<CartesianGrid vertical={false} />
|
||||
<XAxis dataKey="month" tickLine={false} axisLine={false} />
|
||||
<YAxis tickLine={false} axisLine={false} tickFormatter={(value) => `$${value}`} />
|
||||
<Line
|
||||
dataKey="price"
|
||||
stroke="var(--color-price)"
|
||||
strokeWidth={2}
|
||||
dot={false}
|
||||
/>
|
||||
<ChartTooltip content={<ChartTooltipContent />} />
|
||||
</LineChart>
|
||||
</ChartContainer>
|
||||
)
|
||||
}
|
||||
```
|
||||
|
||||
--------------------------------
|
||||
|
||||
### shadcn/ui Chart Component - Area Chart Example
|
||||
|
||||
Source: https://ui.shadcn.com/docs/components/chart
|
||||
|
||||
Creating an area chart with gradient fill and legend.
|
||||
|
||||
```tsx
|
||||
import { Area, AreaChart, XAxis, YAxis } from "recharts"
|
||||
import {
|
||||
ChartContainer,
|
||||
ChartLegend,
|
||||
ChartLegendContent,
|
||||
ChartTooltipContent,
|
||||
} from "@/components/ui/chart"
|
||||
|
||||
const chartConfig = {
|
||||
desktop: { label: "Desktop", color: "var(--chart-1)" },
|
||||
mobile: { label: "Mobile", color: "var(--chart-2)" },
|
||||
} satisfies import("@/components/ui/chart").ChartConfig
|
||||
|
||||
export function AreaChartDemo() {
|
||||
return (
|
||||
<ChartContainer config={chartConfig} className="min-h-[200px]">
|
||||
<AreaChart data={chartData}>
|
||||
<XAxis dataKey="month" tickLine={false} axisLine={false} />
|
||||
<YAxis tickLine={false} axisLine={false} />
|
||||
<Area
|
||||
dataKey="desktop"
|
||||
fill="var(--color-desktop)"
|
||||
stroke="var(--color-desktop)"
|
||||
fillOpacity={0.3}
|
||||
/>
|
||||
<Area
|
||||
dataKey="mobile"
|
||||
fill="var(--color-mobile)"
|
||||
stroke="var(--color-mobile)"
|
||||
fillOpacity={0.3}
|
||||
/>
|
||||
<ChartTooltip content={<ChartTooltipContent />} />
|
||||
<ChartLegend content={<ChartLegendContent />} />
|
||||
</AreaChart>
|
||||
</ChartContainer>
|
||||
)
|
||||
}
|
||||
```
|
||||
|
||||
--------------------------------
|
||||
|
||||
### shadcn/ui Chart Component - Pie Chart Example
|
||||
|
||||
Source: https://ui.shadcn.com/docs/components/chart
|
||||
|
||||
Creating a pie/donut chart with shadcn/ui.
|
||||
|
||||
```tsx
|
||||
import { Pie, PieChart } from "recharts"
|
||||
import {
|
||||
ChartContainer,
|
||||
ChartLegend,
|
||||
ChartLegendContent,
|
||||
ChartTooltipContent,
|
||||
} from "@/components/ui/chart"
|
||||
|
||||
const chartConfig = {
|
||||
chrome: { label: "Chrome", color: "var(--chart-1)" },
|
||||
safari: { label: "Safari", color: "var(--chart-2)" },
|
||||
firefox: { label: "Firefox", color: "var(--chart-3)" },
|
||||
} satisfies import("@/components/ui/chart").ChartConfig
|
||||
|
||||
const pieData = [
|
||||
{ browser: "Chrome", visitors: 275, fill: "var(--color-chrome)" },
|
||||
{ browser: "Safari", visitors: 200, fill: "var(--color-safari)" },
|
||||
{ browser: "Firefox", visitors: 187, fill: "var(--color-firefox)" },
|
||||
]
|
||||
|
||||
export function PieChartDemo() {
|
||||
return (
|
||||
<ChartContainer config={chartConfig} className="min-h-[200px]">
|
||||
<PieChart>
|
||||
<Pie
|
||||
data={pieData}
|
||||
dataKey="visitors"
|
||||
nameKey="browser"
|
||||
cx="50%"
|
||||
cy="50%"
|
||||
outerRadius={80}
|
||||
/>
|
||||
<ChartTooltip content={<ChartTooltipContent />} />
|
||||
<ChartLegend content={<ChartLegendContent />} />
|
||||
</PieChart>
|
||||
</ChartContainer>
|
||||
)
|
||||
}
|
||||
```
|
||||
|
||||
--------------------------------
|
||||
|
||||
### shadcn/ui ChartTooltipContent Props
|
||||
|
||||
Source: https://ui.shadcn.com/docs/components/chart
|
||||
|
||||
The ChartTooltipContent component accepts these props for customizing tooltip behavior.
|
||||
|
||||
| Prop | Type | Default | Description |
|
||||
|------|------|---------|-------------|
|
||||
| `labelKey` | string | "label" | Key for tooltip label |
|
||||
| `nameKey` | string | "name" | Key for tooltip name |
|
||||
| `indicator` | "dot" \| "line" \| "dashed" | "dot" | Indicator style |
|
||||
| `hideLabel` | boolean | false | Hide label |
|
||||
| `hideIndicator` | boolean | false | Hide indicator |
|
||||
|
||||
--------------------------------
|
||||
|
||||
### shadcn/ui Chart Component - Accessibility
|
||||
|
||||
Source: https://ui.shadcn.com/docs/components/chart
|
||||
|
||||
Enable keyboard navigation and screen reader support by adding the accessibilityLayer prop.
|
||||
|
||||
```tsx
|
||||
<BarChart accessibilityLayer data={chartData}>
|
||||
<CartesianGrid vertical={false} />
|
||||
<XAxis dataKey="month" />
|
||||
<Bar dataKey="desktop" fill="var(--color-desktop)" />
|
||||
<ChartTooltip content={<ChartTooltipContent />} />
|
||||
</BarChart>
|
||||
```
|
||||
|
||||
This adds:
|
||||
- Keyboard arrow key navigation
|
||||
- ARIA labels for chart elements
|
||||
- Screen reader announcements for data values
|
||||
|
||||
--------------------------------
|
||||
|
||||
### shadcn/ui Chart Component - Recharts Dependencies
|
||||
|
||||
Source: https://ui.shadcn.com/docs/components/chart
|
||||
|
||||
The chart component requires the following Recharts dependencies to be installed.
|
||||
|
||||
```bash
|
||||
pnpm add recharts
|
||||
npm install recharts
|
||||
yarn add recharts
|
||||
```
|
||||
|
||||
Recharts provides the following chart types:
|
||||
- Area, Bar, Line, Pie, Composed
|
||||
- Radar, RadialBar, Scatter
|
||||
- Funnel, Treemap
|
||||
|
|
@ -1,145 +0,0 @@
|
|||
# shadcn/ui Learning Guide
|
||||
|
||||
This guide helps you learn shadcn/ui from basics to advanced patterns.
|
||||
|
||||
## Learning Path
|
||||
|
||||
### 1. Understanding the Philosophy
|
||||
|
||||
shadcn/ui is different from traditional component libraries:
|
||||
|
||||
- **Copy-paste components**: Components are copied into your project, not installed as packages
|
||||
- **Full customization**: You own the code and can modify it freely
|
||||
- **Built on Radix UI**: Provides accessibility primitives
|
||||
- **Styled with Tailwind**: Uses utility classes for consistent styling
|
||||
|
||||
### 2. Core Concepts to Master
|
||||
|
||||
#### Class Variance Authority (CVA)
|
||||
Most components use CVA for variant management:
|
||||
|
||||
```tsx
|
||||
const buttonVariants = cva(
|
||||
"base-classes",
|
||||
{
|
||||
variants: {
|
||||
variant: {
|
||||
default: "variant-classes",
|
||||
destructive: "destructive-classes",
|
||||
},
|
||||
size: {
|
||||
default: "size-classes",
|
||||
sm: "small-classes",
|
||||
},
|
||||
},
|
||||
defaultVariants: {
|
||||
variant: "default",
|
||||
size: "default",
|
||||
},
|
||||
}
|
||||
)
|
||||
```
|
||||
|
||||
#### cn Utility Function
|
||||
The `cn` function combines classes and resolves conflicts:
|
||||
|
||||
```tsx
|
||||
import { clsx, type ClassValue } from "clsx"
|
||||
import { twMerge } from "tailwind-merge"
|
||||
|
||||
export function cn(...inputs: ClassValue[]) {
|
||||
return twMerge(clsx(inputs))
|
||||
}
|
||||
```
|
||||
|
||||
### 3. Installation Checklist
|
||||
|
||||
- [ ] Initialize a new project (Next.js, Vite, or Remix)
|
||||
- [ ] Install Tailwind CSS
|
||||
- [ ] Run `npx shadcn@latest init`
|
||||
- [ ] Configure CSS variables
|
||||
- [ ] Install first component: `npx shadcn@latest add button`
|
||||
|
||||
### 4. Essential Components to Learn First
|
||||
|
||||
1. **Button** - Learn variants and sizes
|
||||
2. **Input** - Form inputs with labels
|
||||
3. **Card** - Container components
|
||||
4. **Form** - Form handling with React Hook Form
|
||||
5. **Dialog** - Modal windows
|
||||
6. **Select** - Dropdown selections
|
||||
7. **Toast** - Notifications
|
||||
|
||||
### 5. Common Patterns
|
||||
|
||||
#### Form Pattern
|
||||
Every form follows this structure:
|
||||
|
||||
```tsx
|
||||
1. Define Zod schema
|
||||
2. Create form with useForm
|
||||
3. Wrap with Form component
|
||||
4. Add FormField for each input
|
||||
5. Handle submission
|
||||
```
|
||||
|
||||
#### Component Customization Pattern
|
||||
To customize a component:
|
||||
|
||||
1. Copy component to your project
|
||||
2. Modify the variants
|
||||
3. Add new props if needed
|
||||
4. Update types
|
||||
|
||||
### 6. Best Practices
|
||||
|
||||
- Always use TypeScript
|
||||
- Follow the existing component structure
|
||||
- Use semantic HTML when possible
|
||||
- Test with screen readers for accessibility
|
||||
- Keep components small and focused
|
||||
|
||||
### 7. Advanced Topics
|
||||
|
||||
- Creating custom components from scratch
|
||||
- Building complex forms with validation
|
||||
- Implementing dark mode
|
||||
- Optimizing for performance
|
||||
- Testing components
|
||||
|
||||
## Practice Exercises
|
||||
|
||||
### Exercise 1: Basic Setup
|
||||
1. Create a new Next.js project
|
||||
2. Set up shadcn/ui
|
||||
3. Install and customize a Button component
|
||||
4. Add a new variant "gradient"
|
||||
|
||||
### Exercise 2: Form Building
|
||||
1. Create a contact form with:
|
||||
- Name input (required)
|
||||
- Email input (email validation)
|
||||
- Message textarea (min length)
|
||||
- Submit button with loading state
|
||||
|
||||
### Exercise 3: Component Combination
|
||||
1. Build a settings page using:
|
||||
- Card for layout
|
||||
- Sheet for mobile menu
|
||||
- Select for dropdowns
|
||||
- Switch for toggles
|
||||
- Toast for notifications
|
||||
|
||||
### Exercise 4: Custom Component
|
||||
1. Create a custom Badge component
|
||||
2. Support variants: default, secondary, destructive, outline
|
||||
3. Support sizes: sm, default, lg
|
||||
4. Add icon support
|
||||
|
||||
## Resources
|
||||
|
||||
- [Official Documentation](https://ui.shadcn.com)
|
||||
- [GitHub Repository](https://github.com/shadcn/ui)
|
||||
- [Examples Gallery](https://ui.shadcn.com/examples)
|
||||
- [Radix UI Primitives](https://www.radix-ui.com/primitives)
|
||||
- [Tailwind CSS Documentation](https://tailwindcss.com/docs)
|
||||
File diff suppressed because it is too large
Load diff
|
|
@ -1,586 +0,0 @@
|
|||
# shadcn.io Component Library
|
||||
|
||||
shadcn.io is a comprehensive React UI component library built on shadcn/ui principles, providing developers with production-ready, composable components for modern web applications. The library serves as a centralized resource for React developers who need high-quality UI components with TypeScript support, ranging from basic interactive elements to advanced AI-powered integrations. Unlike traditional component libraries that require package installations, shadcn.io components are designed to be copied directly into your project, giving you full control and customization capabilities.
|
||||
|
||||
The library encompasses four major categories: composable UI components (terminal, dock, credit cards, QR codes, color pickers), chart components built with Recharts, animation components with Tailwind CSS integration, and custom React hooks for state management and lifecycle operations. Each component follows best practices for accessibility, performance, and developer experience, with comprehensive TypeScript definitions and Next.js compatibility. The platform emphasizes flexibility and customization, allowing developers to modify components at the source level rather than being constrained by package APIs.
|
||||
|
||||
## Core Components
|
||||
|
||||
### Terminal Component
|
||||
Interactive terminal emulator with typing animations and command execution simulation for developer-focused interfaces.
|
||||
|
||||
```tsx
|
||||
import { Terminal } from "@/components/ui/terminal"
|
||||
|
||||
export default function DemoTerminal() {
|
||||
return (
|
||||
npm install @repo/terminalInstalling dependencies...npm start
|
||||
)
|
||||
}
|
||||
```
|
||||
|
||||
### Dock Component
|
||||
macOS-style application dock with smooth magnification effects on hover, perfect for navigation menus.
|
||||
|
||||
```tsx
|
||||
import { Dock, DockIcon } from "@/components/ui/dock"
|
||||
import { Home, Settings, User, Mail } from "lucide-react"
|
||||
|
||||
export default function AppDock() {
|
||||
return (
|
||||
|
||||
)
|
||||
}
|
||||
```
|
||||
|
||||
### Credit Card Component
|
||||
Interactive 3D credit card component with flip animations for payment forms and card displays.
|
||||
|
||||
```tsx
|
||||
import { CreditCard } from "@/components/ui/credit-card"
|
||||
import { useState } from "react"
|
||||
|
||||
export default function PaymentForm() {
|
||||
const [cardData, setCardData] = useState({
|
||||
number: "4532 1234 5678 9010",
|
||||
holder: "JOHN DOE",
|
||||
expiry: "12/28",
|
||||
cvv: "123"
|
||||
})
|
||||
|
||||
return (
|
||||
console.log("Card flipped:", flipped)}
|
||||
/>
|
||||
)
|
||||
}
|
||||
```
|
||||
|
||||
### Image Zoom Component
|
||||
Zoomable image component with smooth modal transitions for image galleries and product displays.
|
||||
|
||||
```tsx
|
||||
import { ImageZoom } from "@/components/ui/image-zoom"
|
||||
|
||||
export default function ProductGallery() {
|
||||
return (
|
||||
|
||||
|
||||
)
|
||||
}
|
||||
```
|
||||
|
||||
### QR Code Component
|
||||
Generate and display customizable QR codes with styling options for links, contact information, and authentication.
|
||||
|
||||
```tsx
|
||||
import { QRCode } from "@/components/ui/qr-code"
|
||||
|
||||
export default function ShareDialog() {
|
||||
const shareUrl = "https://shadcn.io"
|
||||
|
||||
return (
|
||||
|
||||
|
||||
Scan to visit shadcn.io
|
||||
|
||||
|
||||
)
|
||||
}
|
||||
```
|
||||
|
||||
### Color Picker Component
|
||||
Advanced color selection component supporting multiple color formats (HEX, RGB, HSL) with preview.
|
||||
|
||||
```tsx
|
||||
import { ColorPicker } from "@/components/ui/color-picker"
|
||||
import { useState } from "react"
|
||||
|
||||
export default function ThemeCustomizer() {
|
||||
const [color, setColor] = useState("#3b82f6")
|
||||
|
||||
return (
|
||||
|
||||
|
||||
Selected: {color}
|
||||
|
||||
)
|
||||
}
|
||||
```
|
||||
|
||||
## Chart Components
|
||||
|
||||
### Bar Chart Component
|
||||
Clean bar chart component for data comparison and categorical analysis using Recharts.
|
||||
|
||||
```tsx
|
||||
import { BarChart } from "@/components/ui/bar-chart"
|
||||
|
||||
export default function SalesChart() {
|
||||
const data = [
|
||||
{ month: "Jan", sales: 4000, revenue: 2400 },
|
||||
{ month: "Feb", sales: 3000, revenue: 1398 },
|
||||
{ month: "Mar", sales: 2000, revenue: 9800 },
|
||||
{ month: "Apr", sales: 2780, revenue: 3908 },
|
||||
{ month: "May", sales: 1890, revenue: 4800 },
|
||||
{ month: "Jun", sales: 2390, revenue: 3800 }
|
||||
]
|
||||
|
||||
return (
|
||||
`$${value.toLocaleString()}`}
|
||||
yAxisWidth={60}
|
||||
/>
|
||||
)
|
||||
}
|
||||
```
|
||||
|
||||
### Line Chart Component
|
||||
Smooth line chart for visualizing trends and time-series data with multiple data series support.
|
||||
|
||||
```tsx
|
||||
import { LineChart } from "@/components/ui/line-chart"
|
||||
|
||||
export default function MetricsChart() {
|
||||
const data = [
|
||||
{ date: "2024-01", users: 1200, sessions: 3400 },
|
||||
{ date: "2024-02", users: 1800, sessions: 4200 },
|
||||
{ date: "2024-03", users: 2400, sessions: 5800 },
|
||||
{ date: "2024-04", users: 3100, sessions: 7200 },
|
||||
{ date: "2024-05", users: 3800, sessions: 8900 }
|
||||
]
|
||||
|
||||
return (
|
||||
|
||||
)
|
||||
}
|
||||
```
|
||||
|
||||
### Pie Chart Component
|
||||
Donut chart component for displaying proportional data and percentage distributions.
|
||||
|
||||
```tsx
|
||||
import { PieChart } from "@/components/ui/pie-chart"
|
||||
|
||||
export default function MarketShareChart() {
|
||||
const data = [
|
||||
{ name: "Product A", value: 400, fill: "#3b82f6" },
|
||||
{ name: "Product B", value: 300, fill: "#10b981" },
|
||||
{ name: "Product C", value: 300, fill: "#f59e0b" },
|
||||
{ name: "Product D", value: 200, fill: "#ef4444" }
|
||||
]
|
||||
|
||||
return (
|
||||
`${entry.name}: ${entry.value}`}
|
||||
/>
|
||||
)
|
||||
}
|
||||
```
|
||||
|
||||
### Area Chart Component
|
||||
Stacked area chart for visualizing volume changes over time with multiple data series.
|
||||
|
||||
```tsx
|
||||
import { AreaChart } from "@/components/ui/area-chart"
|
||||
|
||||
export default function TrafficChart() {
|
||||
const data = [
|
||||
{ month: "Jan", mobile: 2000, desktop: 3000, tablet: 1000 },
|
||||
{ month: "Feb", mobile: 2200, desktop: 3200, tablet: 1100 },
|
||||
{ month: "Mar", mobile: 2800, desktop: 3800, tablet: 1300 },
|
||||
{ month: "Apr", mobile: 3200, desktop: 4200, tablet: 1500 },
|
||||
{ month: "May", mobile: 3800, desktop: 4800, tablet: 1800 }
|
||||
]
|
||||
|
||||
return (
|
||||
|
||||
)
|
||||
}
|
||||
```
|
||||
|
||||
### Radar Chart Component
|
||||
Multi-axis chart for comparing multiple variables across different categories simultaneously.
|
||||
|
||||
```tsx
|
||||
import { RadarChart } from "@/components/ui/radar-chart"
|
||||
|
||||
export default function SkillsChart() {
|
||||
const data = [
|
||||
{ skill: "JavaScript", score: 85, industry: 75 },
|
||||
{ skill: "TypeScript", score: 80, industry: 70 },
|
||||
{ skill: "React", score: 90, industry: 80 },
|
||||
{ skill: "Node.js", score: 75, industry: 72 },
|
||||
{ skill: "CSS", score: 88, industry: 78 }
|
||||
]
|
||||
|
||||
return (
|
||||
|
||||
)
|
||||
}
|
||||
```
|
||||
|
||||
### Mixed Chart Component
|
||||
Combined bar and line chart for displaying multiple data types with different visualization methods.
|
||||
|
||||
```tsx
|
||||
import { MixedChart } from "@/components/ui/mixed-chart"
|
||||
|
||||
export default function PerformanceChart() {
|
||||
const data = [
|
||||
{ month: "Jan", revenue: 4000, growth: 5.2 },
|
||||
{ month: "Feb", revenue: 4200, growth: 5.0 },
|
||||
{ month: "Mar", revenue: 4800, growth: 14.3 },
|
||||
{ month: "Apr", revenue: 5200, growth: 8.3 },
|
||||
{ month: "May", revenue: 5800, growth: 11.5 }
|
||||
]
|
||||
|
||||
return (
|
||||
|
||||
)
|
||||
}
|
||||
```
|
||||
|
||||
## Animation Components
|
||||
|
||||
### Magnetic Effect Component
|
||||
Magnetic hover effect that smoothly follows cursor movement for interactive buttons and cards.
|
||||
|
||||
```tsx
|
||||
import { Magnetic } from "@/components/ui/magnetic"
|
||||
|
||||
export default function InteractiveButton() {
|
||||
return (
|
||||
|
||||
Hover me
|
||||
|
||||
)
|
||||
}
|
||||
```
|
||||
|
||||
### Animated Cursor Component
|
||||
Custom animated cursor with interactive effects and particle trails for immersive experiences.
|
||||
|
||||
```tsx
|
||||
import { AnimatedCursor } from "@/components/ui/animated-cursor"
|
||||
|
||||
export default function Layout({ children }) {
|
||||
return (
|
||||
<>
|
||||
|
||||
{children}
|
||||
|
||||
)
|
||||
}
|
||||
```
|
||||
|
||||
### Apple Hello Effect Component
|
||||
Recreation of Apple's iconic "hello" animation with multi-language text transitions.
|
||||
|
||||
```tsx
|
||||
import { AppleHello } from "@/components/ui/apple-hello"
|
||||
|
||||
export default function WelcomeScreen() {
|
||||
const greetings = [
|
||||
{ text: "Hello", lang: "en" },
|
||||
{ text: "Bonjour", lang: "fr" },
|
||||
{ text: "こんにちは", lang: "ja" },
|
||||
{ text: "Hola", lang: "es" },
|
||||
{ text: "你好", lang: "zh" }
|
||||
]
|
||||
|
||||
return (
|
||||
|
||||
)
|
||||
}
|
||||
```
|
||||
|
||||
### Liquid Button Component
|
||||
Button with fluid liquid animation effect on hover for engaging call-to-action elements.
|
||||
|
||||
```tsx
|
||||
import { LiquidButton } from "@/components/ui/liquid-button"
|
||||
|
||||
export default function CTASection() {
|
||||
return (
|
||||
console.log("CTA clicked")}
|
||||
>
|
||||
Get Started
|
||||
|
||||
)
|
||||
}
|
||||
```
|
||||
|
||||
### Rolling Text Component
|
||||
Text animation that creates a rolling effect with smooth character transitions.
|
||||
|
||||
```tsx
|
||||
import { RollingText } from "@/components/ui/rolling-text"
|
||||
|
||||
export default function AnimatedHeading() {
|
||||
return (
|
||||
|
||||
)
|
||||
}
|
||||
```
|
||||
|
||||
### Shimmering Text Component
|
||||
Text with animated shimmer effect for attention-grabbing headings and highlights.
|
||||
|
||||
```tsx
|
||||
import { ShimmeringText } from "@/components/ui/shimmering-text"
|
||||
|
||||
export default function Hero() {
|
||||
return (
|
||||
|
||||
)
|
||||
}
|
||||
```
|
||||
|
||||
## React Hooks
|
||||
|
||||
### useBoolean Hook
|
||||
Enhanced boolean state management with toggle, enable, and disable methods for cleaner component logic.
|
||||
|
||||
```tsx
|
||||
import { useBoolean } from "@/hooks/use-boolean"
|
||||
|
||||
export default function TogglePanel() {
|
||||
const modal = useBoolean(false)
|
||||
const loading = useBoolean(false)
|
||||
|
||||
const handleSubmit = async () => {
|
||||
loading.setTrue()
|
||||
try {
|
||||
await submitForm()
|
||||
modal.setFalse()
|
||||
} finally {
|
||||
loading.setFalse()
|
||||
}
|
||||
}
|
||||
|
||||
return (
|
||||
<>
|
||||
Toggle Modal
|
||||
{modal.value && (
|
||||
|
||||
|
||||
Status: {loading.value ? "Saving..." : "Ready"}
|
||||
|
||||
Submit
|
||||
|
||||
|
||||
)}
|
||||
|
||||
)
|
||||
}
|
||||
```
|
||||
|
||||
### useCounter Hook
|
||||
Counter hook with increment, decrement, reset, and set functionality for numeric state management.
|
||||
|
||||
```tsx
|
||||
import { useCounter } from "@/hooks/use-counter"
|
||||
|
||||
export default function CartCounter() {
|
||||
const quantity = useCounter(0, { min: 0, max: 99 })
|
||||
|
||||
return (
|
||||
|
||||
|
||||
-
|
||||
{quantity.value}
|
||||
+
|
||||
|
||||
Reset
|
||||
|
||||
|
||||
)
|
||||
}
|
||||
```
|
||||
|
||||
### useLocalStorage Hook
|
||||
Persist state in browser localStorage with automatic serialization and deserialization.
|
||||
|
||||
```tsx
|
||||
import { useLocalStorage } from "@/hooks/use-local-storage"
|
||||
|
||||
export default function UserPreferences() {
|
||||
const [theme, setTheme] = useLocalStorage("theme", "light")
|
||||
const [settings, setSettings] = useLocalStorage("settings", {
|
||||
notifications: true,
|
||||
emailUpdates: false
|
||||
})
|
||||
|
||||
return (
|
||||
|
||||
|
||||
setTheme(e.target.value)}>
|
||||
LightDark setSettings({
|
||||
...settings,
|
||||
notifications: e.target.checked
|
||||
})}
|
||||
/>
|
||||
Enable Notifications
|
||||
|
||||
|
||||
)
|
||||
}
|
||||
```
|
||||
|
||||
### useDebounceValue Hook
|
||||
Debounce values to prevent excessive updates and API calls during rapid user input.
|
||||
|
||||
```tsx
|
||||
import { useDebounceValue } from "@/hooks/use-debounce-value"
|
||||
import { useState, useEffect } from "react"
|
||||
|
||||
export default function SearchBox() {
|
||||
const [search, setSearch] = useState("")
|
||||
const debouncedSearch = useDebounceValue(search, 500)
|
||||
const [results, setResults] = useState([])
|
||||
const [apiCalls, setApiCalls] = useState(0)
|
||||
|
||||
useEffect(() => {
|
||||
if (debouncedSearch) {
|
||||
setApiCalls(prev => prev + 1)
|
||||
fetch(`/api/search?q=${debouncedSearch}`)
|
||||
.then(res => res.json())
|
||||
.then(setResults)
|
||||
}
|
||||
}, [debouncedSearch])
|
||||
|
||||
return (
|
||||
|
||||
|
||||
setSearch(e.target.value)}
|
||||
placeholder="Search..."
|
||||
/>
|
||||
|
||||
|
||||
API calls: {apiCalls}
|
||||
|
||||
|
||||
)
|
||||
}
|
||||
```
|
||||
|
||||
### useHover Hook
|
||||
Track hover state on elements with customizable enter and leave delays for tooltip and preview functionality.
|
||||
|
||||
```tsx
|
||||
import { useHover } from "@/hooks/use-hover"
|
||||
import { useRef } from "react"
|
||||
|
||||
export default function ImagePreview() {
|
||||
const hoverRef = useRef(null)
|
||||
const isHovering = useHover(hoverRef, {
|
||||
enterDelay: 200,
|
||||
leaveDelay: 100
|
||||
})
|
||||
|
||||
return (
|
||||
|
||||
|
||||

|
||||
{isHovering && (
|
||||
|
||||
|
||||

|
||||
|
||||
)}
|
||||
|
||||
|
||||
)
|
||||
}
|
||||
```
|
||||
|
||||
### useCountdown Hook
|
||||
Countdown timer with play, pause, reset controls and completion callbacks for time-limited features.
|
||||
|
||||
```tsx
|
||||
import { useCountdown } from "@/hooks/use-countdown"
|
||||
|
||||
export default function OTPTimer() {
|
||||
const countdown = useCountdown({
|
||||
initialSeconds: 60,
|
||||
onComplete: () => alert("OTP expired! Request a new code.")
|
||||
})
|
||||
|
||||
return (
|
||||
|
||||
|
||||
{countdown.seconds}s
|
||||
|
||||
{!countdown.isRunning ? (
|
||||
Start
|
||||
) : (
|
||||
Pause
|
||||
)}
|
||||
Reset
|
||||
|
||||
Status: {countdown.isComplete ? "Expired" : countdown.isRunning ? "Active" : "Paused"}
|
||||
|
||||
|
||||
)
|
||||
}
|
||||
```
|
||||
|
||||
## Installation and Usage
|
||||
|
||||
### CLI Installation
|
||||
Install components directly into your project using the shadcn CLI for instant integration.
|
||||
|
||||
```bash
|
||||
# Initialize shadcn in your project
|
||||
npx shadcn@latest init
|
||||
|
||||
# Add individual components
|
||||
npx shadcn@latest add terminal
|
||||
npx shadcn@latest add dock
|
||||
npx shadcn@latest add credit-card
|
||||
|
||||
# Add multiple components at once
|
||||
npx shadcn@latest add bar-chart line-chart pie-chart
|
||||
|
||||
# Add hooks
|
||||
npx shadcn@latest add use-boolean use-counter use-local-storage
|
||||
```
|
||||
|
||||
### Project Configuration
|
||||
Configure your project to work with shadcn.io components using TypeScript and Tailwind CSS.
|
||||
|
||||
```typescript
|
||||
// tailwind.config.ts
|
||||
import type { Config } from "tailwindcss"
|
||||
|
||||
const config: Config = {
|
||||
darkMode: ["class"],
|
||||
content: [
|
||||
"./pages/**/*.{ts,tsx}",
|
||||
"./components/**/*.{ts,tsx}",
|
||||
"./app/**/*.{ts,tsx}",
|
||||
],
|
||||
theme: {
|
||||
extend: {
|
||||
colors: {
|
||||
border: "hsl(var(--border))",
|
||||
input: "hsl(var(--input))",
|
||||
ring: "hsl(var(--ring))",
|
||||
background: "hsl(var(--background))",
|
||||
foreground: "hsl(var(--foreground))",
|
||||
primary: {
|
||||
DEFAULT: "hsl(var(--primary))",
|
||||
foreground: "hsl(var(--primary-foreground))",
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
plugins: [require("tailwindcss-animate")],
|
||||
}
|
||||
|
||||
export default config
|
||||
```
|
||||
|
||||
## Summary
|
||||
|
||||
The shadcn.io component library serves as a comprehensive toolkit for React developers building modern web applications with Next.js and TypeScript. The library's primary use cases include rapid prototyping of user interfaces, building data-rich dashboards with interactive charts, creating engaging user experiences with animations and effects, and implementing common UI patterns without writing boilerplate code. The copy-paste approach gives developers complete ownership of their components, allowing for deep customization while maintaining consistency with shadcn/ui design principles. Components are particularly well-suited for SaaS applications, admin panels, marketing websites, and e-commerce platforms that require professional, accessible UI elements.
|
||||
|
||||
Integration patterns center around composability and customization rather than rigid package dependencies. Developers can cherry-pick individual components using the CLI, modify them at the source level to match their design system, and combine them with existing shadcn/ui components for a cohesive interface. The library supports both light and dark themes through CSS variables, integrates seamlessly with Tailwind CSS utility classes, and follows React best practices for performance and accessibility. Custom hooks provide reusable logic patterns that complement the visual components, creating a complete ecosystem for building feature-rich applications. The TypeScript-first approach ensures type safety throughout the development process, while the Recharts integration for data visualization provides powerful charting capabilities without additional configuration overhead.
|
||||
File diff suppressed because it is too large
Load diff
|
|
@ -1 +1 @@
|
|||
{}
|
||||
{"user.email":"jordanlive121@gmail.com","user.name":"zenchant"}
|
||||
|
|
@ -1,6 +1,6 @@
|
|||
{
|
||||
"extends": [
|
||||
"next/core-web-vitals",
|
||||
"next/typescript"
|
||||
]
|
||||
}
|
||||
{
|
||||
"extends": [
|
||||
"next/core-web-vitals",
|
||||
"next/typescript"
|
||||
]
|
||||
}
|
||||
|
|
|
|||
304
.github/agents/code-custodian
vendored
304
.github/agents/code-custodian
vendored
|
|
@ -1,152 +1,152 @@
|
|||
---
|
||||
name: code-custodian
|
||||
description: |
|
||||
Comprehensive code quality agent that finds and fixes issues across your codebase:
|
||||
- Discovers untested functions and writes missing tests
|
||||
- Runs test suite to verify coverage
|
||||
- Auto-fixes linting and formatting issues
|
||||
- Adds missing JSDoc/documentation
|
||||
- Updates README with current API examples
|
||||
- Identifies and fixes deprecated API usage
|
||||
- Keeps ARCHITECTURE.md and CONTRIBUTING.md in sync
|
||||
- Opens a single PR with all improvements
|
||||
|
||||
tools: Write, Read, LS, Glob, Grep, Bash(npm:*), Bash(git:*), Bash(gh:*)
|
||||
color: blue
|
||||
---
|
||||
|
||||
# Code Custodian
|
||||
|
||||
You are a comprehensive code quality and documentation steward. Your mission is to identify gaps in testing, documentation, and code quality—then fix them proactively. You work systematically and carefully, always verifying your changes don't break anything.
|
||||
|
||||
## Your Responsibilities
|
||||
|
||||
### 1. Test Coverage Analysis & Creation
|
||||
|
||||
When analyzing test coverage:
|
||||
- Use `find` or `ls` to list all source files in `src/`, `lib/`, or `components/`
|
||||
- For each file, check if a corresponding test file exists (look for `.test.ts`, `.spec.ts`, `.test.js`, etc.)
|
||||
- Read uncovered files to understand what functions should be tested
|
||||
- Identify critical functions: main exports, public APIs, business logic
|
||||
- Write comprehensive Jest/Vitest tests for untested functions
|
||||
- Include happy path tests
|
||||
- Include edge cases and error scenarios
|
||||
- Use meaningful test names describing the behavior
|
||||
- Follow the existing test style in the repo
|
||||
- Create test files in the appropriate `__tests__` or `tests/` directory matching source structure
|
||||
- Run `npm test` or `npm run test` to verify all tests pass
|
||||
- If tests fail, read the error, fix the test code, and re-run
|
||||
|
||||
### 2. Code Quality & Formatting
|
||||
|
||||
- Run `npm run lint` or `npx eslint . --fix` to auto-fix formatting
|
||||
- Search for deprecated patterns (e.g., old API calls, outdated imports)
|
||||
- Replace with current versions with explanations in commit messages
|
||||
- Fix obvious issues: console.logs left in production code, dead code, unused imports
|
||||
|
||||
### 3. Documentation Updates
|
||||
|
||||
#### README.md
|
||||
- Read current README
|
||||
- Check if it accurately reflects current API/features
|
||||
- Update feature list based on recent commits
|
||||
- Refresh code examples to match latest version
|
||||
- Add badges for test coverage, build status if missing
|
||||
- Ensure setup/installation instructions are accurate
|
||||
|
||||
#### JSDoc/Comments
|
||||
- Add missing JSDoc comments to exported functions
|
||||
- Include @param, @returns, @throws where applicable
|
||||
- Add brief descriptions for complex logic
|
||||
|
||||
#### ARCHITECTURE.md (if exists)
|
||||
- Read the existing architecture doc
|
||||
- After major refactors or new modules, update to reflect new components/modules added, changed data flows, new external integrations
|
||||
|
||||
#### CONTRIBUTING.md
|
||||
- Verify test command instructions are correct
|
||||
- Update with latest dev dependency versions
|
||||
- Document common npm/pnpm/yarn commands for local development
|
||||
- Add "golden path" for new contributors
|
||||
|
||||
### 4. Execution & PR Creation
|
||||
|
||||
When you've identified work:
|
||||
|
||||
1. Create branch: `git checkout -b chore/code-custodian-YYYY-MM-DD`
|
||||
|
||||
2. Make changes systematically:
|
||||
- Write/update tests then verify they pass
|
||||
- Fix linting then verify fixes applied
|
||||
- Update docs then verify accuracy
|
||||
- Commit with clear messages
|
||||
|
||||
3. Verify everything works:
|
||||
- Run `npm test` - all tests pass
|
||||
- Run `npm run lint` - no linting errors
|
||||
- Review git diff to ensure quality
|
||||
|
||||
4. Open PR:
|
||||
- Use `gh pr create` with detailed body
|
||||
- List what was added/fixed in each category
|
||||
- Explain any major decisions
|
||||
- Note test results and coverage
|
||||
|
||||
## Workflow Overview
|
||||
|
||||
When invoked:
|
||||
|
||||
### Phase 1: ANALYSIS (5-10 min)
|
||||
- Scan the codebase structure
|
||||
- Identify untested files
|
||||
- Check docs for staleness
|
||||
- List all improvements needed
|
||||
|
||||
### Phase 2: TEST COVERAGE (varies)
|
||||
- Write tests for untested functions
|
||||
- Run test suite
|
||||
- Fix any failing tests
|
||||
|
||||
### Phase 3: CODE QUALITY (5-10 min)
|
||||
- Auto-fix linting
|
||||
- Replace deprecated patterns
|
||||
|
||||
### Phase 4: DOCUMENTATION (10-15 min)
|
||||
- Update README with current examples
|
||||
- Add JSDoc comments
|
||||
- Refresh ARCHITECTURE.md if needed
|
||||
- Update CONTRIBUTING.md
|
||||
|
||||
### Phase 5: INTEGRATION & PR (5 min)
|
||||
- Create branch and commit all changes
|
||||
- Run full test suite one final time
|
||||
- Open PR with detailed summary
|
||||
|
||||
## Best Practices
|
||||
|
||||
**Before making changes:**
|
||||
- Always read existing code first to understand patterns
|
||||
- Match the existing code style
|
||||
- Check for test examples in the repo to replicate patterns
|
||||
|
||||
**When writing tests:**
|
||||
- Use descriptive test names
|
||||
- Test behavior, not implementation
|
||||
- Include both success and failure scenarios
|
||||
- Keep tests focused and independent
|
||||
|
||||
**When updating docs:**
|
||||
- Keep examples short and runnable
|
||||
- Use actual code from the repo where possible
|
||||
- Test examples if they're code snippets
|
||||
- Update dates/version numbers
|
||||
|
||||
**Safety first:**
|
||||
- Always run tests before committing
|
||||
- If tests fail, debug and fix before proceeding
|
||||
- Don't make breaking changes without discussion
|
||||
- When in doubt, add a comment explaining the change
|
||||
|
||||
## Communication
|
||||
|
||||
After each phase, explain what you found, what you fixed, any decisions made, status of test results, and link to the PR when created. If you encounter issues, describe the problem clearly with error messages and suggest solutions.
|
||||
---
|
||||
name: code-custodian
|
||||
description: |
|
||||
Comprehensive code quality agent that finds and fixes issues across your codebase:
|
||||
- Discovers untested functions and writes missing tests
|
||||
- Runs test suite to verify coverage
|
||||
- Auto-fixes linting and formatting issues
|
||||
- Adds missing JSDoc/documentation
|
||||
- Updates README with current API examples
|
||||
- Identifies and fixes deprecated API usage
|
||||
- Keeps ARCHITECTURE.md and CONTRIBUTING.md in sync
|
||||
- Opens a single PR with all improvements
|
||||
|
||||
tools: Write, Read, LS, Glob, Grep, Bash(npm:*), Bash(git:*), Bash(gh:*)
|
||||
color: blue
|
||||
---
|
||||
|
||||
# Code Custodian
|
||||
|
||||
You are a comprehensive code quality and documentation steward. Your mission is to identify gaps in testing, documentation, and code quality—then fix them proactively. You work systematically and carefully, always verifying your changes don't break anything.
|
||||
|
||||
## Your Responsibilities
|
||||
|
||||
### 1. Test Coverage Analysis & Creation
|
||||
|
||||
When analyzing test coverage:
|
||||
- Use `find` or `ls` to list all source files in `src/`, `lib/`, or `components/`
|
||||
- For each file, check if a corresponding test file exists (look for `.test.ts`, `.spec.ts`, `.test.js`, etc.)
|
||||
- Read uncovered files to understand what functions should be tested
|
||||
- Identify critical functions: main exports, public APIs, business logic
|
||||
- Write comprehensive Jest/Vitest tests for untested functions
|
||||
- Include happy path tests
|
||||
- Include edge cases and error scenarios
|
||||
- Use meaningful test names describing the behavior
|
||||
- Follow the existing test style in the repo
|
||||
- Create test files in the appropriate `__tests__` or `tests/` directory matching source structure
|
||||
- Run `npm test` or `npm run test` to verify all tests pass
|
||||
- If tests fail, read the error, fix the test code, and re-run
|
||||
|
||||
### 2. Code Quality & Formatting
|
||||
|
||||
- Run `npm run lint` or `npx eslint . --fix` to auto-fix formatting
|
||||
- Search for deprecated patterns (e.g., old API calls, outdated imports)
|
||||
- Replace with current versions with explanations in commit messages
|
||||
- Fix obvious issues: console.logs left in production code, dead code, unused imports
|
||||
|
||||
### 3. Documentation Updates
|
||||
|
||||
#### README.md
|
||||
- Read current README
|
||||
- Check if it accurately reflects current API/features
|
||||
- Update feature list based on recent commits
|
||||
- Refresh code examples to match latest version
|
||||
- Add badges for test coverage, build status if missing
|
||||
- Ensure setup/installation instructions are accurate
|
||||
|
||||
#### JSDoc/Comments
|
||||
- Add missing JSDoc comments to exported functions
|
||||
- Include @param, @returns, @throws where applicable
|
||||
- Add brief descriptions for complex logic
|
||||
|
||||
#### ARCHITECTURE.md (if exists)
|
||||
- Read the existing architecture doc
|
||||
- After major refactors or new modules, update to reflect new components/modules added, changed data flows, new external integrations
|
||||
|
||||
#### CONTRIBUTING.md
|
||||
- Verify test command instructions are correct
|
||||
- Update with latest dev dependency versions
|
||||
- Document common npm/pnpm/yarn commands for local development
|
||||
- Add "golden path" for new contributors
|
||||
|
||||
### 4. Execution & PR Creation
|
||||
|
||||
When you've identified work:
|
||||
|
||||
1. Create branch: `git checkout -b chore/code-custodian-YYYY-MM-DD`
|
||||
|
||||
2. Make changes systematically:
|
||||
- Write/update tests then verify they pass
|
||||
- Fix linting then verify fixes applied
|
||||
- Update docs then verify accuracy
|
||||
- Commit with clear messages
|
||||
|
||||
3. Verify everything works:
|
||||
- Run `npm test` - all tests pass
|
||||
- Run `npm run lint` - no linting errors
|
||||
- Review git diff to ensure quality
|
||||
|
||||
4. Open PR:
|
||||
- Use `gh pr create` with detailed body
|
||||
- List what was added/fixed in each category
|
||||
- Explain any major decisions
|
||||
- Note test results and coverage
|
||||
|
||||
## Workflow Overview
|
||||
|
||||
When invoked:
|
||||
|
||||
### Phase 1: ANALYSIS (5-10 min)
|
||||
- Scan the codebase structure
|
||||
- Identify untested files
|
||||
- Check docs for staleness
|
||||
- List all improvements needed
|
||||
|
||||
### Phase 2: TEST COVERAGE (varies)
|
||||
- Write tests for untested functions
|
||||
- Run test suite
|
||||
- Fix any failing tests
|
||||
|
||||
### Phase 3: CODE QUALITY (5-10 min)
|
||||
- Auto-fix linting
|
||||
- Replace deprecated patterns
|
||||
|
||||
### Phase 4: DOCUMENTATION (10-15 min)
|
||||
- Update README with current examples
|
||||
- Add JSDoc comments
|
||||
- Refresh ARCHITECTURE.md if needed
|
||||
- Update CONTRIBUTING.md
|
||||
|
||||
### Phase 5: INTEGRATION & PR (5 min)
|
||||
- Create branch and commit all changes
|
||||
- Run full test suite one final time
|
||||
- Open PR with detailed summary
|
||||
|
||||
## Best Practices
|
||||
|
||||
**Before making changes:**
|
||||
- Always read existing code first to understand patterns
|
||||
- Match the existing code style
|
||||
- Check for test examples in the repo to replicate patterns
|
||||
|
||||
**When writing tests:**
|
||||
- Use descriptive test names
|
||||
- Test behavior, not implementation
|
||||
- Include both success and failure scenarios
|
||||
- Keep tests focused and independent
|
||||
|
||||
**When updating docs:**
|
||||
- Keep examples short and runnable
|
||||
- Use actual code from the repo where possible
|
||||
- Test examples if they're code snippets
|
||||
- Update dates/version numbers
|
||||
|
||||
**Safety first:**
|
||||
- Always run tests before committing
|
||||
- If tests fail, debug and fix before proceeding
|
||||
- Don't make breaking changes without discussion
|
||||
- When in doubt, add a comment explaining the change
|
||||
|
||||
## Communication
|
||||
|
||||
After each phase, explain what you found, what you fixed, any decisions made, status of test results, and link to the PR when created. If you encounter issues, describe the problem clearly with error messages and suggest solutions.
|
||||
|
|
|
|||
42
.gitignore
vendored
42
.gitignore
vendored
|
|
@ -1,21 +1,21 @@
|
|||
node_modules/
|
||||
.next/
|
||||
*.tsbuildinfo
|
||||
.worktrees/
|
||||
worktrees/
|
||||
|
||||
# bv (beads viewer) local config and caches
|
||||
.bv/
|
||||
|
||||
# beads lock artifact
|
||||
.beads/.bv.lock
|
||||
.beads/.jsonl.lock
|
||||
|
||||
# local screenshot artifacts
|
||||
artifacts/
|
||||
|
||||
# beads socket lock
|
||||
.beads/bd.sock.startlock
|
||||
|
||||
# beadboard runtime artifacts
|
||||
.beadboard/
|
||||
node_modules/
|
||||
.next/
|
||||
*.tsbuildinfo
|
||||
.worktrees/
|
||||
worktrees/
|
||||
|
||||
# bv (beads viewer) local config and caches
|
||||
.bv/
|
||||
|
||||
# beads lock artifact
|
||||
.beads/.bv.lock
|
||||
.beads/.jsonl.lock
|
||||
|
||||
# local screenshot artifacts
|
||||
artifacts/
|
||||
|
||||
# beads socket lock
|
||||
.beads/bd.sock.startlock
|
||||
|
||||
# beadboard runtime artifacts
|
||||
.beadboard/
|
||||
|
|
|
|||
1
.openhands/skills/shadcn-ui
Symbolic link
1
.openhands/skills/shadcn-ui
Symbolic link
|
|
@ -0,0 +1 @@
|
|||
/mnt/c/Users/Zenchant/codex/beadboard/.agents/skills/shadcn-ui/
|
||||
File diff suppressed because it is too large
Load diff
|
|
@ -1,306 +0,0 @@
|
|||
### shadcn/ui Chart Component - Installation
|
||||
|
||||
Source: https://ui.shadcn.com/docs/components/chart
|
||||
|
||||
The chart component in shadcn/ui is built on Recharts, providing direct access to all Recharts capabilities with consistent theming.
|
||||
|
||||
```bash
|
||||
npx shadcn@latest add chart
|
||||
```
|
||||
|
||||
--------------------------------
|
||||
|
||||
### shadcn/ui Chart Component - Basic Usage
|
||||
|
||||
Source: https://ui.shadcn.com/docs/components/chart
|
||||
|
||||
The ChartContainer wraps your Recharts component and accepts a config prop for theming. Requires `min-h-[value]` for responsiveness.
|
||||
|
||||
```tsx
|
||||
import { Bar, BarChart, CartesianGrid, XAxis, YAxis } from "recharts"
|
||||
import { ChartContainer, ChartTooltipContent } from "@/components/ui/chart"
|
||||
|
||||
const chartConfig = {
|
||||
desktop: {
|
||||
label: "Desktop",
|
||||
color: "var(--chart-1)",
|
||||
},
|
||||
mobile: {
|
||||
label: "Mobile",
|
||||
color: "var(--chart-2)",
|
||||
},
|
||||
} satisfies import("@/components/ui/chart").ChartConfig
|
||||
|
||||
const chartData = [
|
||||
{ month: "January", desktop: 186, mobile: 80 },
|
||||
{ month: "February", desktop: 305, mobile: 200 },
|
||||
{ month: "March", desktop: 237, mobile: 120 },
|
||||
]
|
||||
|
||||
export function BarChartDemo() {
|
||||
return (
|
||||
<ChartContainer config={chartConfig} className="min-h-[200px] w-full">
|
||||
<BarChart data={chartData}>
|
||||
<CartesianGrid vertical={false} />
|
||||
<XAxis dataKey="month" tickLine={false} axisLine={false} />
|
||||
<Bar dataKey="desktop" fill="var(--color-desktop)" radius={4} />
|
||||
<Bar dataKey="mobile" fill="var(--color-mobile)" radius={4} />
|
||||
<ChartTooltip content={<ChartTooltipContent />} />
|
||||
</BarChart>
|
||||
</ChartContainer>
|
||||
)
|
||||
}
|
||||
```
|
||||
|
||||
--------------------------------
|
||||
|
||||
### shadcn/ui Chart Component - ChartConfig with Custom Colors
|
||||
|
||||
Source: https://ui.shadcn.com/docs/components/chart
|
||||
|
||||
You can define custom colors directly in the configuration using hex values or CSS variables.
|
||||
|
||||
```tsx
|
||||
const chartConfig = {
|
||||
desktop: {
|
||||
label: "Desktop",
|
||||
color: "#2563eb",
|
||||
theme: {
|
||||
light: "#2563eb",
|
||||
dark: "#60a5fa",
|
||||
},
|
||||
},
|
||||
mobile: {
|
||||
label: "Mobile",
|
||||
color: "var(--chart-2)",
|
||||
},
|
||||
} satisfies import("@/components/ui/chart").ChartConfig
|
||||
```
|
||||
|
||||
--------------------------------
|
||||
|
||||
### shadcn/ui Chart Component - CSS Variables
|
||||
|
||||
Source: https://ui.shadcn.com/docs/components/chart
|
||||
|
||||
Add chart color variables to your globals.css for consistent theming.
|
||||
|
||||
```css
|
||||
:root {
|
||||
/* Chart colors */
|
||||
--chart-1: oklch(0.646 0.222 41.116);
|
||||
--chart-2: oklch(0.6 0.118 184.704);
|
||||
--chart-3: oklch(0.546 0.198 38.228);
|
||||
--chart-4: oklch(0.596 0.151 343.253);
|
||||
--chart-5: oklch(0.546 0.158 49.157);
|
||||
}
|
||||
|
||||
.dark {
|
||||
--chart-1: oklch(0.488 0.243 264.376);
|
||||
--chart-2: oklch(0.696 0.17 162.48);
|
||||
--chart-3: oklch(0.698 0.141 24.311);
|
||||
--chart-4: oklch(0.676 0.172 171.196);
|
||||
--chart-5: oklch(0.578 0.192 302.85);
|
||||
}
|
||||
```
|
||||
|
||||
--------------------------------
|
||||
|
||||
### shadcn/ui Chart Component - Line Chart Example
|
||||
|
||||
Source: https://ui.shadcn.com/docs/components/chart
|
||||
|
||||
Creating a line chart with shadcn/ui charts component.
|
||||
|
||||
```tsx
|
||||
import { Line, LineChart, CartesianGrid, XAxis, YAxis } from "recharts"
|
||||
import { ChartContainer, ChartTooltipContent } from "@/components/ui/chart"
|
||||
|
||||
const chartConfig = {
|
||||
price: {
|
||||
label: "Price",
|
||||
color: "var(--chart-1)",
|
||||
},
|
||||
} satisfies import("@/components/ui/chart").ChartConfig
|
||||
|
||||
const chartData = [
|
||||
{ month: "January", price: 186 },
|
||||
{ month: "February", price: 305 },
|
||||
{ month: "March", price: 237 },
|
||||
{ month: "April", price: 203 },
|
||||
{ month: "May", price: 276 },
|
||||
]
|
||||
|
||||
export function LineChartDemo() {
|
||||
return (
|
||||
<ChartContainer config={chartConfig} className="min-h-[200px]">
|
||||
<LineChart data={chartData}>
|
||||
<CartesianGrid vertical={false} />
|
||||
<XAxis dataKey="month" tickLine={false} axisLine={false} />
|
||||
<YAxis tickLine={false} axisLine={false} tickFormatter={(value) => `$${value}`} />
|
||||
<Line
|
||||
dataKey="price"
|
||||
stroke="var(--color-price)"
|
||||
strokeWidth={2}
|
||||
dot={false}
|
||||
/>
|
||||
<ChartTooltip content={<ChartTooltipContent />} />
|
||||
</LineChart>
|
||||
</ChartContainer>
|
||||
)
|
||||
}
|
||||
```
|
||||
|
||||
--------------------------------
|
||||
|
||||
### shadcn/ui Chart Component - Area Chart Example
|
||||
|
||||
Source: https://ui.shadcn.com/docs/components/chart
|
||||
|
||||
Creating an area chart with gradient fill and legend.
|
||||
|
||||
```tsx
|
||||
import { Area, AreaChart, XAxis, YAxis } from "recharts"
|
||||
import {
|
||||
ChartContainer,
|
||||
ChartLegend,
|
||||
ChartLegendContent,
|
||||
ChartTooltipContent,
|
||||
} from "@/components/ui/chart"
|
||||
|
||||
const chartConfig = {
|
||||
desktop: { label: "Desktop", color: "var(--chart-1)" },
|
||||
mobile: { label: "Mobile", color: "var(--chart-2)" },
|
||||
} satisfies import("@/components/ui/chart").ChartConfig
|
||||
|
||||
export function AreaChartDemo() {
|
||||
return (
|
||||
<ChartContainer config={chartConfig} className="min-h-[200px]">
|
||||
<AreaChart data={chartData}>
|
||||
<XAxis dataKey="month" tickLine={false} axisLine={false} />
|
||||
<YAxis tickLine={false} axisLine={false} />
|
||||
<Area
|
||||
dataKey="desktop"
|
||||
fill="var(--color-desktop)"
|
||||
stroke="var(--color-desktop)"
|
||||
fillOpacity={0.3}
|
||||
/>
|
||||
<Area
|
||||
dataKey="mobile"
|
||||
fill="var(--color-mobile)"
|
||||
stroke="var(--color-mobile)"
|
||||
fillOpacity={0.3}
|
||||
/>
|
||||
<ChartTooltip content={<ChartTooltipContent />} />
|
||||
<ChartLegend content={<ChartLegendContent />} />
|
||||
</AreaChart>
|
||||
</ChartContainer>
|
||||
)
|
||||
}
|
||||
```
|
||||
|
||||
--------------------------------
|
||||
|
||||
### shadcn/ui Chart Component - Pie Chart Example
|
||||
|
||||
Source: https://ui.shadcn.com/docs/components/chart
|
||||
|
||||
Creating a pie/donut chart with shadcn/ui.
|
||||
|
||||
```tsx
|
||||
import { Pie, PieChart } from "recharts"
|
||||
import {
|
||||
ChartContainer,
|
||||
ChartLegend,
|
||||
ChartLegendContent,
|
||||
ChartTooltipContent,
|
||||
} from "@/components/ui/chart"
|
||||
|
||||
const chartConfig = {
|
||||
chrome: { label: "Chrome", color: "var(--chart-1)" },
|
||||
safari: { label: "Safari", color: "var(--chart-2)" },
|
||||
firefox: { label: "Firefox", color: "var(--chart-3)" },
|
||||
} satisfies import("@/components/ui/chart").ChartConfig
|
||||
|
||||
const pieData = [
|
||||
{ browser: "Chrome", visitors: 275, fill: "var(--color-chrome)" },
|
||||
{ browser: "Safari", visitors: 200, fill: "var(--color-safari)" },
|
||||
{ browser: "Firefox", visitors: 187, fill: "var(--color-firefox)" },
|
||||
]
|
||||
|
||||
export function PieChartDemo() {
|
||||
return (
|
||||
<ChartContainer config={chartConfig} className="min-h-[200px]">
|
||||
<PieChart>
|
||||
<Pie
|
||||
data={pieData}
|
||||
dataKey="visitors"
|
||||
nameKey="browser"
|
||||
cx="50%"
|
||||
cy="50%"
|
||||
outerRadius={80}
|
||||
/>
|
||||
<ChartTooltip content={<ChartTooltipContent />} />
|
||||
<ChartLegend content={<ChartLegendContent />} />
|
||||
</PieChart>
|
||||
</ChartContainer>
|
||||
)
|
||||
}
|
||||
```
|
||||
|
||||
--------------------------------
|
||||
|
||||
### shadcn/ui ChartTooltipContent Props
|
||||
|
||||
Source: https://ui.shadcn.com/docs/components/chart
|
||||
|
||||
The ChartTooltipContent component accepts these props for customizing tooltip behavior.
|
||||
|
||||
| Prop | Type | Default | Description |
|
||||
|------|------|---------|-------------|
|
||||
| `labelKey` | string | "label" | Key for tooltip label |
|
||||
| `nameKey` | string | "name" | Key for tooltip name |
|
||||
| `indicator` | "dot" \| "line" \| "dashed" | "dot" | Indicator style |
|
||||
| `hideLabel` | boolean | false | Hide label |
|
||||
| `hideIndicator` | boolean | false | Hide indicator |
|
||||
|
||||
--------------------------------
|
||||
|
||||
### shadcn/ui Chart Component - Accessibility
|
||||
|
||||
Source: https://ui.shadcn.com/docs/components/chart
|
||||
|
||||
Enable keyboard navigation and screen reader support by adding the accessibilityLayer prop.
|
||||
|
||||
```tsx
|
||||
<BarChart accessibilityLayer data={chartData}>
|
||||
<CartesianGrid vertical={false} />
|
||||
<XAxis dataKey="month" />
|
||||
<Bar dataKey="desktop" fill="var(--color-desktop)" />
|
||||
<ChartTooltip content={<ChartTooltipContent />} />
|
||||
</BarChart>
|
||||
```
|
||||
|
||||
This adds:
|
||||
- Keyboard arrow key navigation
|
||||
- ARIA labels for chart elements
|
||||
- Screen reader announcements for data values
|
||||
|
||||
--------------------------------
|
||||
|
||||
### shadcn/ui Chart Component - Recharts Dependencies
|
||||
|
||||
Source: https://ui.shadcn.com/docs/components/chart
|
||||
|
||||
The chart component requires the following Recharts dependencies to be installed.
|
||||
|
||||
```bash
|
||||
pnpm add recharts
|
||||
npm install recharts
|
||||
yarn add recharts
|
||||
```
|
||||
|
||||
Recharts provides the following chart types:
|
||||
- Area, Bar, Line, Pie, Composed
|
||||
- Radar, RadialBar, Scatter
|
||||
- Funnel, Treemap
|
||||
|
|
@ -1,145 +0,0 @@
|
|||
# shadcn/ui Learning Guide
|
||||
|
||||
This guide helps you learn shadcn/ui from basics to advanced patterns.
|
||||
|
||||
## Learning Path
|
||||
|
||||
### 1. Understanding the Philosophy
|
||||
|
||||
shadcn/ui is different from traditional component libraries:
|
||||
|
||||
- **Copy-paste components**: Components are copied into your project, not installed as packages
|
||||
- **Full customization**: You own the code and can modify it freely
|
||||
- **Built on Radix UI**: Provides accessibility primitives
|
||||
- **Styled with Tailwind**: Uses utility classes for consistent styling
|
||||
|
||||
### 2. Core Concepts to Master
|
||||
|
||||
#### Class Variance Authority (CVA)
|
||||
Most components use CVA for variant management:
|
||||
|
||||
```tsx
|
||||
const buttonVariants = cva(
|
||||
"base-classes",
|
||||
{
|
||||
variants: {
|
||||
variant: {
|
||||
default: "variant-classes",
|
||||
destructive: "destructive-classes",
|
||||
},
|
||||
size: {
|
||||
default: "size-classes",
|
||||
sm: "small-classes",
|
||||
},
|
||||
},
|
||||
defaultVariants: {
|
||||
variant: "default",
|
||||
size: "default",
|
||||
},
|
||||
}
|
||||
)
|
||||
```
|
||||
|
||||
#### cn Utility Function
|
||||
The `cn` function combines classes and resolves conflicts:
|
||||
|
||||
```tsx
|
||||
import { clsx, type ClassValue } from "clsx"
|
||||
import { twMerge } from "tailwind-merge"
|
||||
|
||||
export function cn(...inputs: ClassValue[]) {
|
||||
return twMerge(clsx(inputs))
|
||||
}
|
||||
```
|
||||
|
||||
### 3. Installation Checklist
|
||||
|
||||
- [ ] Initialize a new project (Next.js, Vite, or Remix)
|
||||
- [ ] Install Tailwind CSS
|
||||
- [ ] Run `npx shadcn@latest init`
|
||||
- [ ] Configure CSS variables
|
||||
- [ ] Install first component: `npx shadcn@latest add button`
|
||||
|
||||
### 4. Essential Components to Learn First
|
||||
|
||||
1. **Button** - Learn variants and sizes
|
||||
2. **Input** - Form inputs with labels
|
||||
3. **Card** - Container components
|
||||
4. **Form** - Form handling with React Hook Form
|
||||
5. **Dialog** - Modal windows
|
||||
6. **Select** - Dropdown selections
|
||||
7. **Toast** - Notifications
|
||||
|
||||
### 5. Common Patterns
|
||||
|
||||
#### Form Pattern
|
||||
Every form follows this structure:
|
||||
|
||||
```tsx
|
||||
1. Define Zod schema
|
||||
2. Create form with useForm
|
||||
3. Wrap with Form component
|
||||
4. Add FormField for each input
|
||||
5. Handle submission
|
||||
```
|
||||
|
||||
#### Component Customization Pattern
|
||||
To customize a component:
|
||||
|
||||
1. Copy component to your project
|
||||
2. Modify the variants
|
||||
3. Add new props if needed
|
||||
4. Update types
|
||||
|
||||
### 6. Best Practices
|
||||
|
||||
- Always use TypeScript
|
||||
- Follow the existing component structure
|
||||
- Use semantic HTML when possible
|
||||
- Test with screen readers for accessibility
|
||||
- Keep components small and focused
|
||||
|
||||
### 7. Advanced Topics
|
||||
|
||||
- Creating custom components from scratch
|
||||
- Building complex forms with validation
|
||||
- Implementing dark mode
|
||||
- Optimizing for performance
|
||||
- Testing components
|
||||
|
||||
## Practice Exercises
|
||||
|
||||
### Exercise 1: Basic Setup
|
||||
1. Create a new Next.js project
|
||||
2. Set up shadcn/ui
|
||||
3. Install and customize a Button component
|
||||
4. Add a new variant "gradient"
|
||||
|
||||
### Exercise 2: Form Building
|
||||
1. Create a contact form with:
|
||||
- Name input (required)
|
||||
- Email input (email validation)
|
||||
- Message textarea (min length)
|
||||
- Submit button with loading state
|
||||
|
||||
### Exercise 3: Component Combination
|
||||
1. Build a settings page using:
|
||||
- Card for layout
|
||||
- Sheet for mobile menu
|
||||
- Select for dropdowns
|
||||
- Switch for toggles
|
||||
- Toast for notifications
|
||||
|
||||
### Exercise 4: Custom Component
|
||||
1. Create a custom Badge component
|
||||
2. Support variants: default, secondary, destructive, outline
|
||||
3. Support sizes: sm, default, lg
|
||||
4. Add icon support
|
||||
|
||||
## Resources
|
||||
|
||||
- [Official Documentation](https://ui.shadcn.com)
|
||||
- [GitHub Repository](https://github.com/shadcn/ui)
|
||||
- [Examples Gallery](https://ui.shadcn.com/examples)
|
||||
- [Radix UI Primitives](https://www.radix-ui.com/primitives)
|
||||
- [Tailwind CSS Documentation](https://tailwindcss.com/docs)
|
||||
File diff suppressed because it is too large
Load diff
|
|
@ -1,586 +0,0 @@
|
|||
# shadcn.io Component Library
|
||||
|
||||
shadcn.io is a comprehensive React UI component library built on shadcn/ui principles, providing developers with production-ready, composable components for modern web applications. The library serves as a centralized resource for React developers who need high-quality UI components with TypeScript support, ranging from basic interactive elements to advanced AI-powered integrations. Unlike traditional component libraries that require package installations, shadcn.io components are designed to be copied directly into your project, giving you full control and customization capabilities.
|
||||
|
||||
The library encompasses four major categories: composable UI components (terminal, dock, credit cards, QR codes, color pickers), chart components built with Recharts, animation components with Tailwind CSS integration, and custom React hooks for state management and lifecycle operations. Each component follows best practices for accessibility, performance, and developer experience, with comprehensive TypeScript definitions and Next.js compatibility. The platform emphasizes flexibility and customization, allowing developers to modify components at the source level rather than being constrained by package APIs.
|
||||
|
||||
## Core Components
|
||||
|
||||
### Terminal Component
|
||||
Interactive terminal emulator with typing animations and command execution simulation for developer-focused interfaces.
|
||||
|
||||
```tsx
|
||||
import { Terminal } from "@/components/ui/terminal"
|
||||
|
||||
export default function DemoTerminal() {
|
||||
return (
|
||||
npm install @repo/terminalInstalling dependencies...npm start
|
||||
)
|
||||
}
|
||||
```
|
||||
|
||||
### Dock Component
|
||||
macOS-style application dock with smooth magnification effects on hover, perfect for navigation menus.
|
||||
|
||||
```tsx
|
||||
import { Dock, DockIcon } from "@/components/ui/dock"
|
||||
import { Home, Settings, User, Mail } from "lucide-react"
|
||||
|
||||
export default function AppDock() {
|
||||
return (
|
||||
|
||||
)
|
||||
}
|
||||
```
|
||||
|
||||
### Credit Card Component
|
||||
Interactive 3D credit card component with flip animations for payment forms and card displays.
|
||||
|
||||
```tsx
|
||||
import { CreditCard } from "@/components/ui/credit-card"
|
||||
import { useState } from "react"
|
||||
|
||||
export default function PaymentForm() {
|
||||
const [cardData, setCardData] = useState({
|
||||
number: "4532 1234 5678 9010",
|
||||
holder: "JOHN DOE",
|
||||
expiry: "12/28",
|
||||
cvv: "123"
|
||||
})
|
||||
|
||||
return (
|
||||
console.log("Card flipped:", flipped)}
|
||||
/>
|
||||
)
|
||||
}
|
||||
```
|
||||
|
||||
### Image Zoom Component
|
||||
Zoomable image component with smooth modal transitions for image galleries and product displays.
|
||||
|
||||
```tsx
|
||||
import { ImageZoom } from "@/components/ui/image-zoom"
|
||||
|
||||
export default function ProductGallery() {
|
||||
return (
|
||||
|
||||
|
||||
)
|
||||
}
|
||||
```
|
||||
|
||||
### QR Code Component
|
||||
Generate and display customizable QR codes with styling options for links, contact information, and authentication.
|
||||
|
||||
```tsx
|
||||
import { QRCode } from "@/components/ui/qr-code"
|
||||
|
||||
export default function ShareDialog() {
|
||||
const shareUrl = "https://shadcn.io"
|
||||
|
||||
return (
|
||||
|
||||
|
||||
Scan to visit shadcn.io
|
||||
|
||||
|
||||
)
|
||||
}
|
||||
```
|
||||
|
||||
### Color Picker Component
|
||||
Advanced color selection component supporting multiple color formats (HEX, RGB, HSL) with preview.
|
||||
|
||||
```tsx
|
||||
import { ColorPicker } from "@/components/ui/color-picker"
|
||||
import { useState } from "react"
|
||||
|
||||
export default function ThemeCustomizer() {
|
||||
const [color, setColor] = useState("#3b82f6")
|
||||
|
||||
return (
|
||||
|
||||
|
||||
Selected: {color}
|
||||
|
||||
)
|
||||
}
|
||||
```
|
||||
|
||||
## Chart Components
|
||||
|
||||
### Bar Chart Component
|
||||
Clean bar chart component for data comparison and categorical analysis using Recharts.
|
||||
|
||||
```tsx
|
||||
import { BarChart } from "@/components/ui/bar-chart"
|
||||
|
||||
export default function SalesChart() {
|
||||
const data = [
|
||||
{ month: "Jan", sales: 4000, revenue: 2400 },
|
||||
{ month: "Feb", sales: 3000, revenue: 1398 },
|
||||
{ month: "Mar", sales: 2000, revenue: 9800 },
|
||||
{ month: "Apr", sales: 2780, revenue: 3908 },
|
||||
{ month: "May", sales: 1890, revenue: 4800 },
|
||||
{ month: "Jun", sales: 2390, revenue: 3800 }
|
||||
]
|
||||
|
||||
return (
|
||||
`$${value.toLocaleString()}`}
|
||||
yAxisWidth={60}
|
||||
/>
|
||||
)
|
||||
}
|
||||
```
|
||||
|
||||
### Line Chart Component
|
||||
Smooth line chart for visualizing trends and time-series data with multiple data series support.
|
||||
|
||||
```tsx
|
||||
import { LineChart } from "@/components/ui/line-chart"
|
||||
|
||||
export default function MetricsChart() {
|
||||
const data = [
|
||||
{ date: "2024-01", users: 1200, sessions: 3400 },
|
||||
{ date: "2024-02", users: 1800, sessions: 4200 },
|
||||
{ date: "2024-03", users: 2400, sessions: 5800 },
|
||||
{ date: "2024-04", users: 3100, sessions: 7200 },
|
||||
{ date: "2024-05", users: 3800, sessions: 8900 }
|
||||
]
|
||||
|
||||
return (
|
||||
|
||||
)
|
||||
}
|
||||
```
|
||||
|
||||
### Pie Chart Component
|
||||
Donut chart component for displaying proportional data and percentage distributions.
|
||||
|
||||
```tsx
|
||||
import { PieChart } from "@/components/ui/pie-chart"
|
||||
|
||||
export default function MarketShareChart() {
|
||||
const data = [
|
||||
{ name: "Product A", value: 400, fill: "#3b82f6" },
|
||||
{ name: "Product B", value: 300, fill: "#10b981" },
|
||||
{ name: "Product C", value: 300, fill: "#f59e0b" },
|
||||
{ name: "Product D", value: 200, fill: "#ef4444" }
|
||||
]
|
||||
|
||||
return (
|
||||
`${entry.name}: ${entry.value}`}
|
||||
/>
|
||||
)
|
||||
}
|
||||
```
|
||||
|
||||
### Area Chart Component
|
||||
Stacked area chart for visualizing volume changes over time with multiple data series.
|
||||
|
||||
```tsx
|
||||
import { AreaChart } from "@/components/ui/area-chart"
|
||||
|
||||
export default function TrafficChart() {
|
||||
const data = [
|
||||
{ month: "Jan", mobile: 2000, desktop: 3000, tablet: 1000 },
|
||||
{ month: "Feb", mobile: 2200, desktop: 3200, tablet: 1100 },
|
||||
{ month: "Mar", mobile: 2800, desktop: 3800, tablet: 1300 },
|
||||
{ month: "Apr", mobile: 3200, desktop: 4200, tablet: 1500 },
|
||||
{ month: "May", mobile: 3800, desktop: 4800, tablet: 1800 }
|
||||
]
|
||||
|
||||
return (
|
||||
|
||||
)
|
||||
}
|
||||
```
|
||||
|
||||
### Radar Chart Component
|
||||
Multi-axis chart for comparing multiple variables across different categories simultaneously.
|
||||
|
||||
```tsx
|
||||
import { RadarChart } from "@/components/ui/radar-chart"
|
||||
|
||||
export default function SkillsChart() {
|
||||
const data = [
|
||||
{ skill: "JavaScript", score: 85, industry: 75 },
|
||||
{ skill: "TypeScript", score: 80, industry: 70 },
|
||||
{ skill: "React", score: 90, industry: 80 },
|
||||
{ skill: "Node.js", score: 75, industry: 72 },
|
||||
{ skill: "CSS", score: 88, industry: 78 }
|
||||
]
|
||||
|
||||
return (
|
||||
|
||||
)
|
||||
}
|
||||
```
|
||||
|
||||
### Mixed Chart Component
|
||||
Combined bar and line chart for displaying multiple data types with different visualization methods.
|
||||
|
||||
```tsx
|
||||
import { MixedChart } from "@/components/ui/mixed-chart"
|
||||
|
||||
export default function PerformanceChart() {
|
||||
const data = [
|
||||
{ month: "Jan", revenue: 4000, growth: 5.2 },
|
||||
{ month: "Feb", revenue: 4200, growth: 5.0 },
|
||||
{ month: "Mar", revenue: 4800, growth: 14.3 },
|
||||
{ month: "Apr", revenue: 5200, growth: 8.3 },
|
||||
{ month: "May", revenue: 5800, growth: 11.5 }
|
||||
]
|
||||
|
||||
return (
|
||||
|
||||
)
|
||||
}
|
||||
```
|
||||
|
||||
## Animation Components
|
||||
|
||||
### Magnetic Effect Component
|
||||
Magnetic hover effect that smoothly follows cursor movement for interactive buttons and cards.
|
||||
|
||||
```tsx
|
||||
import { Magnetic } from "@/components/ui/magnetic"
|
||||
|
||||
export default function InteractiveButton() {
|
||||
return (
|
||||
|
||||
Hover me
|
||||
|
||||
)
|
||||
}
|
||||
```
|
||||
|
||||
### Animated Cursor Component
|
||||
Custom animated cursor with interactive effects and particle trails for immersive experiences.
|
||||
|
||||
```tsx
|
||||
import { AnimatedCursor } from "@/components/ui/animated-cursor"
|
||||
|
||||
export default function Layout({ children }) {
|
||||
return (
|
||||
<>
|
||||
|
||||
{children}
|
||||
|
||||
)
|
||||
}
|
||||
```
|
||||
|
||||
### Apple Hello Effect Component
|
||||
Recreation of Apple's iconic "hello" animation with multi-language text transitions.
|
||||
|
||||
```tsx
|
||||
import { AppleHello } from "@/components/ui/apple-hello"
|
||||
|
||||
export default function WelcomeScreen() {
|
||||
const greetings = [
|
||||
{ text: "Hello", lang: "en" },
|
||||
{ text: "Bonjour", lang: "fr" },
|
||||
{ text: "こんにちは", lang: "ja" },
|
||||
{ text: "Hola", lang: "es" },
|
||||
{ text: "你好", lang: "zh" }
|
||||
]
|
||||
|
||||
return (
|
||||
|
||||
)
|
||||
}
|
||||
```
|
||||
|
||||
### Liquid Button Component
|
||||
Button with fluid liquid animation effect on hover for engaging call-to-action elements.
|
||||
|
||||
```tsx
|
||||
import { LiquidButton } from "@/components/ui/liquid-button"
|
||||
|
||||
export default function CTASection() {
|
||||
return (
|
||||
console.log("CTA clicked")}
|
||||
>
|
||||
Get Started
|
||||
|
||||
)
|
||||
}
|
||||
```
|
||||
|
||||
### Rolling Text Component
|
||||
Text animation that creates a rolling effect with smooth character transitions.
|
||||
|
||||
```tsx
|
||||
import { RollingText } from "@/components/ui/rolling-text"
|
||||
|
||||
export default function AnimatedHeading() {
|
||||
return (
|
||||
|
||||
)
|
||||
}
|
||||
```
|
||||
|
||||
### Shimmering Text Component
|
||||
Text with animated shimmer effect for attention-grabbing headings and highlights.
|
||||
|
||||
```tsx
|
||||
import { ShimmeringText } from "@/components/ui/shimmering-text"
|
||||
|
||||
export default function Hero() {
|
||||
return (
|
||||
|
||||
)
|
||||
}
|
||||
```
|
||||
|
||||
## React Hooks
|
||||
|
||||
### useBoolean Hook
|
||||
Enhanced boolean state management with toggle, enable, and disable methods for cleaner component logic.
|
||||
|
||||
```tsx
|
||||
import { useBoolean } from "@/hooks/use-boolean"
|
||||
|
||||
export default function TogglePanel() {
|
||||
const modal = useBoolean(false)
|
||||
const loading = useBoolean(false)
|
||||
|
||||
const handleSubmit = async () => {
|
||||
loading.setTrue()
|
||||
try {
|
||||
await submitForm()
|
||||
modal.setFalse()
|
||||
} finally {
|
||||
loading.setFalse()
|
||||
}
|
||||
}
|
||||
|
||||
return (
|
||||
<>
|
||||
Toggle Modal
|
||||
{modal.value && (
|
||||
|
||||
|
||||
Status: {loading.value ? "Saving..." : "Ready"}
|
||||
|
||||
Submit
|
||||
|
||||
|
||||
)}
|
||||
|
||||
)
|
||||
}
|
||||
```
|
||||
|
||||
### useCounter Hook
|
||||
Counter hook with increment, decrement, reset, and set functionality for numeric state management.
|
||||
|
||||
```tsx
|
||||
import { useCounter } from "@/hooks/use-counter"
|
||||
|
||||
export default function CartCounter() {
|
||||
const quantity = useCounter(0, { min: 0, max: 99 })
|
||||
|
||||
return (
|
||||
|
||||
|
||||
-
|
||||
{quantity.value}
|
||||
+
|
||||
|
||||
Reset
|
||||
|
||||
|
||||
)
|
||||
}
|
||||
```
|
||||
|
||||
### useLocalStorage Hook
|
||||
Persist state in browser localStorage with automatic serialization and deserialization.
|
||||
|
||||
```tsx
|
||||
import { useLocalStorage } from "@/hooks/use-local-storage"
|
||||
|
||||
export default function UserPreferences() {
|
||||
const [theme, setTheme] = useLocalStorage("theme", "light")
|
||||
const [settings, setSettings] = useLocalStorage("settings", {
|
||||
notifications: true,
|
||||
emailUpdates: false
|
||||
})
|
||||
|
||||
return (
|
||||
|
||||
|
||||
setTheme(e.target.value)}>
|
||||
LightDark setSettings({
|
||||
...settings,
|
||||
notifications: e.target.checked
|
||||
})}
|
||||
/>
|
||||
Enable Notifications
|
||||
|
||||
|
||||
)
|
||||
}
|
||||
```
|
||||
|
||||
### useDebounceValue Hook
|
||||
Debounce values to prevent excessive updates and API calls during rapid user input.
|
||||
|
||||
```tsx
|
||||
import { useDebounceValue } from "@/hooks/use-debounce-value"
|
||||
import { useState, useEffect } from "react"
|
||||
|
||||
export default function SearchBox() {
|
||||
const [search, setSearch] = useState("")
|
||||
const debouncedSearch = useDebounceValue(search, 500)
|
||||
const [results, setResults] = useState([])
|
||||
const [apiCalls, setApiCalls] = useState(0)
|
||||
|
||||
useEffect(() => {
|
||||
if (debouncedSearch) {
|
||||
setApiCalls(prev => prev + 1)
|
||||
fetch(`/api/search?q=${debouncedSearch}`)
|
||||
.then(res => res.json())
|
||||
.then(setResults)
|
||||
}
|
||||
}, [debouncedSearch])
|
||||
|
||||
return (
|
||||
|
||||
|
||||
setSearch(e.target.value)}
|
||||
placeholder="Search..."
|
||||
/>
|
||||
|
||||
|
||||
API calls: {apiCalls}
|
||||
|
||||
|
||||
)
|
||||
}
|
||||
```
|
||||
|
||||
### useHover Hook
|
||||
Track hover state on elements with customizable enter and leave delays for tooltip and preview functionality.
|
||||
|
||||
```tsx
|
||||
import { useHover } from "@/hooks/use-hover"
|
||||
import { useRef } from "react"
|
||||
|
||||
export default function ImagePreview() {
|
||||
const hoverRef = useRef(null)
|
||||
const isHovering = useHover(hoverRef, {
|
||||
enterDelay: 200,
|
||||
leaveDelay: 100
|
||||
})
|
||||
|
||||
return (
|
||||
|
||||
|
||||

|
||||
{isHovering && (
|
||||
|
||||
|
||||

|
||||
|
||||
)}
|
||||
|
||||
|
||||
)
|
||||
}
|
||||
```
|
||||
|
||||
### useCountdown Hook
|
||||
Countdown timer with play, pause, reset controls and completion callbacks for time-limited features.
|
||||
|
||||
```tsx
|
||||
import { useCountdown } from "@/hooks/use-countdown"
|
||||
|
||||
export default function OTPTimer() {
|
||||
const countdown = useCountdown({
|
||||
initialSeconds: 60,
|
||||
onComplete: () => alert("OTP expired! Request a new code.")
|
||||
})
|
||||
|
||||
return (
|
||||
|
||||
|
||||
{countdown.seconds}s
|
||||
|
||||
{!countdown.isRunning ? (
|
||||
Start
|
||||
) : (
|
||||
Pause
|
||||
)}
|
||||
Reset
|
||||
|
||||
Status: {countdown.isComplete ? "Expired" : countdown.isRunning ? "Active" : "Paused"}
|
||||
|
||||
|
||||
)
|
||||
}
|
||||
```
|
||||
|
||||
## Installation and Usage
|
||||
|
||||
### CLI Installation
|
||||
Install components directly into your project using the shadcn CLI for instant integration.
|
||||
|
||||
```bash
|
||||
# Initialize shadcn in your project
|
||||
npx shadcn@latest init
|
||||
|
||||
# Add individual components
|
||||
npx shadcn@latest add terminal
|
||||
npx shadcn@latest add dock
|
||||
npx shadcn@latest add credit-card
|
||||
|
||||
# Add multiple components at once
|
||||
npx shadcn@latest add bar-chart line-chart pie-chart
|
||||
|
||||
# Add hooks
|
||||
npx shadcn@latest add use-boolean use-counter use-local-storage
|
||||
```
|
||||
|
||||
### Project Configuration
|
||||
Configure your project to work with shadcn.io components using TypeScript and Tailwind CSS.
|
||||
|
||||
```typescript
|
||||
// tailwind.config.ts
|
||||
import type { Config } from "tailwindcss"
|
||||
|
||||
const config: Config = {
|
||||
darkMode: ["class"],
|
||||
content: [
|
||||
"./pages/**/*.{ts,tsx}",
|
||||
"./components/**/*.{ts,tsx}",
|
||||
"./app/**/*.{ts,tsx}",
|
||||
],
|
||||
theme: {
|
||||
extend: {
|
||||
colors: {
|
||||
border: "hsl(var(--border))",
|
||||
input: "hsl(var(--input))",
|
||||
ring: "hsl(var(--ring))",
|
||||
background: "hsl(var(--background))",
|
||||
foreground: "hsl(var(--foreground))",
|
||||
primary: {
|
||||
DEFAULT: "hsl(var(--primary))",
|
||||
foreground: "hsl(var(--primary-foreground))",
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
plugins: [require("tailwindcss-animate")],
|
||||
}
|
||||
|
||||
export default config
|
||||
```
|
||||
|
||||
## Summary
|
||||
|
||||
The shadcn.io component library serves as a comprehensive toolkit for React developers building modern web applications with Next.js and TypeScript. The library's primary use cases include rapid prototyping of user interfaces, building data-rich dashboards with interactive charts, creating engaging user experiences with animations and effects, and implementing common UI patterns without writing boilerplate code. The copy-paste approach gives developers complete ownership of their components, allowing for deep customization while maintaining consistency with shadcn/ui design principles. Components are particularly well-suited for SaaS applications, admin panels, marketing websites, and e-commerce platforms that require professional, accessible UI elements.
|
||||
|
||||
Integration patterns center around composability and customization rather than rigid package dependencies. Developers can cherry-pick individual components using the CLI, modify them at the source level to match their design system, and combine them with existing shadcn/ui components for a cohesive interface. The library supports both light and dark themes through CSS variables, integrates seamlessly with Tailwind CSS utility classes, and follows React best practices for performance and accessibility. Custom hooks provide reusable logic patterns that complement the visual components, creating a complete ecosystem for building feature-rich applications. The TypeScript-first approach ensures type safety throughout the development process, while the Recharts integration for data visualization provides powerful charting capabilities without additional configuration overhead.
|
||||
File diff suppressed because it is too large
Load diff
42
LICENSE
42
LICENSE
|
|
@ -1,21 +1,21 @@
|
|||
MIT License
|
||||
|
||||
Copyright (c) 2026 Zenchant
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
||||
MIT License
|
||||
|
||||
Copyright (c) 2026 Zenchant
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
||||
|
|
|
|||
|
|
@ -1,33 +1,33 @@
|
|||
bb-verify2-mlnaouad
|
||||
bb-bridge-fix-mlnaja4j
|
||||
bb-join-mlna9nbo
|
||||
bb-invepic-mln9perd
|
||||
bb-invalid-epic-mln9hraq
|
||||
bb-m1-mln9perd
|
||||
bb-leave-mln9perd
|
||||
bb-member3-mln9hraq
|
||||
bb-member2-mln9hraq
|
||||
bb-switch-mln9perd
|
||||
bb-nolabel-test-mln9hraq
|
||||
bb-leave-test-mln9hraq
|
||||
bb-switch-test-mln9hraq
|
||||
bb-join-test-mln9hraq
|
||||
bb-idem-test-mln97lyt
|
||||
bb-switch-test-mln97lyt
|
||||
bb-join-test-mln97lyt
|
||||
bb-switch-test-mln8xxn4
|
||||
bb-nolabel-test-mln8pdgh
|
||||
bb-leave-test-mln8pdgh
|
||||
bb-idem-test-mln8pdgh
|
||||
bb-switch-test-mln8pdgh
|
||||
bb-join-test-mln8pdgh
|
||||
bb-leave-test-mln8hp8j
|
||||
bb-idem-test-mln8hp8j
|
||||
bb-switch-test-mln8hp8j
|
||||
bb-join-test-mln8hp8j
|
||||
bb-fresh-test-mln8canu
|
||||
bb-step-test-mln872rm
|
||||
bb-debug-test-mln83q18
|
||||
bb-switch-test-mln7xyls
|
||||
bb-join-test-mln7xyls
|
||||
bb-test-agent
|
||||
bb-verify2-mlnaouad
|
||||
bb-bridge-fix-mlnaja4j
|
||||
bb-join-mlna9nbo
|
||||
bb-invepic-mln9perd
|
||||
bb-invalid-epic-mln9hraq
|
||||
bb-m1-mln9perd
|
||||
bb-leave-mln9perd
|
||||
bb-member3-mln9hraq
|
||||
bb-member2-mln9hraq
|
||||
bb-switch-mln9perd
|
||||
bb-nolabel-test-mln9hraq
|
||||
bb-leave-test-mln9hraq
|
||||
bb-switch-test-mln9hraq
|
||||
bb-join-test-mln9hraq
|
||||
bb-idem-test-mln97lyt
|
||||
bb-switch-test-mln97lyt
|
||||
bb-join-test-mln97lyt
|
||||
bb-switch-test-mln8xxn4
|
||||
bb-nolabel-test-mln8pdgh
|
||||
bb-leave-test-mln8pdgh
|
||||
bb-idem-test-mln8pdgh
|
||||
bb-switch-test-mln8pdgh
|
||||
bb-join-test-mln8pdgh
|
||||
bb-leave-test-mln8hp8j
|
||||
bb-idem-test-mln8hp8j
|
||||
bb-switch-test-mln8hp8j
|
||||
bb-join-test-mln8hp8j
|
||||
bb-fresh-test-mln8canu
|
||||
bb-step-test-mln872rm
|
||||
bb-debug-test-mln83q18
|
||||
bb-switch-test-mln7xyls
|
||||
bb-join-test-mln7xyls
|
||||
bb-test-agent
|
||||
|
|
|
|||
|
|
@ -1,114 +1,114 @@
|
|||
bb-ui2.29
|
||||
bb-atf
|
||||
bb-z6s
|
||||
bb-54x
|
||||
bb-nuy
|
||||
bb-98c
|
||||
bb-3ha
|
||||
bb-22l
|
||||
bb-5am
|
||||
bb-dwz
|
||||
bb-3dv
|
||||
bb-only-ui-agent
|
||||
bb-graph-agent-1
|
||||
bb-ui-agent-2
|
||||
bb-ui-agent-1
|
||||
bb-verify-mlnavzwu
|
||||
bb-final-mlnar702
|
||||
bb-verify2-mlnaouad
|
||||
bb-final-mlnalaqz
|
||||
bb-bridge-fix-mlnaja4j
|
||||
bb-verify-mlnadaip
|
||||
bb-switch-mlna9nbo
|
||||
bb-join-mlna9nbo
|
||||
bb-invepic-mln9perd
|
||||
bb-m2-mln9perd
|
||||
bb-invalid-epic-mln9hraq
|
||||
bb-m1-mln9perd
|
||||
bb-leave-mln9perd
|
||||
bb-member3-mln9hraq
|
||||
bb-member2-mln9hraq
|
||||
bb-member1-mln9hraq
|
||||
bb-switch-mln9perd
|
||||
bb-nolabel-test-mln9hraq
|
||||
bb-join-mln9perd
|
||||
bb-leave-test-mln9hraq
|
||||
bb-idem-test-mln9hraq
|
||||
bb-debug-mln9knzs
|
||||
bb-switch-test-mln9hraq
|
||||
bb-join-test-mln9hraq
|
||||
bb-smoke-mln9e525
|
||||
bb-idem-test-mln97lyt
|
||||
bb-switch-test-mln97lyt
|
||||
bb-join-test-mln97lyt
|
||||
bb-switch-test-mln8xxn4
|
||||
bb-join-test-mln8xxn4
|
||||
bb-nolabel-test-mln8pdgh
|
||||
bb-leave-test-mln8pdgh
|
||||
bb-idem-test-mln8pdgh
|
||||
bb-switch-test-mln8pdgh
|
||||
bb-join-test-mln8pdgh
|
||||
bb-leave-test-mln8hp8j
|
||||
bb-idem-test-mln8hp8j
|
||||
bb-switch-test-mln8hp8j
|
||||
bb-join-test-mln8hp8j
|
||||
bb-daemon-test-mln8e4tf
|
||||
bb-fresh-test-mln8canu
|
||||
bb-upd-test-mln8981k
|
||||
bb-step-test-mln872rm
|
||||
bb-debug-test-mln83q18
|
||||
bb-switch-test-mln7xyls
|
||||
bb-join-test-mln7xyls
|
||||
bb-linus-swarm
|
||||
bb-ff6
|
||||
bb-agent-graph-1
|
||||
bb-1xj
|
||||
bb-agent-a
|
||||
bb-agent-b
|
||||
bb-active-agent
|
||||
bb-agent-ui-1
|
||||
bb-green-falcon
|
||||
bb-zenchantlive
|
||||
bb-silver-castle
|
||||
bb-test-agent
|
||||
bb-9p8
|
||||
bb-u6f.3
|
||||
bb-6aj.2
|
||||
bb-6aj.1
|
||||
beadboard-yad
|
||||
beadboard-eo8
|
||||
beadboard-c08
|
||||
bb-ui2.30
|
||||
bb-buff
|
||||
bb-jp2
|
||||
bb-79b
|
||||
bb-1y7
|
||||
bb-u6f.6.6
|
||||
bb-u6f.6.4
|
||||
bb-u6f.6.3
|
||||
bb-u6f.6.2
|
||||
bb-u6f.6.1
|
||||
bb-u6f.6
|
||||
bb-kp5
|
||||
bb-dcv.8
|
||||
bb-dcv.7
|
||||
bb-dcv.6
|
||||
bb-dcv.5
|
||||
bb-dcv.4
|
||||
bb-dcv.3
|
||||
bb-dcv.2
|
||||
bb-dcv.1
|
||||
bb-dcv
|
||||
bb-u6f.1
|
||||
bb-u6f
|
||||
bb-trz.4
|
||||
bb-trz.3
|
||||
bb-trz.2
|
||||
bb-trz.1
|
||||
bb-zzr
|
||||
bb-1d1
|
||||
bb-5pw
|
||||
bb-format-check
|
||||
bb-buff.4
|
||||
bb-u6f.6.5
|
||||
bb-u6f.2
|
||||
bb-ui2.29
|
||||
bb-atf
|
||||
bb-z6s
|
||||
bb-54x
|
||||
bb-nuy
|
||||
bb-98c
|
||||
bb-3ha
|
||||
bb-22l
|
||||
bb-5am
|
||||
bb-dwz
|
||||
bb-3dv
|
||||
bb-only-ui-agent
|
||||
bb-graph-agent-1
|
||||
bb-ui-agent-2
|
||||
bb-ui-agent-1
|
||||
bb-verify-mlnavzwu
|
||||
bb-final-mlnar702
|
||||
bb-verify2-mlnaouad
|
||||
bb-final-mlnalaqz
|
||||
bb-bridge-fix-mlnaja4j
|
||||
bb-verify-mlnadaip
|
||||
bb-switch-mlna9nbo
|
||||
bb-join-mlna9nbo
|
||||
bb-invepic-mln9perd
|
||||
bb-m2-mln9perd
|
||||
bb-invalid-epic-mln9hraq
|
||||
bb-m1-mln9perd
|
||||
bb-leave-mln9perd
|
||||
bb-member3-mln9hraq
|
||||
bb-member2-mln9hraq
|
||||
bb-member1-mln9hraq
|
||||
bb-switch-mln9perd
|
||||
bb-nolabel-test-mln9hraq
|
||||
bb-join-mln9perd
|
||||
bb-leave-test-mln9hraq
|
||||
bb-idem-test-mln9hraq
|
||||
bb-debug-mln9knzs
|
||||
bb-switch-test-mln9hraq
|
||||
bb-join-test-mln9hraq
|
||||
bb-smoke-mln9e525
|
||||
bb-idem-test-mln97lyt
|
||||
bb-switch-test-mln97lyt
|
||||
bb-join-test-mln97lyt
|
||||
bb-switch-test-mln8xxn4
|
||||
bb-join-test-mln8xxn4
|
||||
bb-nolabel-test-mln8pdgh
|
||||
bb-leave-test-mln8pdgh
|
||||
bb-idem-test-mln8pdgh
|
||||
bb-switch-test-mln8pdgh
|
||||
bb-join-test-mln8pdgh
|
||||
bb-leave-test-mln8hp8j
|
||||
bb-idem-test-mln8hp8j
|
||||
bb-switch-test-mln8hp8j
|
||||
bb-join-test-mln8hp8j
|
||||
bb-daemon-test-mln8e4tf
|
||||
bb-fresh-test-mln8canu
|
||||
bb-upd-test-mln8981k
|
||||
bb-step-test-mln872rm
|
||||
bb-debug-test-mln83q18
|
||||
bb-switch-test-mln7xyls
|
||||
bb-join-test-mln7xyls
|
||||
bb-linus-swarm
|
||||
bb-ff6
|
||||
bb-agent-graph-1
|
||||
bb-1xj
|
||||
bb-agent-a
|
||||
bb-agent-b
|
||||
bb-active-agent
|
||||
bb-agent-ui-1
|
||||
bb-green-falcon
|
||||
bb-zenchantlive
|
||||
bb-silver-castle
|
||||
bb-test-agent
|
||||
bb-9p8
|
||||
bb-u6f.3
|
||||
bb-6aj.2
|
||||
bb-6aj.1
|
||||
beadboard-yad
|
||||
beadboard-eo8
|
||||
beadboard-c08
|
||||
bb-ui2.30
|
||||
bb-buff
|
||||
bb-jp2
|
||||
bb-79b
|
||||
bb-1y7
|
||||
bb-u6f.6.6
|
||||
bb-u6f.6.4
|
||||
bb-u6f.6.3
|
||||
bb-u6f.6.2
|
||||
bb-u6f.6.1
|
||||
bb-u6f.6
|
||||
bb-kp5
|
||||
bb-dcv.8
|
||||
bb-dcv.7
|
||||
bb-dcv.6
|
||||
bb-dcv.5
|
||||
bb-dcv.4
|
||||
bb-dcv.3
|
||||
bb-dcv.2
|
||||
bb-dcv.1
|
||||
bb-dcv
|
||||
bb-u6f.1
|
||||
bb-u6f
|
||||
bb-trz.4
|
||||
bb-trz.3
|
||||
bb-trz.2
|
||||
bb-trz.1
|
||||
bb-zzr
|
||||
bb-1d1
|
||||
bb-5pw
|
||||
bb-format-check
|
||||
bb-buff.4
|
||||
bb-u6f.6.5
|
||||
bb-u6f.2
|
||||
|
|
|
|||
|
|
@ -1,61 +1,61 @@
|
|||
import * as React from "react"
|
||||
import { Slot } from "@radix-ui/react-slot"
|
||||
import { cva, type VariantProps } from "class-variance-authority"
|
||||
|
||||
import { cn } from "@/lib/utils"
|
||||
|
||||
const buttonVariants = cva(
|
||||
"inline-flex items-center justify-center gap-2 whitespace-nowrap rounded-md text-sm font-medium transition-colors focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-ring disabled:pointer-events-none disabled:opacity-50 [&_svg]:pointer-events-none [&_svg]:size-4 [&_svg]:shrink-0",
|
||||
{
|
||||
variants: {
|
||||
variant: {
|
||||
default:
|
||||
"bg-primary text-primary-foreground shadow hover:bg-primary/90",
|
||||
destructive:
|
||||
"bg-destructive text-destructive-foreground shadow-sm hover:bg-destructive/90",
|
||||
outline:
|
||||
"border border-input bg-background shadow-sm hover:bg-accent hover:text-accent-foreground",
|
||||
secondary:
|
||||
"bg-secondary text-secondary-foreground shadow-sm hover:bg-secondary/80",
|
||||
ghost: "hover:bg-accent hover:text-accent-foreground",
|
||||
link: "text-primary underline-offset-4 hover:underline",
|
||||
aurora: "btn-aurora",
|
||||
"aurora-primary": "btn-aurora-primary",
|
||||
"aurora-success": "btn-aurora-success",
|
||||
"aurora-danger": "btn-aurora-danger",
|
||||
},
|
||||
size: {
|
||||
default: "h-9 px-4 py-2",
|
||||
sm: "h-8 rounded-md px-3 text-xs",
|
||||
lg: "h-10 rounded-md px-8",
|
||||
icon: "h-9 w-9",
|
||||
},
|
||||
},
|
||||
defaultVariants: {
|
||||
variant: "default",
|
||||
size: "default",
|
||||
},
|
||||
}
|
||||
)
|
||||
|
||||
export interface ButtonProps
|
||||
extends React.ButtonHTMLAttributes<HTMLButtonElement>,
|
||||
VariantProps<typeof buttonVariants> {
|
||||
asChild?: boolean
|
||||
}
|
||||
|
||||
const Button = React.forwardRef<HTMLButtonElement, ButtonProps>(
|
||||
({ className, variant, size, asChild = false, ...props }, ref) => {
|
||||
const Comp = asChild ? Slot : "button"
|
||||
return (
|
||||
<Comp
|
||||
className={cn(buttonVariants({ variant, size, className }))}
|
||||
ref={ref}
|
||||
{...props}
|
||||
/>
|
||||
)
|
||||
}
|
||||
)
|
||||
Button.displayName = "Button"
|
||||
|
||||
export { Button, buttonVariants }
|
||||
import * as React from "react"
|
||||
import { Slot } from "@radix-ui/react-slot"
|
||||
import { cva, type VariantProps } from "class-variance-authority"
|
||||
|
||||
import { cn } from "@/lib/utils"
|
||||
|
||||
const buttonVariants = cva(
|
||||
"inline-flex items-center justify-center gap-2 whitespace-nowrap rounded-md text-sm font-medium transition-colors focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-ring disabled:pointer-events-none disabled:opacity-50 [&_svg]:pointer-events-none [&_svg]:size-4 [&_svg]:shrink-0",
|
||||
{
|
||||
variants: {
|
||||
variant: {
|
||||
default:
|
||||
"bg-primary text-primary-foreground shadow hover:bg-primary/90",
|
||||
destructive:
|
||||
"bg-destructive text-destructive-foreground shadow-sm hover:bg-destructive/90",
|
||||
outline:
|
||||
"border border-input bg-background shadow-sm hover:bg-accent hover:text-accent-foreground",
|
||||
secondary:
|
||||
"bg-secondary text-secondary-foreground shadow-sm hover:bg-secondary/80",
|
||||
ghost: "hover:bg-accent hover:text-accent-foreground",
|
||||
link: "text-primary underline-offset-4 hover:underline",
|
||||
aurora: "btn-aurora",
|
||||
"aurora-primary": "btn-aurora-primary",
|
||||
"aurora-success": "btn-aurora-success",
|
||||
"aurora-danger": "btn-aurora-danger",
|
||||
},
|
||||
size: {
|
||||
default: "h-9 px-4 py-2",
|
||||
sm: "h-8 rounded-md px-3 text-xs",
|
||||
lg: "h-10 rounded-md px-8",
|
||||
icon: "h-9 w-9",
|
||||
},
|
||||
},
|
||||
defaultVariants: {
|
||||
variant: "default",
|
||||
size: "default",
|
||||
},
|
||||
}
|
||||
)
|
||||
|
||||
export interface ButtonProps
|
||||
extends React.ButtonHTMLAttributes<HTMLButtonElement>,
|
||||
VariantProps<typeof buttonVariants> {
|
||||
asChild?: boolean
|
||||
}
|
||||
|
||||
const Button = React.forwardRef<HTMLButtonElement, ButtonProps>(
|
||||
({ className, variant, size, asChild = false, ...props }, ref) => {
|
||||
const Comp = asChild ? Slot : "button"
|
||||
return (
|
||||
<Comp
|
||||
className={cn(buttonVariants({ variant, size, className }))}
|
||||
ref={ref}
|
||||
{...props}
|
||||
/>
|
||||
)
|
||||
}
|
||||
)
|
||||
Button.displayName = "Button"
|
||||
|
||||
export { Button, buttonVariants }
|
||||
|
|
|
|||
|
|
@ -1,165 +1,165 @@
|
|||
# Agent Session Flow & Operator Guide
|
||||
|
||||
This document defines the canonical workflow for human operators using `bb agent` to coordinate work in the Beadboard repo.
|
||||
|
||||
## Core Principle: Two Sources of Truth
|
||||
|
||||
1. **Work Lifecycle**: `bd` (Beads) is the ONLY source of truth for what work is happening (`in_progress`, `done`, dependencies).
|
||||
2. **Coordination**: `bb agent` is the source of truth for *who* is doing it and *how* they are coordinating (reservations, handoffs).
|
||||
|
||||
**Rule**: Never write to `.beads/issues.jsonl` directly. Always use `bd` commands.
|
||||
|
||||
## Session Lifecycle
|
||||
|
||||
### 1. Identity Check (Start of Session)
|
||||
|
||||
Before claiming work, ensure your agent identity is registered and active.
|
||||
|
||||
```bash
|
||||
# Check if you are registered
|
||||
bb agent show --agent agent-ui-1
|
||||
|
||||
# If not, register (idempotent, use --force-update to change role/display)
|
||||
bb agent register --name agent-ui-1 --role ui --display "UI Agent 1"
|
||||
```
|
||||
|
||||
### 2. Picking and Claiming Work
|
||||
|
||||
Use `bd` to find and claim work. This is the "clock in" event.
|
||||
|
||||
```bash
|
||||
# 1. Find ready work (unblocked)
|
||||
bd ready
|
||||
|
||||
# 2. Inspect the bead
|
||||
bd show bb-dcv.5
|
||||
|
||||
# 3. CLAIM the bead (Atomic Claim)
|
||||
# This sets status=in_progress AND assigns it to you in one atomic op.
|
||||
bd update bb-dcv.5 --status in_progress --notes "Starting docs work" --claim
|
||||
```
|
||||
|
||||
### 3. Coordination (During Work)
|
||||
|
||||
While working, use `bb agent` to coordinate with other agents or reserve contested resources.
|
||||
|
||||
#### Reservations (Traffic Control)
|
||||
Prevent collisions on shared files or subsystems.
|
||||
|
||||
```bash
|
||||
# Reserve a scope (default TTL 120m)
|
||||
bb agent reserve --agent agent-ui-1 --bead bb-dcv.5 --scope "src/components/graph/*"
|
||||
|
||||
# Check status of your reservation
|
||||
bb agent status --bead bb-dcv.5
|
||||
```
|
||||
|
||||
#### Communication (Handoffs & Blockers)
|
||||
Send structured signals to other agents.
|
||||
|
||||
```bash
|
||||
# BLOCKER: Request help
|
||||
bb agent send \
|
||||
--from agent-ui-1 \
|
||||
--to agent-backend-1 \
|
||||
--bead bb-dcv.5 \
|
||||
--category BLOCKED \
|
||||
--subject "API 404 on /b/users" \
|
||||
--body "Endpoint missing. Blocking UI integration."
|
||||
|
||||
# HANDOFF: Pass context
|
||||
bb agent send \
|
||||
--from agent-ui-1 \
|
||||
--to agent-qa-1 \
|
||||
--bead bb-dcv.5 \
|
||||
--category HANDOFF \
|
||||
--subject "Ready for verification" \
|
||||
--body "UI complete. Verify at /graph and /kanban."
|
||||
```
|
||||
|
||||
#### Checking Mail
|
||||
```bash
|
||||
# Check inbox
|
||||
bb agent inbox --agent agent-ui-1 --state unread
|
||||
|
||||
# Read a message (marks as read)
|
||||
bb agent read --agent agent-ui-1 --message msg_id_123
|
||||
|
||||
# Acknowledge a message (required for HANDOFF/BLOCKED)
|
||||
bb agent ack --agent agent-ui-1 --message msg_id_123
|
||||
```
|
||||
|
||||
### 4. Completion (End of Session)
|
||||
|
||||
Wrap up the session cleanly.
|
||||
|
||||
1. **Release Reservations**:
|
||||
```bash
|
||||
# Release specific scope
|
||||
bb agent release --agent agent-ui-1 --scope "src/components/graph/*"
|
||||
```
|
||||
|
||||
2. **Update Bead Status**:
|
||||
```bash
|
||||
# Post evidence/results
|
||||
bd update bb-dcv.5 --notes "Docs created. Validation passed."
|
||||
|
||||
# Close the bead
|
||||
bd close bb-dcv.5 --reason "Completed all acceptance criteria"
|
||||
```
|
||||
|
||||
## UX & Output Formats
|
||||
|
||||
All `bb agent` commands support human-friendly output (default) and machine-readable JSON.
|
||||
|
||||
### Human Format (Default)
|
||||
Optimized for operator readability.
|
||||
|
||||
```text
|
||||
$ bb agent register --name agent-ui-1 --role ui
|
||||
✓ Agent registered: agent-ui-1 (role: ui)
|
||||
```
|
||||
|
||||
### JSON Format (`--json`)
|
||||
Optimized for tool parsing. Always returns a standard envelope.
|
||||
|
||||
```bash
|
||||
$ bb agent register --name agent-ui-1 --role ui --json
|
||||
```
|
||||
|
||||
```json
|
||||
{
|
||||
"ok": true,
|
||||
"command": "agent register",
|
||||
"data": {
|
||||
"agent_id": "agent-ui-1",
|
||||
"role": "ui",
|
||||
"status": "idle",
|
||||
...
|
||||
},
|
||||
"error": null
|
||||
}
|
||||
```
|
||||
|
||||
### Error Handling
|
||||
|
||||
Errors always return `ok: false` with a stable error code.
|
||||
|
||||
```json
|
||||
{
|
||||
"ok": false,
|
||||
"command": "agent send",
|
||||
"data": null,
|
||||
"error": {
|
||||
"code": "UNKNOWN_RECIPIENT",
|
||||
"message": "Agent 'ghost-1' not found"
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
## Anti-Patterns (Don't Do This)
|
||||
|
||||
1. **Ghosting**: Claiming a bead but not registering an agent identity.
|
||||
2. **Squatting**: Holding a reservation (`--ttl 1440`) while not actively working.
|
||||
3. **Bypassing**: Writing to `issues.jsonl` directly instead of using `bd`.
|
||||
4. **Zombie Claims**: Forgetting to `bd close` or `bd update --status todo` when stopping work.
|
||||
# Agent Session Flow & Operator Guide
|
||||
|
||||
This document defines the canonical workflow for human operators using `bb agent` to coordinate work in the Beadboard repo.
|
||||
|
||||
## Core Principle: Two Sources of Truth
|
||||
|
||||
1. **Work Lifecycle**: `bd` (Beads) is the ONLY source of truth for what work is happening (`in_progress`, `done`, dependencies).
|
||||
2. **Coordination**: `bb agent` is the source of truth for *who* is doing it and *how* they are coordinating (reservations, handoffs).
|
||||
|
||||
**Rule**: Never write to `.beads/issues.jsonl` directly. Always use `bd` commands.
|
||||
|
||||
## Session Lifecycle
|
||||
|
||||
### 1. Identity Check (Start of Session)
|
||||
|
||||
Before claiming work, ensure your agent identity is registered and active.
|
||||
|
||||
```bash
|
||||
# Check if you are registered
|
||||
bb agent show --agent agent-ui-1
|
||||
|
||||
# If not, register (idempotent, use --force-update to change role/display)
|
||||
bb agent register --name agent-ui-1 --role ui --display "UI Agent 1"
|
||||
```
|
||||
|
||||
### 2. Picking and Claiming Work
|
||||
|
||||
Use `bd` to find and claim work. This is the "clock in" event.
|
||||
|
||||
```bash
|
||||
# 1. Find ready work (unblocked)
|
||||
bd ready
|
||||
|
||||
# 2. Inspect the bead
|
||||
bd show bb-dcv.5
|
||||
|
||||
# 3. CLAIM the bead (Atomic Claim)
|
||||
# This sets status=in_progress AND assigns it to you in one atomic op.
|
||||
bd update bb-dcv.5 --status in_progress --notes "Starting docs work" --claim
|
||||
```
|
||||
|
||||
### 3. Coordination (During Work)
|
||||
|
||||
While working, use `bb agent` to coordinate with other agents or reserve contested resources.
|
||||
|
||||
#### Reservations (Traffic Control)
|
||||
Prevent collisions on shared files or subsystems.
|
||||
|
||||
```bash
|
||||
# Reserve a scope (default TTL 120m)
|
||||
bb agent reserve --agent agent-ui-1 --bead bb-dcv.5 --scope "src/components/graph/*"
|
||||
|
||||
# Check status of your reservation
|
||||
bb agent status --bead bb-dcv.5
|
||||
```
|
||||
|
||||
#### Communication (Handoffs & Blockers)
|
||||
Send structured signals to other agents.
|
||||
|
||||
```bash
|
||||
# BLOCKER: Request help
|
||||
bb agent send \
|
||||
--from agent-ui-1 \
|
||||
--to agent-backend-1 \
|
||||
--bead bb-dcv.5 \
|
||||
--category BLOCKED \
|
||||
--subject "API 404 on /b/users" \
|
||||
--body "Endpoint missing. Blocking UI integration."
|
||||
|
||||
# HANDOFF: Pass context
|
||||
bb agent send \
|
||||
--from agent-ui-1 \
|
||||
--to agent-qa-1 \
|
||||
--bead bb-dcv.5 \
|
||||
--category HANDOFF \
|
||||
--subject "Ready for verification" \
|
||||
--body "UI complete. Verify at /graph and /kanban."
|
||||
```
|
||||
|
||||
#### Checking Mail
|
||||
```bash
|
||||
# Check inbox
|
||||
bb agent inbox --agent agent-ui-1 --state unread
|
||||
|
||||
# Read a message (marks as read)
|
||||
bb agent read --agent agent-ui-1 --message msg_id_123
|
||||
|
||||
# Acknowledge a message (required for HANDOFF/BLOCKED)
|
||||
bb agent ack --agent agent-ui-1 --message msg_id_123
|
||||
```
|
||||
|
||||
### 4. Completion (End of Session)
|
||||
|
||||
Wrap up the session cleanly.
|
||||
|
||||
1. **Release Reservations**:
|
||||
```bash
|
||||
# Release specific scope
|
||||
bb agent release --agent agent-ui-1 --scope "src/components/graph/*"
|
||||
```
|
||||
|
||||
2. **Update Bead Status**:
|
||||
```bash
|
||||
# Post evidence/results
|
||||
bd update bb-dcv.5 --notes "Docs created. Validation passed."
|
||||
|
||||
# Close the bead
|
||||
bd close bb-dcv.5 --reason "Completed all acceptance criteria"
|
||||
```
|
||||
|
||||
## UX & Output Formats
|
||||
|
||||
All `bb agent` commands support human-friendly output (default) and machine-readable JSON.
|
||||
|
||||
### Human Format (Default)
|
||||
Optimized for operator readability.
|
||||
|
||||
```text
|
||||
$ bb agent register --name agent-ui-1 --role ui
|
||||
✓ Agent registered: agent-ui-1 (role: ui)
|
||||
```
|
||||
|
||||
### JSON Format (`--json`)
|
||||
Optimized for tool parsing. Always returns a standard envelope.
|
||||
|
||||
```bash
|
||||
$ bb agent register --name agent-ui-1 --role ui --json
|
||||
```
|
||||
|
||||
```json
|
||||
{
|
||||
"ok": true,
|
||||
"command": "agent register",
|
||||
"data": {
|
||||
"agent_id": "agent-ui-1",
|
||||
"role": "ui",
|
||||
"status": "idle",
|
||||
...
|
||||
},
|
||||
"error": null
|
||||
}
|
||||
```
|
||||
|
||||
### Error Handling
|
||||
|
||||
Errors always return `ok: false` with a stable error code.
|
||||
|
||||
```json
|
||||
{
|
||||
"ok": false,
|
||||
"command": "agent send",
|
||||
"data": null,
|
||||
"error": {
|
||||
"code": "UNKNOWN_RECIPIENT",
|
||||
"message": "Agent 'ghost-1' not found"
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
## Anti-Patterns (Don't Do This)
|
||||
|
||||
1. **Ghosting**: Claiming a bead but not registering an agent identity.
|
||||
2. **Squatting**: Holding a reservation (`--ttl 1440`) while not actively working.
|
||||
3. **Bypassing**: Writing to `issues.jsonl` directly instead of using `bd`.
|
||||
4. **Zombie Claims**: Forgetting to `bd close` or `bd update --status todo` when stopping work.
|
||||
|
|
|
|||
|
|
@ -1,283 +1,283 @@
|
|||
# BeadBoard API Reference
|
||||
|
||||
## Overview
|
||||
BeadBoard exposes REST endpoints for reading bead data, managing agent coordination, and streaming real-time activity. All endpoints return JSON (unless noted otherwise).
|
||||
|
||||
## Bead Management
|
||||
|
||||
### `GET /api/beads/read`
|
||||
Read beads from the current or specified project.
|
||||
|
||||
**Query Parameters:**
|
||||
- `project` (optional): Project key for scope resolution
|
||||
- `mode` (optional): `single` or `aggregate`
|
||||
|
||||
**Response:**
|
||||
```json
|
||||
{
|
||||
"issues": [...],
|
||||
"projectRoot": "/path/to/project"
|
||||
}
|
||||
```
|
||||
|
||||
### `POST /api/beads/create`
|
||||
Create a new bead.
|
||||
|
||||
**Body:**
|
||||
```json
|
||||
{
|
||||
"title": "Task title",
|
||||
"description": "Optional description",
|
||||
"status": "open",
|
||||
"priority": "p2",
|
||||
"issue_type": "task"
|
||||
}
|
||||
```
|
||||
|
||||
### `POST /api/beads/update`
|
||||
Update an existing bead.
|
||||
|
||||
**Body:**
|
||||
```json
|
||||
{
|
||||
"id": "bb-abc",
|
||||
"updates": {
|
||||
"status": "in_progress",
|
||||
"assignee": "agent-1"
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### `POST /api/beads/close`
|
||||
Close a bead.
|
||||
|
||||
**Body:**
|
||||
```json
|
||||
{
|
||||
"id": "bb-abc",
|
||||
"reason": "Completion reason"
|
||||
}
|
||||
```
|
||||
|
||||
### `POST /api/beads/reopen`
|
||||
Reopen a closed bead.
|
||||
|
||||
**Body:**
|
||||
```json
|
||||
{
|
||||
"id": "bb-abc"
|
||||
}
|
||||
```
|
||||
|
||||
### `POST /api/beads/comment`
|
||||
Add a comment to a bead.
|
||||
|
||||
**Body:**
|
||||
```json
|
||||
{
|
||||
"id": "bb-abc",
|
||||
"comment": "Comment text",
|
||||
"author": "agent-1"
|
||||
}
|
||||
```
|
||||
|
||||
## Agent Coordination
|
||||
|
||||
### `GET /api/agents/[agentId]/stats`
|
||||
Fetch productivity metrics for a specific agent.
|
||||
|
||||
**Path Parameters:**
|
||||
- `agentId`: Agent identifier
|
||||
|
||||
**Response:**
|
||||
```json
|
||||
{
|
||||
"activeTasks": 3,
|
||||
"completedTasks": 12,
|
||||
"handoffsSent": 8,
|
||||
"recentWins": [
|
||||
{ "id": "bb-xyz", "title": "Task title" }
|
||||
]
|
||||
}
|
||||
```
|
||||
|
||||
### `GET /api/sessions`
|
||||
Fetch the agent sessions task feed.
|
||||
|
||||
**Query Parameters:**
|
||||
- `project` (optional): Project scope
|
||||
- `mode` (optional): `single` or `aggregate`
|
||||
|
||||
**Response:**
|
||||
```json
|
||||
{
|
||||
"buckets": [
|
||||
{
|
||||
"epic": {
|
||||
"id": "bb-epic",
|
||||
"title": "Epic Title",
|
||||
"status": "open"
|
||||
},
|
||||
"tasks": [
|
||||
{
|
||||
"id": "bb-task",
|
||||
"title": "Task Title",
|
||||
"epicId": "bb-epic",
|
||||
"status": "in_progress",
|
||||
"sessionState": "active",
|
||||
"owner": "agent-1",
|
||||
"lastActor": "agent-1",
|
||||
"lastActivityAt": "2026-02-16T05:00:00Z",
|
||||
"communication": {
|
||||
"unreadCount": 2,
|
||||
"pendingRequired": true,
|
||||
"latestSnippet": "Blocked on API"
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
```
|
||||
|
||||
### `GET /api/sessions/[beadId]/conversation`
|
||||
Get the full conversation thread for a bead, including comments and agent messages.
|
||||
|
||||
**Path Parameters:**
|
||||
- `beadId`: Bead identifier
|
||||
|
||||
**Response:**
|
||||
```json
|
||||
{
|
||||
"comments": [...],
|
||||
"messages": [...]
|
||||
}
|
||||
```
|
||||
|
||||
### `POST /api/sessions/[beadId]/comment`
|
||||
Add a comment to a bead session.
|
||||
|
||||
**Path Parameters:**
|
||||
- `beadId`: Bead identifier
|
||||
|
||||
**Body:**
|
||||
```json
|
||||
{
|
||||
"comment": "Comment text",
|
||||
"author": "agent-1"
|
||||
}
|
||||
```
|
||||
|
||||
### `POST /api/sessions/[beadId]/messages/[messageId]/read`
|
||||
Mark an agent message as read.
|
||||
|
||||
**Path Parameters:**
|
||||
- `beadId`: Bead identifier
|
||||
- `messageId`: Message identifier
|
||||
|
||||
### `POST /api/sessions/[beadId]/messages/[messageId]/ack`
|
||||
Acknowledge an agent message (required for HANDOFF/BLOCKED categories).
|
||||
|
||||
**Path Parameters:**
|
||||
- `beadId`: Bead identifier
|
||||
- `messageId`: Message identifier
|
||||
|
||||
## Activity & Events
|
||||
|
||||
### `GET /api/activity`
|
||||
Fetch recent activity events (history buffer).
|
||||
|
||||
**Response:**
|
||||
```json
|
||||
{
|
||||
"events": [
|
||||
{
|
||||
"id": "evt-123",
|
||||
"beadId": "bb-abc",
|
||||
"kind": "status_changed",
|
||||
"actor": "agent-1",
|
||||
"timestamp": "2026-02-16T05:00:00Z",
|
||||
"changes": {
|
||||
"from": "todo",
|
||||
"to": "in_progress"
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
```
|
||||
|
||||
### `GET /api/events`
|
||||
Server-Sent Events stream for real-time activity.
|
||||
|
||||
**Response:** SSE stream with `event` and `data` fields.
|
||||
|
||||
**Event Types:**
|
||||
- `activity`: New activity event
|
||||
- `bead_updated`: Bead state changed
|
||||
- `agent_registered`: New agent registered
|
||||
|
||||
## Project Management
|
||||
|
||||
### `GET /api/projects`
|
||||
List all registered projects.
|
||||
|
||||
**Response:**
|
||||
```json
|
||||
{
|
||||
"projects": [
|
||||
{
|
||||
"key": "proj-1",
|
||||
"root": "/path/to/project",
|
||||
"name": "Project Name"
|
||||
}
|
||||
]
|
||||
}
|
||||
```
|
||||
|
||||
### `POST /api/scan`
|
||||
Scan filesystem for bead-enabled projects.
|
||||
|
||||
**Body:**
|
||||
```json
|
||||
{
|
||||
"paths": ["/path/to/scan"]
|
||||
}
|
||||
```
|
||||
|
||||
**Response:**
|
||||
```json
|
||||
{
|
||||
"discovered": [
|
||||
{
|
||||
"root": "/path/to/project",
|
||||
"beadCount": 42
|
||||
}
|
||||
]
|
||||
}
|
||||
```
|
||||
|
||||
## Error Handling
|
||||
|
||||
All endpoints follow a consistent error format:
|
||||
|
||||
```json
|
||||
{
|
||||
"error": "Error message",
|
||||
"code": "ERROR_CODE",
|
||||
"details": {}
|
||||
}
|
||||
```
|
||||
|
||||
**Common Error Codes:**
|
||||
- `INVALID_REQUEST`: Malformed request body or parameters
|
||||
- `NOT_FOUND`: Resource does not exist
|
||||
- `PERMISSION_DENIED`: Operation not allowed
|
||||
- `INTERNAL_ERROR`: Server-side error
|
||||
|
||||
## Rate Limiting
|
||||
|
||||
No rate limiting is currently enforced for local BeadBoard instances. If deploying publicly, implement rate limiting externally.
|
||||
|
||||
## Authentication
|
||||
|
||||
BeadBoard runs as a local dashboard with no authentication. If exposing over a network, secure access using reverse proxy authentication or network isolation.
|
||||
# BeadBoard API Reference
|
||||
|
||||
## Overview
|
||||
BeadBoard exposes REST endpoints for reading bead data, managing agent coordination, and streaming real-time activity. All endpoints return JSON (unless noted otherwise).
|
||||
|
||||
## Bead Management
|
||||
|
||||
### `GET /api/beads/read`
|
||||
Read beads from the current or specified project.
|
||||
|
||||
**Query Parameters:**
|
||||
- `project` (optional): Project key for scope resolution
|
||||
- `mode` (optional): `single` or `aggregate`
|
||||
|
||||
**Response:**
|
||||
```json
|
||||
{
|
||||
"issues": [...],
|
||||
"projectRoot": "/path/to/project"
|
||||
}
|
||||
```
|
||||
|
||||
### `POST /api/beads/create`
|
||||
Create a new bead.
|
||||
|
||||
**Body:**
|
||||
```json
|
||||
{
|
||||
"title": "Task title",
|
||||
"description": "Optional description",
|
||||
"status": "open",
|
||||
"priority": "p2",
|
||||
"issue_type": "task"
|
||||
}
|
||||
```
|
||||
|
||||
### `POST /api/beads/update`
|
||||
Update an existing bead.
|
||||
|
||||
**Body:**
|
||||
```json
|
||||
{
|
||||
"id": "bb-abc",
|
||||
"updates": {
|
||||
"status": "in_progress",
|
||||
"assignee": "agent-1"
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### `POST /api/beads/close`
|
||||
Close a bead.
|
||||
|
||||
**Body:**
|
||||
```json
|
||||
{
|
||||
"id": "bb-abc",
|
||||
"reason": "Completion reason"
|
||||
}
|
||||
```
|
||||
|
||||
### `POST /api/beads/reopen`
|
||||
Reopen a closed bead.
|
||||
|
||||
**Body:**
|
||||
```json
|
||||
{
|
||||
"id": "bb-abc"
|
||||
}
|
||||
```
|
||||
|
||||
### `POST /api/beads/comment`
|
||||
Add a comment to a bead.
|
||||
|
||||
**Body:**
|
||||
```json
|
||||
{
|
||||
"id": "bb-abc",
|
||||
"comment": "Comment text",
|
||||
"author": "agent-1"
|
||||
}
|
||||
```
|
||||
|
||||
## Agent Coordination
|
||||
|
||||
### `GET /api/agents/[agentId]/stats`
|
||||
Fetch productivity metrics for a specific agent.
|
||||
|
||||
**Path Parameters:**
|
||||
- `agentId`: Agent identifier
|
||||
|
||||
**Response:**
|
||||
```json
|
||||
{
|
||||
"activeTasks": 3,
|
||||
"completedTasks": 12,
|
||||
"handoffsSent": 8,
|
||||
"recentWins": [
|
||||
{ "id": "bb-xyz", "title": "Task title" }
|
||||
]
|
||||
}
|
||||
```
|
||||
|
||||
### `GET /api/sessions`
|
||||
Fetch the agent sessions task feed.
|
||||
|
||||
**Query Parameters:**
|
||||
- `project` (optional): Project scope
|
||||
- `mode` (optional): `single` or `aggregate`
|
||||
|
||||
**Response:**
|
||||
```json
|
||||
{
|
||||
"buckets": [
|
||||
{
|
||||
"epic": {
|
||||
"id": "bb-epic",
|
||||
"title": "Epic Title",
|
||||
"status": "open"
|
||||
},
|
||||
"tasks": [
|
||||
{
|
||||
"id": "bb-task",
|
||||
"title": "Task Title",
|
||||
"epicId": "bb-epic",
|
||||
"status": "in_progress",
|
||||
"sessionState": "active",
|
||||
"owner": "agent-1",
|
||||
"lastActor": "agent-1",
|
||||
"lastActivityAt": "2026-02-16T05:00:00Z",
|
||||
"communication": {
|
||||
"unreadCount": 2,
|
||||
"pendingRequired": true,
|
||||
"latestSnippet": "Blocked on API"
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
```
|
||||
|
||||
### `GET /api/sessions/[beadId]/conversation`
|
||||
Get the full conversation thread for a bead, including comments and agent messages.
|
||||
|
||||
**Path Parameters:**
|
||||
- `beadId`: Bead identifier
|
||||
|
||||
**Response:**
|
||||
```json
|
||||
{
|
||||
"comments": [...],
|
||||
"messages": [...]
|
||||
}
|
||||
```
|
||||
|
||||
### `POST /api/sessions/[beadId]/comment`
|
||||
Add a comment to a bead session.
|
||||
|
||||
**Path Parameters:**
|
||||
- `beadId`: Bead identifier
|
||||
|
||||
**Body:**
|
||||
```json
|
||||
{
|
||||
"comment": "Comment text",
|
||||
"author": "agent-1"
|
||||
}
|
||||
```
|
||||
|
||||
### `POST /api/sessions/[beadId]/messages/[messageId]/read`
|
||||
Mark an agent message as read.
|
||||
|
||||
**Path Parameters:**
|
||||
- `beadId`: Bead identifier
|
||||
- `messageId`: Message identifier
|
||||
|
||||
### `POST /api/sessions/[beadId]/messages/[messageId]/ack`
|
||||
Acknowledge an agent message (required for HANDOFF/BLOCKED categories).
|
||||
|
||||
**Path Parameters:**
|
||||
- `beadId`: Bead identifier
|
||||
- `messageId`: Message identifier
|
||||
|
||||
## Activity & Events
|
||||
|
||||
### `GET /api/activity`
|
||||
Fetch recent activity events (history buffer).
|
||||
|
||||
**Response:**
|
||||
```json
|
||||
{
|
||||
"events": [
|
||||
{
|
||||
"id": "evt-123",
|
||||
"beadId": "bb-abc",
|
||||
"kind": "status_changed",
|
||||
"actor": "agent-1",
|
||||
"timestamp": "2026-02-16T05:00:00Z",
|
||||
"changes": {
|
||||
"from": "todo",
|
||||
"to": "in_progress"
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
```
|
||||
|
||||
### `GET /api/events`
|
||||
Server-Sent Events stream for real-time activity.
|
||||
|
||||
**Response:** SSE stream with `event` and `data` fields.
|
||||
|
||||
**Event Types:**
|
||||
- `activity`: New activity event
|
||||
- `bead_updated`: Bead state changed
|
||||
- `agent_registered`: New agent registered
|
||||
|
||||
## Project Management
|
||||
|
||||
### `GET /api/projects`
|
||||
List all registered projects.
|
||||
|
||||
**Response:**
|
||||
```json
|
||||
{
|
||||
"projects": [
|
||||
{
|
||||
"key": "proj-1",
|
||||
"root": "/path/to/project",
|
||||
"name": "Project Name"
|
||||
}
|
||||
]
|
||||
}
|
||||
```
|
||||
|
||||
### `POST /api/scan`
|
||||
Scan filesystem for bead-enabled projects.
|
||||
|
||||
**Body:**
|
||||
```json
|
||||
{
|
||||
"paths": ["/path/to/scan"]
|
||||
}
|
||||
```
|
||||
|
||||
**Response:**
|
||||
```json
|
||||
{
|
||||
"discovered": [
|
||||
{
|
||||
"root": "/path/to/project",
|
||||
"beadCount": 42
|
||||
}
|
||||
]
|
||||
}
|
||||
```
|
||||
|
||||
## Error Handling
|
||||
|
||||
All endpoints follow a consistent error format:
|
||||
|
||||
```json
|
||||
{
|
||||
"error": "Error message",
|
||||
"code": "ERROR_CODE",
|
||||
"details": {}
|
||||
}
|
||||
```
|
||||
|
||||
**Common Error Codes:**
|
||||
- `INVALID_REQUEST`: Malformed request body or parameters
|
||||
- `NOT_FOUND`: Resource does not exist
|
||||
- `PERMISSION_DENIED`: Operation not allowed
|
||||
- `INTERNAL_ERROR`: Server-side error
|
||||
|
||||
## Rate Limiting
|
||||
|
||||
No rate limiting is currently enforced for local BeadBoard instances. If deploying publicly, implement rate limiting externally.
|
||||
|
||||
## Authentication
|
||||
|
||||
BeadBoard runs as a local dashboard with no authentication. If exposing over a network, secure access using reverse proxy authentication or network isolation.
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
export default {
|
||||
plugins: {
|
||||
'@tailwindcss/postcss': {},
|
||||
},
|
||||
};
|
||||
export default {
|
||||
plugins: {
|
||||
'@tailwindcss/postcss': {},
|
||||
},
|
||||
};
|
||||
|
|
|
|||
|
|
@ -1,166 +1,166 @@
|
|||
diff --git a/.gitignore b/.gitignore
|
||||
index eb35607..596f42a 100644
|
||||
--- a/.gitignore
|
||||
+++ b/.gitignore
|
||||
@@ -3,3 +3,6 @@ node_modules/
|
||||
*.tsbuildinfo
|
||||
.worktrees/
|
||||
worktrees/
|
||||
+
|
||||
+# bv (beads viewer) local config and caches
|
||||
+.bv/
|
||||
diff --git a/src/app/globals.css b/src/app/globals.css
|
||||
index d17e938..a474080 100644
|
||||
--- a/src/app/globals.css
|
||||
+++ b/src/app/globals.css
|
||||
@@ -3,15 +3,15 @@
|
||||
@tailwind utilities;
|
||||
|
||||
:root {
|
||||
- --color-bg: #090c14;
|
||||
- --color-surface: #101827;
|
||||
- --color-surface-muted: #192336;
|
||||
- --color-surface-raised: #22314a;
|
||||
- --color-text-strong: #f6f8ff;
|
||||
- --color-text-body: #d8e0f1;
|
||||
- --color-text-muted: #9caccc;
|
||||
- --color-border-soft: rgba(145, 166, 204, 0.3);
|
||||
- --color-border-strong: rgba(187, 209, 246, 0.62);
|
||||
+ --color-bg: #090909;
|
||||
+ --color-surface: #161616;
|
||||
+ --color-surface-muted: #212121;
|
||||
+ --color-surface-raised: #2a2a2a;
|
||||
+ --color-text-strong: #f5f5f5;
|
||||
+ --color-text-body: #d0d0d0;
|
||||
+ --color-text-muted: #9a9a9a;
|
||||
+ --color-border-soft: rgba(255, 255, 255, 0.15);
|
||||
+ --color-border-strong: rgba(255, 255, 255, 0.3);
|
||||
|
||||
--status-open: #60a5fa;
|
||||
--status-progress: #fbbf24;
|
||||
@@ -38,10 +38,9 @@ body {
|
||||
|
||||
body {
|
||||
background:
|
||||
- radial-gradient(circle at 10% 12%, rgba(12, 138, 215, 0.34), transparent 36%),
|
||||
- radial-gradient(circle at 84% 20%, rgba(250, 122, 91, 0.18), transparent 30%),
|
||||
- radial-gradient(circle at 68% 88%, rgba(57, 189, 154, 0.14), transparent 36%),
|
||||
- linear-gradient(155deg, #05070d 0%, #0b1322 42%, #121e34 100%);
|
||||
+ radial-gradient(circle at 14% 12%, rgba(255, 255, 255, 0.05), transparent 36%),
|
||||
+ radial-gradient(circle at 84% 18%, rgba(255, 180, 80, 0.06), transparent 32%),
|
||||
+ linear-gradient(160deg, #070707 0%, #101010 48%, #161616 100%);
|
||||
color: var(--color-text-body);
|
||||
- font-family: 'Segoe UI', 'Aptos', Inter, system-ui, sans-serif;
|
||||
+ font-family: 'DM Sans', 'Segoe UI', Inter, system-ui, sans-serif;
|
||||
}
|
||||
diff --git a/src/app/layout.tsx b/src/app/layout.tsx
|
||||
index ff1ad90..1417e77 100644
|
||||
--- a/src/app/layout.tsx
|
||||
+++ b/src/app/layout.tsx
|
||||
@@ -1,7 +1,18 @@
|
||||
import type { Metadata } from 'next';
|
||||
+import { DM_Sans, JetBrains_Mono } from 'next/font/google';
|
||||
import type { ReactNode } from 'react';
|
||||
import './globals.css';
|
||||
|
||||
+const dmSans = DM_Sans({
|
||||
+ subsets: ['latin'],
|
||||
+ variable: '--font-ui',
|
||||
+});
|
||||
+
|
||||
+const jetbrainsMono = JetBrains_Mono({
|
||||
+ subsets: ['latin'],
|
||||
+ variable: '--font-mono',
|
||||
+});
|
||||
+
|
||||
export const metadata: Metadata = {
|
||||
title: 'BeadBoard',
|
||||
description: 'Windows-native Beads dashboard',
|
||||
@@ -10,7 +21,7 @@ export const metadata: Metadata = {
|
||||
export default function RootLayout({ children }: { children: ReactNode }) {
|
||||
return (
|
||||
<html lang="en">
|
||||
- <body>{children}</body>
|
||||
+ <body className={`${dmSans.variable} ${jetbrainsMono.variable}`}>{children}</body>
|
||||
</html>
|
||||
);
|
||||
}
|
||||
diff --git a/src/components/kanban/kanban-controls.tsx b/src/components/kanban/kanban-controls.tsx
|
||||
index 78b09f4..e1e04f9 100644
|
||||
--- a/src/components/kanban/kanban-controls.tsx
|
||||
+++ b/src/components/kanban/kanban-controls.tsx
|
||||
@@ -14,7 +14,7 @@ interface KanbanControlsProps {
|
||||
|
||||
export function KanbanControls({ filters, stats, onFiltersChange }: KanbanControlsProps) {
|
||||
const inputClass =
|
||||
- 'rounded-xl border border-border-soft bg-surface-muted/78 px-3 py-2.5 text-sm text-text-strong outline-none transition placeholder:text-text-muted focus:border-cyan-300/70 focus:ring-2 focus:ring-cyan-300/20';
|
||||
+ 'rounded-xl border border-border-soft bg-surface-muted/78 px-3 py-2.5 text-sm text-text-strong outline-none transition placeholder:text-text-muted focus:border-border-strong focus:ring-2 focus:ring-white/10';
|
||||
|
||||
return (
|
||||
<section className="grid gap-3">
|
||||
@@ -57,7 +57,7 @@ export function KanbanControls({ filters, stats, onFiltersChange }: KanbanContro
|
||||
type="checkbox"
|
||||
checked={filters.showClosed ?? false}
|
||||
onChange={(event) => onFiltersChange({ ...filters, showClosed: event.target.checked })}
|
||||
- className="h-4 w-4 accent-cyan-400"
|
||||
+ className="h-4 w-4 accent-amber-400"
|
||||
/>
|
||||
Show closed
|
||||
</label>
|
||||
diff --git a/src/components/shared/chip.tsx b/src/components/shared/chip.tsx
|
||||
index c1637e6..e29d49d 100644
|
||||
--- a/src/components/shared/chip.tsx
|
||||
+++ b/src/components/shared/chip.tsx
|
||||
@@ -7,7 +7,7 @@ interface ChipProps {
|
||||
|
||||
const CHIP_TONE_CLASS: Record<NonNullable<ChipProps['tone']>, string> = {
|
||||
default: 'border-border-soft bg-surface-muted/75 text-text-body',
|
||||
- status: 'border-cyan-300/30 bg-cyan-500/20 text-cyan-50',
|
||||
+ status: 'border-zinc-300/30 bg-zinc-500/20 text-zinc-100',
|
||||
priority: 'border-amber-300/30 bg-amber-500/20 text-amber-50',
|
||||
};
|
||||
|
||||
diff --git a/tailwind.config.ts b/tailwind.config.ts
|
||||
index 5ad9067..953965c 100644
|
||||
--- a/tailwind.config.ts
|
||||
+++ b/tailwind.config.ts
|
||||
@@ -5,8 +5,8 @@ const config: Config = {
|
||||
theme: {
|
||||
extend: {
|
||||
fontFamily: {
|
||||
- ui: ['Segoe UI', 'Inter', 'system-ui', 'sans-serif'],
|
||||
- mono: ['JetBrains Mono', 'Consolas', 'monospace'],
|
||||
+ ui: ['var(--font-ui)', 'Segoe UI', 'Inter', 'system-ui', 'sans-serif'],
|
||||
+ mono: ['var(--font-mono)', 'Consolas', 'monospace'],
|
||||
},
|
||||
colors: {
|
||||
bg: 'var(--color-bg)',
|
||||
diff --git a/tests/guards/kanban-responsive-contract.test.mjs b/tests/guards/kanban-responsive-contract.test.mjs
|
||||
index 4e02f28..3efabf4 100644
|
||||
--- a/tests/guards/kanban-responsive-contract.test.mjs
|
||||
+++ b/tests/guards/kanban-responsive-contract.test.mjs
|
||||
@@ -9,11 +9,12 @@ async function read(relativePath) {
|
||||
return fs.readFile(path.join(ROOT, relativePath), 'utf8');
|
||||
}
|
||||
|
||||
-test('kanban board uses intentional horizontal scroll affordances', async () => {
|
||||
+test('kanban board uses expandable vertical swimlanes', async () => {
|
||||
const board = await read('src/components/kanban/kanban-board.tsx');
|
||||
|
||||
- assert.match(board, /snap-x/);
|
||||
- assert.match(board, /overflow-x-auto/);
|
||||
+ assert.match(board, /aria-expanded/);
|
||||
+ assert.match(board, /onActivateStatus/);
|
||||
+ assert.match(board, /max-h-\[50vh\]/);
|
||||
});
|
||||
|
||||
test('kanban page defines mobile detail drawer behavior', async () => {
|
||||
@@ -21,6 +22,8 @@ test('kanban page defines mobile detail drawer behavior', async () => {
|
||||
|
||||
assert.match(page, /fixed inset-0/);
|
||||
assert.match(page, /lg:hidden/);
|
||||
+ assert.match(page, /lg:grid-cols-\[minmax\(0,1fr\)_minmax\(22rem,26rem\)\]/);
|
||||
+ assert.match(page, /lg:border-l/);
|
||||
});
|
||||
|
||||
test('kanban controls use fluid full-width sizing on small viewports', async () => {
|
||||
diff --git a/.gitignore b/.gitignore
|
||||
index eb35607..596f42a 100644
|
||||
--- a/.gitignore
|
||||
+++ b/.gitignore
|
||||
@@ -3,3 +3,6 @@ node_modules/
|
||||
*.tsbuildinfo
|
||||
.worktrees/
|
||||
worktrees/
|
||||
+
|
||||
+# bv (beads viewer) local config and caches
|
||||
+.bv/
|
||||
diff --git a/src/app/globals.css b/src/app/globals.css
|
||||
index d17e938..a474080 100644
|
||||
--- a/src/app/globals.css
|
||||
+++ b/src/app/globals.css
|
||||
@@ -3,15 +3,15 @@
|
||||
@tailwind utilities;
|
||||
|
||||
:root {
|
||||
- --color-bg: #090c14;
|
||||
- --color-surface: #101827;
|
||||
- --color-surface-muted: #192336;
|
||||
- --color-surface-raised: #22314a;
|
||||
- --color-text-strong: #f6f8ff;
|
||||
- --color-text-body: #d8e0f1;
|
||||
- --color-text-muted: #9caccc;
|
||||
- --color-border-soft: rgba(145, 166, 204, 0.3);
|
||||
- --color-border-strong: rgba(187, 209, 246, 0.62);
|
||||
+ --color-bg: #090909;
|
||||
+ --color-surface: #161616;
|
||||
+ --color-surface-muted: #212121;
|
||||
+ --color-surface-raised: #2a2a2a;
|
||||
+ --color-text-strong: #f5f5f5;
|
||||
+ --color-text-body: #d0d0d0;
|
||||
+ --color-text-muted: #9a9a9a;
|
||||
+ --color-border-soft: rgba(255, 255, 255, 0.15);
|
||||
+ --color-border-strong: rgba(255, 255, 255, 0.3);
|
||||
|
||||
--status-open: #60a5fa;
|
||||
--status-progress: #fbbf24;
|
||||
@@ -38,10 +38,9 @@ body {
|
||||
|
||||
body {
|
||||
background:
|
||||
- radial-gradient(circle at 10% 12%, rgba(12, 138, 215, 0.34), transparent 36%),
|
||||
- radial-gradient(circle at 84% 20%, rgba(250, 122, 91, 0.18), transparent 30%),
|
||||
- radial-gradient(circle at 68% 88%, rgba(57, 189, 154, 0.14), transparent 36%),
|
||||
- linear-gradient(155deg, #05070d 0%, #0b1322 42%, #121e34 100%);
|
||||
+ radial-gradient(circle at 14% 12%, rgba(255, 255, 255, 0.05), transparent 36%),
|
||||
+ radial-gradient(circle at 84% 18%, rgba(255, 180, 80, 0.06), transparent 32%),
|
||||
+ linear-gradient(160deg, #070707 0%, #101010 48%, #161616 100%);
|
||||
color: var(--color-text-body);
|
||||
- font-family: 'Segoe UI', 'Aptos', Inter, system-ui, sans-serif;
|
||||
+ font-family: 'DM Sans', 'Segoe UI', Inter, system-ui, sans-serif;
|
||||
}
|
||||
diff --git a/src/app/layout.tsx b/src/app/layout.tsx
|
||||
index ff1ad90..1417e77 100644
|
||||
--- a/src/app/layout.tsx
|
||||
+++ b/src/app/layout.tsx
|
||||
@@ -1,7 +1,18 @@
|
||||
import type { Metadata } from 'next';
|
||||
+import { DM_Sans, JetBrains_Mono } from 'next/font/google';
|
||||
import type { ReactNode } from 'react';
|
||||
import './globals.css';
|
||||
|
||||
+const dmSans = DM_Sans({
|
||||
+ subsets: ['latin'],
|
||||
+ variable: '--font-ui',
|
||||
+});
|
||||
+
|
||||
+const jetbrainsMono = JetBrains_Mono({
|
||||
+ subsets: ['latin'],
|
||||
+ variable: '--font-mono',
|
||||
+});
|
||||
+
|
||||
export const metadata: Metadata = {
|
||||
title: 'BeadBoard',
|
||||
description: 'Windows-native Beads dashboard',
|
||||
@@ -10,7 +21,7 @@ export const metadata: Metadata = {
|
||||
export default function RootLayout({ children }: { children: ReactNode }) {
|
||||
return (
|
||||
<html lang="en">
|
||||
- <body>{children}</body>
|
||||
+ <body className={`${dmSans.variable} ${jetbrainsMono.variable}`}>{children}</body>
|
||||
</html>
|
||||
);
|
||||
}
|
||||
diff --git a/src/components/kanban/kanban-controls.tsx b/src/components/kanban/kanban-controls.tsx
|
||||
index 78b09f4..e1e04f9 100644
|
||||
--- a/src/components/kanban/kanban-controls.tsx
|
||||
+++ b/src/components/kanban/kanban-controls.tsx
|
||||
@@ -14,7 +14,7 @@ interface KanbanControlsProps {
|
||||
|
||||
export function KanbanControls({ filters, stats, onFiltersChange }: KanbanControlsProps) {
|
||||
const inputClass =
|
||||
- 'rounded-xl border border-border-soft bg-surface-muted/78 px-3 py-2.5 text-sm text-text-strong outline-none transition placeholder:text-text-muted focus:border-cyan-300/70 focus:ring-2 focus:ring-cyan-300/20';
|
||||
+ 'rounded-xl border border-border-soft bg-surface-muted/78 px-3 py-2.5 text-sm text-text-strong outline-none transition placeholder:text-text-muted focus:border-border-strong focus:ring-2 focus:ring-white/10';
|
||||
|
||||
return (
|
||||
<section className="grid gap-3">
|
||||
@@ -57,7 +57,7 @@ export function KanbanControls({ filters, stats, onFiltersChange }: KanbanContro
|
||||
type="checkbox"
|
||||
checked={filters.showClosed ?? false}
|
||||
onChange={(event) => onFiltersChange({ ...filters, showClosed: event.target.checked })}
|
||||
- className="h-4 w-4 accent-cyan-400"
|
||||
+ className="h-4 w-4 accent-amber-400"
|
||||
/>
|
||||
Show closed
|
||||
</label>
|
||||
diff --git a/src/components/shared/chip.tsx b/src/components/shared/chip.tsx
|
||||
index c1637e6..e29d49d 100644
|
||||
--- a/src/components/shared/chip.tsx
|
||||
+++ b/src/components/shared/chip.tsx
|
||||
@@ -7,7 +7,7 @@ interface ChipProps {
|
||||
|
||||
const CHIP_TONE_CLASS: Record<NonNullable<ChipProps['tone']>, string> = {
|
||||
default: 'border-border-soft bg-surface-muted/75 text-text-body',
|
||||
- status: 'border-cyan-300/30 bg-cyan-500/20 text-cyan-50',
|
||||
+ status: 'border-zinc-300/30 bg-zinc-500/20 text-zinc-100',
|
||||
priority: 'border-amber-300/30 bg-amber-500/20 text-amber-50',
|
||||
};
|
||||
|
||||
diff --git a/tailwind.config.ts b/tailwind.config.ts
|
||||
index 5ad9067..953965c 100644
|
||||
--- a/tailwind.config.ts
|
||||
+++ b/tailwind.config.ts
|
||||
@@ -5,8 +5,8 @@ const config: Config = {
|
||||
theme: {
|
||||
extend: {
|
||||
fontFamily: {
|
||||
- ui: ['Segoe UI', 'Inter', 'system-ui', 'sans-serif'],
|
||||
- mono: ['JetBrains Mono', 'Consolas', 'monospace'],
|
||||
+ ui: ['var(--font-ui)', 'Segoe UI', 'Inter', 'system-ui', 'sans-serif'],
|
||||
+ mono: ['var(--font-mono)', 'Consolas', 'monospace'],
|
||||
},
|
||||
colors: {
|
||||
bg: 'var(--color-bg)',
|
||||
diff --git a/tests/guards/kanban-responsive-contract.test.mjs b/tests/guards/kanban-responsive-contract.test.mjs
|
||||
index 4e02f28..3efabf4 100644
|
||||
--- a/tests/guards/kanban-responsive-contract.test.mjs
|
||||
+++ b/tests/guards/kanban-responsive-contract.test.mjs
|
||||
@@ -9,11 +9,12 @@ async function read(relativePath) {
|
||||
return fs.readFile(path.join(ROOT, relativePath), 'utf8');
|
||||
}
|
||||
|
||||
-test('kanban board uses intentional horizontal scroll affordances', async () => {
|
||||
+test('kanban board uses expandable vertical swimlanes', async () => {
|
||||
const board = await read('src/components/kanban/kanban-board.tsx');
|
||||
|
||||
- assert.match(board, /snap-x/);
|
||||
- assert.match(board, /overflow-x-auto/);
|
||||
+ assert.match(board, /aria-expanded/);
|
||||
+ assert.match(board, /onActivateStatus/);
|
||||
+ assert.match(board, /max-h-\[50vh\]/);
|
||||
});
|
||||
|
||||
test('kanban page defines mobile detail drawer behavior', async () => {
|
||||
@@ -21,6 +22,8 @@ test('kanban page defines mobile detail drawer behavior', async () => {
|
||||
|
||||
assert.match(page, /fixed inset-0/);
|
||||
assert.match(page, /lg:hidden/);
|
||||
+ assert.match(page, /lg:grid-cols-\[minmax\(0,1fr\)_minmax\(22rem,26rem\)\]/);
|
||||
+ assert.match(page, /lg:border-l/);
|
||||
});
|
||||
|
||||
test('kanban controls use fluid full-width sizing on small viewports', async () => {
|
||||
|
|
|
|||
File diff suppressed because it is too large
Load diff
|
|
@ -1,130 +1,130 @@
|
|||
# Agent Sessions Hub
|
||||
|
||||
## Overview
|
||||
The Agent Sessions Hub (`/sessions`) provides a unified command workspace for tracking multi-agent coordination across your BeadBoard projects. It combines task status, agent communication, and derived activity into a social-dense interface optimized for understanding "who's doing what" at a glance.
|
||||
|
||||
## Features
|
||||
|
||||
### 1. Epic-Grouped Task Feed
|
||||
Tasks are automatically organized by their parent Epic, providing logical context for understanding work scope.
|
||||
|
||||
- **Session State Indicators**: Each task displays its real-time state (active, reviewing, needs_input, completed, stale)
|
||||
- **Owner & Actor Tracking**: See who owns the task and who last acted on it
|
||||
- **Communication Badges**: Unread message counts and pending acknowledgment flags
|
||||
|
||||
### 2. Agent Communication Integration
|
||||
Built-in cross-agent messaging system for coordination without leaving the dashboard.
|
||||
|
||||
**Message Types:**
|
||||
- `HANDOFF` - Pass context to another agent
|
||||
- `BLOCKED` - Request help or flag blockers
|
||||
- `INFO` - Share updates or documentation
|
||||
|
||||
**Communication Features:**
|
||||
- Inbox view with unread/read/acked states
|
||||
- Required acknowledgments for critical handoffs
|
||||
- Per-bead conversation threads
|
||||
|
||||
### 3. Agent Statistics & Productivity Metrics
|
||||
Real-time performance tracking for each registered agent.
|
||||
|
||||
**Metrics Tracked:**
|
||||
- Active tasks (currently in progress)
|
||||
- Completed tasks (closed beads)
|
||||
- Handoffs sent (coordination events)
|
||||
- Recent wins (last 3 completed tasks)
|
||||
|
||||
### 4. Derived Activity Engine
|
||||
Instead of storing history separately, BeadBoard computes activity on-demand by diffing snapshots of `issues.jsonl`.
|
||||
|
||||
**Event Types Generated:**
|
||||
- Bead lifecycle: created, closed, reopened
|
||||
- Status changes: todo → in_progress → done
|
||||
- Assignee changes
|
||||
- Priority, title, description updates
|
||||
- Label and dependency changes
|
||||
|
||||
**Persistence:**
|
||||
- File-backed ring buffer survives server restarts
|
||||
- O(N) snapshot diffing algorithm
|
||||
- No separate event database required
|
||||
|
||||
## Architecture
|
||||
|
||||
### Backend Components
|
||||
- **Agent Registry** (`src/lib/agent-registry.ts`): Maintains agent identity and roles
|
||||
- **Agent Mail** (`src/lib/agent-mail.ts`): Cross-agent messaging with inbox/ack protocol
|
||||
- **Agent Reservations** (`src/lib/agent-reservations.ts`): File/scope locking to prevent collisions
|
||||
- **Agent Sessions** (`src/lib/agent-sessions.ts`): Session state derivation and task feed builder
|
||||
- **Snapshot Differ** (`src/lib/snapshot-differ.ts`): O(N) diffing engine for activity events
|
||||
- **Activity Persistence** (`src/lib/activity-persistence.ts`): File-backed event buffer
|
||||
|
||||
### API Endpoints
|
||||
- `GET /api/sessions` - Fetch session task feed
|
||||
- `GET /api/sessions/[beadId]/conversation` - Get full conversation thread for a bead
|
||||
- `POST /api/sessions/[beadId]/comment` - Add a comment to a bead session
|
||||
- `POST /api/sessions/[beadId]/messages/[messageId]/read` - Mark message as read
|
||||
- `POST /api/sessions/[beadId]/messages/[messageId]/ack` - Acknowledge message
|
||||
- `GET /api/agents/[agentId]/stats` - Fetch agent productivity metrics
|
||||
|
||||
### Frontend Components
|
||||
- **SessionsPage** (`src/components/sessions/sessions-page.tsx`): Main layout and orchestration
|
||||
- **TaskCard** components: Visual representation of session state
|
||||
- **AgentStatsPanel**: Metrics dashboard per agent
|
||||
|
||||
## Session States
|
||||
|
||||
Tasks automatically transition between states based on activity and communication:
|
||||
|
||||
| State | Description | Visual Indicator |
|
||||
|-------|-------------|------------------|
|
||||
| `active` | Status is `in_progress`, recent activity | Green pulse |
|
||||
| `reviewing` | Under review or verification | Blue |
|
||||
| `deciding` | Status is `todo` or `ready`, waiting for claim | Gray |
|
||||
| `needs_input` | Status is `blocked` or has pending required acknowledgments | Yellow/Orange |
|
||||
| `completed` | Status is `closed` | Green checkmark |
|
||||
| `stale` | No activity in 24+ hours | Faded/Red |
|
||||
|
||||
## Integration with `bb agent` CLI
|
||||
|
||||
The Sessions Hub visualizes data managed by the `bb agent` command-line interface. See `docs/agent-session-flow.md` for the operator workflow.
|
||||
|
||||
**Key Commands:**
|
||||
- `bb agent register --name <name> --role <role>` - Register agent identity
|
||||
- `bb agent send --from <sender> --to <recipient> --bead <id> --category <type>` - Send message
|
||||
- `bb agent inbox --agent <name>` - Check messages
|
||||
- `bb agent reserve --agent <name> --scope <glob> --bead <id>` - Reserve files
|
||||
- `bb agent status --bead <id>` - Check reservation status
|
||||
|
||||
## Data Flow
|
||||
|
||||
1. **Source of Truth**: `.beads/issues.jsonl` via `bd` CLI
|
||||
2. **Activity Generation**: Watcher detects changes → snapshot differ → event bus
|
||||
3. **Agent Coordination**: `bb` CLI writes to `.beads/agents/` directory
|
||||
4. **UI Refresh**: SSE stream (`/api/events`) pushes updates to frontend in real-time
|
||||
|
||||
## Configuration
|
||||
|
||||
No configuration required. The Sessions Hub automatically:
|
||||
- Discovers registered agents from `.beads/agents/`
|
||||
- Builds communication graph from mailboxes
|
||||
- Derives session states from current bead status + activity
|
||||
|
||||
## Performance
|
||||
|
||||
- **O(N) Diffing**: Snapshot differ scales linearly with number of beads
|
||||
- **Ring Buffer**: Activity persistence uses fixed-size memory buffer (configurable)
|
||||
- **Real-time Updates**: SSE keeps UI synchronized without polling
|
||||
|
||||
## Limitations
|
||||
|
||||
- Comment interactions are not yet streamed to the timeline
|
||||
- Cross-project agent coordination requires agents to be registered in each project
|
||||
- Stale threshold is fixed at 24 hours (not user-configurable)
|
||||
|
||||
## Related Documentation
|
||||
|
||||
- `docs/agent-session-flow.md` - CLI workflow guide for operators
|
||||
- `docs/features/timeline.md` - Chronological activity feed
|
||||
- `docs/RFC-001-Agent-Coordination.md` - Agent coordination design
|
||||
- `docs/adr/2026-02-14-beadboard-driver-skill-and-bb-resolution.md` - beadboard-driver skill
|
||||
# Agent Sessions Hub
|
||||
|
||||
## Overview
|
||||
The Agent Sessions Hub (`/sessions`) provides a unified command workspace for tracking multi-agent coordination across your BeadBoard projects. It combines task status, agent communication, and derived activity into a social-dense interface optimized for understanding "who's doing what" at a glance.
|
||||
|
||||
## Features
|
||||
|
||||
### 1. Epic-Grouped Task Feed
|
||||
Tasks are automatically organized by their parent Epic, providing logical context for understanding work scope.
|
||||
|
||||
- **Session State Indicators**: Each task displays its real-time state (active, reviewing, needs_input, completed, stale)
|
||||
- **Owner & Actor Tracking**: See who owns the task and who last acted on it
|
||||
- **Communication Badges**: Unread message counts and pending acknowledgment flags
|
||||
|
||||
### 2. Agent Communication Integration
|
||||
Built-in cross-agent messaging system for coordination without leaving the dashboard.
|
||||
|
||||
**Message Types:**
|
||||
- `HANDOFF` - Pass context to another agent
|
||||
- `BLOCKED` - Request help or flag blockers
|
||||
- `INFO` - Share updates or documentation
|
||||
|
||||
**Communication Features:**
|
||||
- Inbox view with unread/read/acked states
|
||||
- Required acknowledgments for critical handoffs
|
||||
- Per-bead conversation threads
|
||||
|
||||
### 3. Agent Statistics & Productivity Metrics
|
||||
Real-time performance tracking for each registered agent.
|
||||
|
||||
**Metrics Tracked:**
|
||||
- Active tasks (currently in progress)
|
||||
- Completed tasks (closed beads)
|
||||
- Handoffs sent (coordination events)
|
||||
- Recent wins (last 3 completed tasks)
|
||||
|
||||
### 4. Derived Activity Engine
|
||||
Instead of storing history separately, BeadBoard computes activity on-demand by diffing snapshots of `issues.jsonl`.
|
||||
|
||||
**Event Types Generated:**
|
||||
- Bead lifecycle: created, closed, reopened
|
||||
- Status changes: todo → in_progress → done
|
||||
- Assignee changes
|
||||
- Priority, title, description updates
|
||||
- Label and dependency changes
|
||||
|
||||
**Persistence:**
|
||||
- File-backed ring buffer survives server restarts
|
||||
- O(N) snapshot diffing algorithm
|
||||
- No separate event database required
|
||||
|
||||
## Architecture
|
||||
|
||||
### Backend Components
|
||||
- **Agent Registry** (`src/lib/agent-registry.ts`): Maintains agent identity and roles
|
||||
- **Agent Mail** (`src/lib/agent-mail.ts`): Cross-agent messaging with inbox/ack protocol
|
||||
- **Agent Reservations** (`src/lib/agent-reservations.ts`): File/scope locking to prevent collisions
|
||||
- **Agent Sessions** (`src/lib/agent-sessions.ts`): Session state derivation and task feed builder
|
||||
- **Snapshot Differ** (`src/lib/snapshot-differ.ts`): O(N) diffing engine for activity events
|
||||
- **Activity Persistence** (`src/lib/activity-persistence.ts`): File-backed event buffer
|
||||
|
||||
### API Endpoints
|
||||
- `GET /api/sessions` - Fetch session task feed
|
||||
- `GET /api/sessions/[beadId]/conversation` - Get full conversation thread for a bead
|
||||
- `POST /api/sessions/[beadId]/comment` - Add a comment to a bead session
|
||||
- `POST /api/sessions/[beadId]/messages/[messageId]/read` - Mark message as read
|
||||
- `POST /api/sessions/[beadId]/messages/[messageId]/ack` - Acknowledge message
|
||||
- `GET /api/agents/[agentId]/stats` - Fetch agent productivity metrics
|
||||
|
||||
### Frontend Components
|
||||
- **SessionsPage** (`src/components/sessions/sessions-page.tsx`): Main layout and orchestration
|
||||
- **TaskCard** components: Visual representation of session state
|
||||
- **AgentStatsPanel**: Metrics dashboard per agent
|
||||
|
||||
## Session States
|
||||
|
||||
Tasks automatically transition between states based on activity and communication:
|
||||
|
||||
| State | Description | Visual Indicator |
|
||||
|-------|-------------|------------------|
|
||||
| `active` | Status is `in_progress`, recent activity | Green pulse |
|
||||
| `reviewing` | Under review or verification | Blue |
|
||||
| `deciding` | Status is `todo` or `ready`, waiting for claim | Gray |
|
||||
| `needs_input` | Status is `blocked` or has pending required acknowledgments | Yellow/Orange |
|
||||
| `completed` | Status is `closed` | Green checkmark |
|
||||
| `stale` | No activity in 24+ hours | Faded/Red |
|
||||
|
||||
## Integration with `bb agent` CLI
|
||||
|
||||
The Sessions Hub visualizes data managed by the `bb agent` command-line interface. See `docs/agent-session-flow.md` for the operator workflow.
|
||||
|
||||
**Key Commands:**
|
||||
- `bb agent register --name <name> --role <role>` - Register agent identity
|
||||
- `bb agent send --from <sender> --to <recipient> --bead <id> --category <type>` - Send message
|
||||
- `bb agent inbox --agent <name>` - Check messages
|
||||
- `bb agent reserve --agent <name> --scope <glob> --bead <id>` - Reserve files
|
||||
- `bb agent status --bead <id>` - Check reservation status
|
||||
|
||||
## Data Flow
|
||||
|
||||
1. **Source of Truth**: `.beads/issues.jsonl` via `bd` CLI
|
||||
2. **Activity Generation**: Watcher detects changes → snapshot differ → event bus
|
||||
3. **Agent Coordination**: `bb` CLI writes to `.beads/agents/` directory
|
||||
4. **UI Refresh**: SSE stream (`/api/events`) pushes updates to frontend in real-time
|
||||
|
||||
## Configuration
|
||||
|
||||
No configuration required. The Sessions Hub automatically:
|
||||
- Discovers registered agents from `.beads/agents/`
|
||||
- Builds communication graph from mailboxes
|
||||
- Derives session states from current bead status + activity
|
||||
|
||||
## Performance
|
||||
|
||||
- **O(N) Diffing**: Snapshot differ scales linearly with number of beads
|
||||
- **Ring Buffer**: Activity persistence uses fixed-size memory buffer (configurable)
|
||||
- **Real-time Updates**: SSE keeps UI synchronized without polling
|
||||
|
||||
## Limitations
|
||||
|
||||
- Comment interactions are not yet streamed to the timeline
|
||||
- Cross-project agent coordination requires agents to be registered in each project
|
||||
- Stale threshold is fixed at 24 hours (not user-configurable)
|
||||
|
||||
## Related Documentation
|
||||
|
||||
- `docs/agent-session-flow.md` - CLI workflow guide for operators
|
||||
- `docs/features/timeline.md` - Chronological activity feed
|
||||
- `docs/RFC-001-Agent-Coordination.md` - Agent coordination design
|
||||
- `docs/adr/2026-02-14-beadboard-driver-skill-and-bb-resolution.md` - beadboard-driver skill
|
||||
|
|
|
|||
|
|
@ -1,318 +1,318 @@
|
|||
# Comprehensive Theme System Design
|
||||
|
||||
## The Problem
|
||||
We have colors scattered across 67+ files:
|
||||
- Hardcoded hex: `bg-[#0a111a]`, `bg-[#111f2b]`, `bg-[#14202e]`
|
||||
- Inline styles: `style={{ backgroundColor: '#1a2d3d' }}`
|
||||
- Arbitrary Tailwind: `bg-white/5`, `border-white/10`
|
||||
- Mixed variable systems: `--ui-bg-*`, `--color-bg-*`, etc.
|
||||
|
||||
## The Solution: Unified Theme System
|
||||
|
||||
### File Structure
|
||||
```
|
||||
src/styles/
|
||||
themes/
|
||||
index.css ← Theme definitions + data-attribute switching
|
||||
tokens.css ← Base CSS variable names (no values)
|
||||
components/
|
||||
surfaces.css ← Surface layer utilities
|
||||
interactions.css ← Hover, focus, active states
|
||||
```
|
||||
|
||||
### Token Architecture (12 Semantic Categories)
|
||||
|
||||
#### 1. SURFACE LAYERS (Backgrounds)
|
||||
```css
|
||||
--surface-backdrop: /* Page background */
|
||||
--surface-elevated: /* Header - sits on top */
|
||||
--surface-primary: /* Left sidebar */
|
||||
--surface-secondary: /* Main content area */
|
||||
--surface-tertiary: /* Panels/cards within sidebars */
|
||||
--surface-quaternary: /* Cards */
|
||||
--surface-overlay: /* Modals, dropdowns, drawers */
|
||||
--surface-input: /* Form fields, inputs */
|
||||
--surface-hover: /* Hover states */
|
||||
--surface-active: /* Active/selected states */
|
||||
--surface-tooltip: /* Tooltips, popovers */
|
||||
```
|
||||
|
||||
#### 2. BORDERS
|
||||
```css
|
||||
--border-subtle: /* Dividers between sections */
|
||||
--border-default: /* Card borders */
|
||||
--border-strong: /* Focus rings, selected states */
|
||||
--border-accent: /* Colored status borders */
|
||||
```
|
||||
|
||||
#### 3. TEXT
|
||||
```css
|
||||
--text-primary: /* Headlines, important text */
|
||||
--text-secondary: /* Body text */
|
||||
--text-tertiary: /* Muted, hints */
|
||||
--text-disabled: /* Disabled elements */
|
||||
--text-inverse: /* Text on colored backgrounds */
|
||||
```
|
||||
|
||||
#### 4. ACCENTS (Functional)
|
||||
```css
|
||||
--accent-info: /* Cyan - links, actions */
|
||||
--accent-success: /* Green - ready, done */
|
||||
--accent-warning: /* Amber - in progress */
|
||||
--accent-danger: /* Red - blocked, errors */
|
||||
```
|
||||
|
||||
#### 5. ACCENTS (Aurora Glow)
|
||||
```css
|
||||
--glow-info: /* Box-shadow glow for info */
|
||||
--glow-success: /* Box-shadow glow for success */
|
||||
--glow-warning: /* Box-shadow glow for warning */
|
||||
--glow-danger: /* Box-shadow glow for danger */
|
||||
```
|
||||
|
||||
#### 6. GRAPH COLORS
|
||||
```css
|
||||
--graph-node-default: /* Default node background */
|
||||
--graph-node-epic: /* Epic node accent */
|
||||
--graph-edge-default: /* Default edge color */
|
||||
--graph-edge-selected: /* Selected edge color */
|
||||
--graph-edge-cycle: /* Cycle warning color */
|
||||
```
|
||||
|
||||
#### 7. SEMANTIC ALPHAS
|
||||
Instead of `bg-white/5` and `bg-black/40`, use themeable alphas:
|
||||
```css
|
||||
--alpha-white-low: /* 5% white */
|
||||
--alpha-white-medium: /* 10% white */
|
||||
--alpha-white-high: /* 20% white */
|
||||
--alpha-black-low: /* 10% black */
|
||||
--alpha-black-medium: /* 40% black */
|
||||
--alpha-black-high: /* 80% black */
|
||||
```
|
||||
|
||||
#### 8. STATUS COLORS
|
||||
```css
|
||||
--status-ready: /* Ready/open status */
|
||||
--status-in-progress: /* In progress status */
|
||||
--status-blocked: /* Blocked status */
|
||||
--status-closed: /* Closed/done status */
|
||||
--status-deferred: /* Deferred status */
|
||||
```
|
||||
|
||||
#### 9. SHADOWS
|
||||
```css
|
||||
--shadow-sm: /* Subtle elevation */
|
||||
--shadow-md: /* Cards */
|
||||
--shadow-lg: /* Modals, drawers */
|
||||
--shadow-glow-info: /* Aurora glow */
|
||||
--shadow-glow-success: /* Aurora glow */
|
||||
--shadow-glow-warning: /* Aurora glow */
|
||||
--shadow-glow-danger: /* Aurora glow */
|
||||
```
|
||||
|
||||
#### 10. AGENT/ROLE COLORS
|
||||
```css
|
||||
--agent-role-ui: /* UI role color */
|
||||
--agent-role-graph: /* Graph role color */
|
||||
--agent-role-orchestrator: /* Orchestrator role */
|
||||
--agent-role-researcher: /* Researcher role */
|
||||
```
|
||||
|
||||
#### 11. SCROLLBARS
|
||||
```css
|
||||
--scrollbar-track: /* Scrollbar track */
|
||||
--scrollbar-thumb: /* Scrollbar thumb */
|
||||
--scrollbar-thumb-hover: /* Scrollbar thumb hover */
|
||||
```
|
||||
|
||||
#### 12. CODE/SYNTAX
|
||||
```css
|
||||
--code-background: /* Code block background */
|
||||
--code-text: /* Code text color */
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Theme Definitions (Example)
|
||||
|
||||
### Aurora Theme (Current)
|
||||
```css
|
||||
[data-theme="aurora"] {
|
||||
/* Surfaces - Warm Charcoal */
|
||||
--surface-backdrop: #181716;
|
||||
--surface-elevated: #131211;
|
||||
--surface-primary: #1f1e1d;
|
||||
--surface-secondary: #242322;
|
||||
--surface-tertiary: #282725;
|
||||
--surface-quaternary: #302e2c;
|
||||
--surface-overlay: #0d0c0b;
|
||||
|
||||
/* Borders */
|
||||
--border-subtle: rgba(180, 175, 165, 0.15);
|
||||
--border-default: rgba(180, 175, 165, 0.25);
|
||||
--border-strong: rgba(180, 175, 165, 0.4);
|
||||
|
||||
/* Text */
|
||||
--text-primary: #f0eeea;
|
||||
--text-secondary: #c9c5bc;
|
||||
--text-tertiary: #a8a49a;
|
||||
|
||||
/* Accents */
|
||||
--accent-info: #35c9ff;
|
||||
--accent-success: #35d98f;
|
||||
--accent-warning: #ffb24a;
|
||||
--accent-danger: #ff4c72;
|
||||
|
||||
/* Glows */
|
||||
--glow-info: 0 0 20px rgba(53, 201, 255, 0.3);
|
||||
--glow-success: 0 0 20px rgba(53, 217, 143, 0.3);
|
||||
|
||||
/* Graph */
|
||||
--graph-node-default: rgba(48, 46, 44, 0.8);
|
||||
--graph-node-epic: rgba(53, 201, 255, 0.15);
|
||||
--graph-edge-default: rgba(180, 175, 165, 0.3);
|
||||
--graph-edge-selected: #35c9ff;
|
||||
|
||||
/* Alphas */
|
||||
--alpha-white-low: rgba(240, 238, 234, 0.05);
|
||||
--alpha-white-medium: rgba(240, 238, 234, 0.1);
|
||||
--alpha-black-medium: rgba(0, 0, 0, 0.4);
|
||||
}
|
||||
```
|
||||
|
||||
### Midnight Theme (Future)
|
||||
```css
|
||||
[data-theme="midnight"] {
|
||||
--surface-backdrop: #0a0a0f;
|
||||
--surface-elevated: #050508;
|
||||
--surface-primary: #111118;
|
||||
--surface-secondary: #151520;
|
||||
--surface-quaternary: #1e1e2e;
|
||||
|
||||
--accent-info: #8b5cf6;
|
||||
--accent-success: #10b981;
|
||||
|
||||
/* Same structure, different values */
|
||||
}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Migration Strategy
|
||||
|
||||
### Phase 1: Create Token System
|
||||
1. Create `src/styles/themes/index.css` with token definitions
|
||||
2. Create `src/styles/themes/tokens.css` with token names
|
||||
3. Add data-theme attribute to layout
|
||||
|
||||
### Phase 2: Component Audit & Migration
|
||||
For each component:
|
||||
1. Replace hardcoded colors with semantic tokens
|
||||
2. Replace `bg-white/5` with `bg-[var(--alpha-white-low)]`
|
||||
3. Replace `bg-[#0a111a]` with appropriate surface token
|
||||
|
||||
### Phase 3: Graph/Flow Colors
|
||||
1. Extract all graph colors to `--graph-*` tokens
|
||||
2. Update ReactFlow styles to use CSS variables
|
||||
|
||||
### Phase 4: Validation
|
||||
1. Create theme preview page showing all tokens
|
||||
2. Verify no hardcoded colors remain
|
||||
|
||||
---
|
||||
|
||||
## Usage Examples
|
||||
|
||||
### Before (Chaos):
|
||||
```tsx
|
||||
<div className="bg-[#0a111a] border border-white/10">
|
||||
<span className="text-[#a8a49a]">Text</span>
|
||||
</div>
|
||||
```
|
||||
|
||||
### After (Clean):
|
||||
```tsx
|
||||
<div className="bg-[var(--surface-tertiary)] border border-[var(--border-default)]">
|
||||
<span className="text-[var(--text-tertiary)]">Text</span>
|
||||
</div>
|
||||
```
|
||||
|
||||
### With Tailwind utilities (even cleaner):
|
||||
```tsx
|
||||
<div className="surface-tertiary border-default">
|
||||
<span className="text-tertiary">Text</span>
|
||||
</div>
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Component Mapping Guide
|
||||
|
||||
| Component | Current | New Token |
|
||||
|-----------|---------|-----------|
|
||||
| TopBar | `bg-[var(--ui-bg-header)]` | `bg-[var(--surface-elevated)]` |
|
||||
| LeftPanel | `bg-[var(--ui-bg-shell)]` | `bg-[var(--surface-primary)]` |
|
||||
| Main content | `bg-[var(--ui-bg-main)]` | `bg-[var(--surface-secondary)]` |
|
||||
| SocialCard | `bg-[var(--ui-bg-card)]` | `bg-[var(--surface-quaternary)]` |
|
||||
| AssignmentPanel | `bg-[#0a111a]` | `bg-[var(--surface-tertiary)]` |
|
||||
| Modal/Drawer | `bg-[#0d0c0b]` | `bg-[var(--surface-overlay)]` |
|
||||
| Input fields | `bg-[#0f1824]` | `bg-[var(--surface-input)]` |
|
||||
|
||||
---
|
||||
|
||||
## Files That Need Migration (Priority Order)
|
||||
|
||||
### HIGH (Core UI):
|
||||
1. `src/app/globals.css` - Define tokens
|
||||
2. `src/components/shared/unified-shell.tsx` - Main layout
|
||||
3. `src/components/shared/top-bar.tsx` - Header
|
||||
4. `src/components/shared/left-panel.tsx` - Sidebar
|
||||
5. `src/components/shared/right-panel.tsx` - Right panel
|
||||
6. `src/components/social/social-card.tsx` - Cards
|
||||
|
||||
### MEDIUM (Active Views):
|
||||
7. `src/components/graph/assignment-panel.tsx` - Heavy hardcoded colors
|
||||
8. `src/components/graph/graph-node-card.tsx` - Graph nodes
|
||||
9. `src/components/activity/swarm-command-feed.tsx` - Activity feed
|
||||
10. `src/components/graph/smart-dag.tsx` - Graph background
|
||||
|
||||
### LOWER (Secondary):
|
||||
11. All modal/dialog components
|
||||
12. All form/input components
|
||||
13. Kanban components (if still used)
|
||||
14. Swarm components
|
||||
|
||||
---
|
||||
|
||||
## Success Criteria
|
||||
|
||||
- [ ] Zero hardcoded hex colors in components (except for data viz)
|
||||
- [ ] Zero `bg-white/X` or `bg-black/X` - all use `--alpha-*` tokens
|
||||
- [ ] Theme switcher works instantly without reload
|
||||
- [ ] All 12 token categories have values for each theme
|
||||
- [ ] Visual regression test passes (no unintended changes)
|
||||
|
||||
---
|
||||
|
||||
## For You (The Human)
|
||||
|
||||
Once this is implemented, you can just say:
|
||||
> "Change the sidebar to be slightly lighter in the aurora theme"
|
||||
|
||||
And I'll know exactly where to go:
|
||||
```css
|
||||
[data-theme="aurora"] {
|
||||
--surface-primary: #252422; /* Changed from #1f1e1d */
|
||||
}
|
||||
```
|
||||
|
||||
Or:
|
||||
> "Make the aurora glow more subtle"
|
||||
|
||||
```css
|
||||
[data-theme="aurora"] {
|
||||
--glow-info: 0 0 12px rgba(53, 201, 255, 0.15); /* Reduced from 20px/0.3 */
|
||||
}
|
||||
```
|
||||
|
||||
Everything in one place. No hunting through 67 files.
|
||||
# Comprehensive Theme System Design
|
||||
|
||||
## The Problem
|
||||
We have colors scattered across 67+ files:
|
||||
- Hardcoded hex: `bg-[#0a111a]`, `bg-[#111f2b]`, `bg-[#14202e]`
|
||||
- Inline styles: `style={{ backgroundColor: '#1a2d3d' }}`
|
||||
- Arbitrary Tailwind: `bg-white/5`, `border-white/10`
|
||||
- Mixed variable systems: `--ui-bg-*`, `--color-bg-*`, etc.
|
||||
|
||||
## The Solution: Unified Theme System
|
||||
|
||||
### File Structure
|
||||
```
|
||||
src/styles/
|
||||
themes/
|
||||
index.css ← Theme definitions + data-attribute switching
|
||||
tokens.css ← Base CSS variable names (no values)
|
||||
components/
|
||||
surfaces.css ← Surface layer utilities
|
||||
interactions.css ← Hover, focus, active states
|
||||
```
|
||||
|
||||
### Token Architecture (12 Semantic Categories)
|
||||
|
||||
#### 1. SURFACE LAYERS (Backgrounds)
|
||||
```css
|
||||
--surface-backdrop: /* Page background */
|
||||
--surface-elevated: /* Header - sits on top */
|
||||
--surface-primary: /* Left sidebar */
|
||||
--surface-secondary: /* Main content area */
|
||||
--surface-tertiary: /* Panels/cards within sidebars */
|
||||
--surface-quaternary: /* Cards */
|
||||
--surface-overlay: /* Modals, dropdowns, drawers */
|
||||
--surface-input: /* Form fields, inputs */
|
||||
--surface-hover: /* Hover states */
|
||||
--surface-active: /* Active/selected states */
|
||||
--surface-tooltip: /* Tooltips, popovers */
|
||||
```
|
||||
|
||||
#### 2. BORDERS
|
||||
```css
|
||||
--border-subtle: /* Dividers between sections */
|
||||
--border-default: /* Card borders */
|
||||
--border-strong: /* Focus rings, selected states */
|
||||
--border-accent: /* Colored status borders */
|
||||
```
|
||||
|
||||
#### 3. TEXT
|
||||
```css
|
||||
--text-primary: /* Headlines, important text */
|
||||
--text-secondary: /* Body text */
|
||||
--text-tertiary: /* Muted, hints */
|
||||
--text-disabled: /* Disabled elements */
|
||||
--text-inverse: /* Text on colored backgrounds */
|
||||
```
|
||||
|
||||
#### 4. ACCENTS (Functional)
|
||||
```css
|
||||
--accent-info: /* Cyan - links, actions */
|
||||
--accent-success: /* Green - ready, done */
|
||||
--accent-warning: /* Amber - in progress */
|
||||
--accent-danger: /* Red - blocked, errors */
|
||||
```
|
||||
|
||||
#### 5. ACCENTS (Aurora Glow)
|
||||
```css
|
||||
--glow-info: /* Box-shadow glow for info */
|
||||
--glow-success: /* Box-shadow glow for success */
|
||||
--glow-warning: /* Box-shadow glow for warning */
|
||||
--glow-danger: /* Box-shadow glow for danger */
|
||||
```
|
||||
|
||||
#### 6. GRAPH COLORS
|
||||
```css
|
||||
--graph-node-default: /* Default node background */
|
||||
--graph-node-epic: /* Epic node accent */
|
||||
--graph-edge-default: /* Default edge color */
|
||||
--graph-edge-selected: /* Selected edge color */
|
||||
--graph-edge-cycle: /* Cycle warning color */
|
||||
```
|
||||
|
||||
#### 7. SEMANTIC ALPHAS
|
||||
Instead of `bg-white/5` and `bg-black/40`, use themeable alphas:
|
||||
```css
|
||||
--alpha-white-low: /* 5% white */
|
||||
--alpha-white-medium: /* 10% white */
|
||||
--alpha-white-high: /* 20% white */
|
||||
--alpha-black-low: /* 10% black */
|
||||
--alpha-black-medium: /* 40% black */
|
||||
--alpha-black-high: /* 80% black */
|
||||
```
|
||||
|
||||
#### 8. STATUS COLORS
|
||||
```css
|
||||
--status-ready: /* Ready/open status */
|
||||
--status-in-progress: /* In progress status */
|
||||
--status-blocked: /* Blocked status */
|
||||
--status-closed: /* Closed/done status */
|
||||
--status-deferred: /* Deferred status */
|
||||
```
|
||||
|
||||
#### 9. SHADOWS
|
||||
```css
|
||||
--shadow-sm: /* Subtle elevation */
|
||||
--shadow-md: /* Cards */
|
||||
--shadow-lg: /* Modals, drawers */
|
||||
--shadow-glow-info: /* Aurora glow */
|
||||
--shadow-glow-success: /* Aurora glow */
|
||||
--shadow-glow-warning: /* Aurora glow */
|
||||
--shadow-glow-danger: /* Aurora glow */
|
||||
```
|
||||
|
||||
#### 10. AGENT/ROLE COLORS
|
||||
```css
|
||||
--agent-role-ui: /* UI role color */
|
||||
--agent-role-graph: /* Graph role color */
|
||||
--agent-role-orchestrator: /* Orchestrator role */
|
||||
--agent-role-researcher: /* Researcher role */
|
||||
```
|
||||
|
||||
#### 11. SCROLLBARS
|
||||
```css
|
||||
--scrollbar-track: /* Scrollbar track */
|
||||
--scrollbar-thumb: /* Scrollbar thumb */
|
||||
--scrollbar-thumb-hover: /* Scrollbar thumb hover */
|
||||
```
|
||||
|
||||
#### 12. CODE/SYNTAX
|
||||
```css
|
||||
--code-background: /* Code block background */
|
||||
--code-text: /* Code text color */
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Theme Definitions (Example)
|
||||
|
||||
### Aurora Theme (Current)
|
||||
```css
|
||||
[data-theme="aurora"] {
|
||||
/* Surfaces - Warm Charcoal */
|
||||
--surface-backdrop: #181716;
|
||||
--surface-elevated: #131211;
|
||||
--surface-primary: #1f1e1d;
|
||||
--surface-secondary: #242322;
|
||||
--surface-tertiary: #282725;
|
||||
--surface-quaternary: #302e2c;
|
||||
--surface-overlay: #0d0c0b;
|
||||
|
||||
/* Borders */
|
||||
--border-subtle: rgba(180, 175, 165, 0.15);
|
||||
--border-default: rgba(180, 175, 165, 0.25);
|
||||
--border-strong: rgba(180, 175, 165, 0.4);
|
||||
|
||||
/* Text */
|
||||
--text-primary: #f0eeea;
|
||||
--text-secondary: #c9c5bc;
|
||||
--text-tertiary: #a8a49a;
|
||||
|
||||
/* Accents */
|
||||
--accent-info: #35c9ff;
|
||||
--accent-success: #35d98f;
|
||||
--accent-warning: #ffb24a;
|
||||
--accent-danger: #ff4c72;
|
||||
|
||||
/* Glows */
|
||||
--glow-info: 0 0 20px rgba(53, 201, 255, 0.3);
|
||||
--glow-success: 0 0 20px rgba(53, 217, 143, 0.3);
|
||||
|
||||
/* Graph */
|
||||
--graph-node-default: rgba(48, 46, 44, 0.8);
|
||||
--graph-node-epic: rgba(53, 201, 255, 0.15);
|
||||
--graph-edge-default: rgba(180, 175, 165, 0.3);
|
||||
--graph-edge-selected: #35c9ff;
|
||||
|
||||
/* Alphas */
|
||||
--alpha-white-low: rgba(240, 238, 234, 0.05);
|
||||
--alpha-white-medium: rgba(240, 238, 234, 0.1);
|
||||
--alpha-black-medium: rgba(0, 0, 0, 0.4);
|
||||
}
|
||||
```
|
||||
|
||||
### Midnight Theme (Future)
|
||||
```css
|
||||
[data-theme="midnight"] {
|
||||
--surface-backdrop: #0a0a0f;
|
||||
--surface-elevated: #050508;
|
||||
--surface-primary: #111118;
|
||||
--surface-secondary: #151520;
|
||||
--surface-quaternary: #1e1e2e;
|
||||
|
||||
--accent-info: #8b5cf6;
|
||||
--accent-success: #10b981;
|
||||
|
||||
/* Same structure, different values */
|
||||
}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Migration Strategy
|
||||
|
||||
### Phase 1: Create Token System
|
||||
1. Create `src/styles/themes/index.css` with token definitions
|
||||
2. Create `src/styles/themes/tokens.css` with token names
|
||||
3. Add data-theme attribute to layout
|
||||
|
||||
### Phase 2: Component Audit & Migration
|
||||
For each component:
|
||||
1. Replace hardcoded colors with semantic tokens
|
||||
2. Replace `bg-white/5` with `bg-[var(--alpha-white-low)]`
|
||||
3. Replace `bg-[#0a111a]` with appropriate surface token
|
||||
|
||||
### Phase 3: Graph/Flow Colors
|
||||
1. Extract all graph colors to `--graph-*` tokens
|
||||
2. Update ReactFlow styles to use CSS variables
|
||||
|
||||
### Phase 4: Validation
|
||||
1. Create theme preview page showing all tokens
|
||||
2. Verify no hardcoded colors remain
|
||||
|
||||
---
|
||||
|
||||
## Usage Examples
|
||||
|
||||
### Before (Chaos):
|
||||
```tsx
|
||||
<div className="bg-[#0a111a] border border-white/10">
|
||||
<span className="text-[#a8a49a]">Text</span>
|
||||
</div>
|
||||
```
|
||||
|
||||
### After (Clean):
|
||||
```tsx
|
||||
<div className="bg-[var(--surface-tertiary)] border border-[var(--border-default)]">
|
||||
<span className="text-[var(--text-tertiary)]">Text</span>
|
||||
</div>
|
||||
```
|
||||
|
||||
### With Tailwind utilities (even cleaner):
|
||||
```tsx
|
||||
<div className="surface-tertiary border-default">
|
||||
<span className="text-tertiary">Text</span>
|
||||
</div>
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Component Mapping Guide
|
||||
|
||||
| Component | Current | New Token |
|
||||
|-----------|---------|-----------|
|
||||
| TopBar | `bg-[var(--ui-bg-header)]` | `bg-[var(--surface-elevated)]` |
|
||||
| LeftPanel | `bg-[var(--ui-bg-shell)]` | `bg-[var(--surface-primary)]` |
|
||||
| Main content | `bg-[var(--ui-bg-main)]` | `bg-[var(--surface-secondary)]` |
|
||||
| SocialCard | `bg-[var(--ui-bg-card)]` | `bg-[var(--surface-quaternary)]` |
|
||||
| AssignmentPanel | `bg-[#0a111a]` | `bg-[var(--surface-tertiary)]` |
|
||||
| Modal/Drawer | `bg-[#0d0c0b]` | `bg-[var(--surface-overlay)]` |
|
||||
| Input fields | `bg-[#0f1824]` | `bg-[var(--surface-input)]` |
|
||||
|
||||
---
|
||||
|
||||
## Files That Need Migration (Priority Order)
|
||||
|
||||
### HIGH (Core UI):
|
||||
1. `src/app/globals.css` - Define tokens
|
||||
2. `src/components/shared/unified-shell.tsx` - Main layout
|
||||
3. `src/components/shared/top-bar.tsx` - Header
|
||||
4. `src/components/shared/left-panel.tsx` - Sidebar
|
||||
5. `src/components/shared/right-panel.tsx` - Right panel
|
||||
6. `src/components/social/social-card.tsx` - Cards
|
||||
|
||||
### MEDIUM (Active Views):
|
||||
7. `src/components/graph/assignment-panel.tsx` - Heavy hardcoded colors
|
||||
8. `src/components/graph/graph-node-card.tsx` - Graph nodes
|
||||
9. `src/components/activity/swarm-command-feed.tsx` - Activity feed
|
||||
10. `src/components/graph/smart-dag.tsx` - Graph background
|
||||
|
||||
### LOWER (Secondary):
|
||||
11. All modal/dialog components
|
||||
12. All form/input components
|
||||
13. Kanban components (if still used)
|
||||
14. Swarm components
|
||||
|
||||
---
|
||||
|
||||
## Success Criteria
|
||||
|
||||
- [ ] Zero hardcoded hex colors in components (except for data viz)
|
||||
- [ ] Zero `bg-white/X` or `bg-black/X` - all use `--alpha-*` tokens
|
||||
- [ ] Theme switcher works instantly without reload
|
||||
- [ ] All 12 token categories have values for each theme
|
||||
- [ ] Visual regression test passes (no unintended changes)
|
||||
|
||||
---
|
||||
|
||||
## For You (The Human)
|
||||
|
||||
Once this is implemented, you can just say:
|
||||
> "Change the sidebar to be slightly lighter in the aurora theme"
|
||||
|
||||
And I'll know exactly where to go:
|
||||
```css
|
||||
[data-theme="aurora"] {
|
||||
--surface-primary: #252422; /* Changed from #1f1e1d */
|
||||
}
|
||||
```
|
||||
|
||||
Or:
|
||||
> "Make the aurora glow more subtle"
|
||||
|
||||
```css
|
||||
[data-theme="aurora"] {
|
||||
--glow-info: 0 0 12px rgba(53, 201, 255, 0.15); /* Reduced from 20px/0.3 */
|
||||
}
|
||||
```
|
||||
|
||||
Everything in one place. No hunting through 67 files.
|
||||
|
|
|
|||
|
|
@ -257,4 +257,4 @@
|
|||
- Mutations executed only via `bd.exe`
|
||||
- Real-time updates delivered via SSE
|
||||
- Kanban, Graph, Timeline, Agent Session views functional
|
||||
- Boundary guard test prevents direct JSONL writes
|
||||
- Boundary guard test prevents direct JSONL writes
|
||||
|
|
|
|||
|
|
@ -159,4 +159,4 @@ Current Beads ecosystem tools are often Unix/macOS oriented, creating friction f
|
|||
- Reads from `.beads/issues.jsonl` successfully for registered projects
|
||||
- All writes performed via `bd.exe` and reflected back via watcher/SSE
|
||||
- Kanban, Timeline, Graph, and Agent Session views function against real bead data
|
||||
- No direct `issues.jsonl` write implementation exists in app code
|
||||
- No direct `issues.jsonl` write implementation exists in app code
|
||||
|
|
|
|||
|
|
@ -1,134 +1,134 @@
|
|||
# BeadBoard Kanban Design System Plan
|
||||
|
||||
**Goal**
|
||||
Ship a production-ready baseline visual system for Tracer Bullet 1 (Kanban) before further feature expansion.
|
||||
|
||||
**Primary decision**
|
||||
Use **Tailwind CSS v4 + CSS tokens (`@theme`) + Framer Motion**.
|
||||
|
||||
## 1. Why This Stack
|
||||
|
||||
### Tailwind v4 is the right baseline
|
||||
- Fastest path to a coherent, reusable system in Next.js 15.
|
||||
- CSS-first token model (`@theme`) fits our need for semantic design tokens.
|
||||
- Lets us avoid scattered inline styles and ad-hoc CSS files.
|
||||
|
||||
### Framer Motion should be scoped
|
||||
- Use for state transitions (card changes, panel enter/exit, filtered results).
|
||||
- Avoid decorative over-animation that hurts readability in a dense dashboard.
|
||||
|
||||
### Risks and mitigations
|
||||
- Risk: “generic Tailwind look”
|
||||
- Mitigation: strict token palette + component contracts + typography rules.
|
||||
- Risk: visual inconsistency
|
||||
- Mitigation: no direct color literals in component markup except token definitions.
|
||||
|
||||
## 2. Baseline-First Sequencing
|
||||
|
||||
This should happen **now**, not later.
|
||||
|
||||
1. Foundation (tokens, layout, core components)
|
||||
2. Motion and interaction polish
|
||||
3. Accessibility and responsive hardening
|
||||
4. Continue other tracer bullets
|
||||
|
||||
## 3. Visual Language (v1)
|
||||
|
||||
### Product feel
|
||||
- High-signal operations UI.
|
||||
- Calm neutral surfaces with sharp status accents.
|
||||
- Dense information without visual clutter.
|
||||
|
||||
### Typography
|
||||
- Primary UI: `DM Sans` (or `Inter` fallback decision at implementation time)
|
||||
- Metadata/IDs: `JetBrains Mono`
|
||||
|
||||
### Color model
|
||||
- Semantic tokens only:
|
||||
- `background`, `foreground`, `surface`, `muted`
|
||||
- `status-open`, `status-in-progress`, `status-blocked`, `status-deferred`, `status-closed`
|
||||
- `priority-p0` ... `priority-p4`
|
||||
- Contrast target: at least WCAG AA for normal text.
|
||||
|
||||
## 4. Component Contract
|
||||
|
||||
Required first-class components:
|
||||
- `KanbanPageShell`
|
||||
- `KanbanControls`
|
||||
- `KanbanBoard`
|
||||
- `KanbanColumn`
|
||||
- `KanbanCard`
|
||||
- `KanbanDetailPanel`
|
||||
- shared: `Badge`, `Chip`, `StatPill`
|
||||
|
||||
Rules:
|
||||
- Component variants defined via class composition (CVA optional but preferred).
|
||||
- No inline style objects for production components.
|
||||
- All spacing/radius/shadow/color come from tokens/utilities.
|
||||
|
||||
## 5. Layout Contract
|
||||
|
||||
### Desktop
|
||||
- Sticky top header with filters + stats.
|
||||
- Main grid: board + detail panel.
|
||||
- Columns scroll horizontally as needed.
|
||||
|
||||
### Mobile
|
||||
- Stacked controls.
|
||||
- Board in horizontal swipe/scroll mode.
|
||||
- Detail panel becomes full-screen drawer.
|
||||
|
||||
## 6. Motion Contract (Framer Motion)
|
||||
|
||||
Use motion for:
|
||||
- Card appear/disappear on filtering.
|
||||
- Detail panel slide-in/out.
|
||||
- Subtle status count transitions.
|
||||
|
||||
Do not animate:
|
||||
- Global page container on every render.
|
||||
- Constant hover effects that reduce legibility/performance.
|
||||
|
||||
## 7. Tailwind v4 Implementation Plan
|
||||
|
||||
### Phase A: Design System Foundation (P0)
|
||||
- Add Tailwind v4 pipeline with `@import "tailwindcss"` in global stylesheet.
|
||||
- Define `@theme` token set (colors, radius, spacing aliases, shadows, motion tokens).
|
||||
- Add base layer typography/background defaults.
|
||||
- Replace inline styles in tracer-1 components with tokenized Tailwind classes.
|
||||
|
||||
Acceptance criteria:
|
||||
- No inline style usage in `src/components/kanban/*` and shared primitives (except truly dynamic edge cases).
|
||||
- UI at `localhost:3000` has coherent baseline styling.
|
||||
|
||||
### Phase B: Motion + Interaction Polish (P1)
|
||||
- Integrate Framer Motion transitions for board and panel.
|
||||
- Improve visual hierarchy of card metadata.
|
||||
- Add polished empty/loading/error states.
|
||||
|
||||
Acceptance criteria:
|
||||
- Motion communicates state changes without jitter.
|
||||
- Filtering and detail interactions feel intentional.
|
||||
|
||||
### Phase C: Accessibility + Responsive Hardening (P1)
|
||||
- Keyboard focus and traversal for cards/panel.
|
||||
- Verify color contrast and focus visibility.
|
||||
- Tune mobile breakpoints and touch targets.
|
||||
|
||||
Acceptance criteria:
|
||||
- Keyboard-only flow works for core Kanban actions.
|
||||
- Mobile experience is usable and visually consistent.
|
||||
|
||||
## 8. Technical Boundaries
|
||||
|
||||
- Read path remains `.beads/issues.jsonl` / `.beads/issues.jsonl.new`.
|
||||
- No direct write path to JSONL.
|
||||
- Styling changes must not alter read/write boundary behavior.
|
||||
|
||||
## 9. Definition of Done (Tracer-1 Design Baseline)
|
||||
|
||||
- Tailwind v4 configured and used as primary styling framework.
|
||||
- Tokenized design system applied across tracer-1 Kanban components.
|
||||
- Framer Motion integrated for key transitions.
|
||||
- Tests/typecheck pass, app runs on `localhost:3000`.
|
||||
- Visual result is clearly beyond prototype/demo quality.
|
||||
# BeadBoard Kanban Design System Plan
|
||||
|
||||
**Goal**
|
||||
Ship a production-ready baseline visual system for Tracer Bullet 1 (Kanban) before further feature expansion.
|
||||
|
||||
**Primary decision**
|
||||
Use **Tailwind CSS v4 + CSS tokens (`@theme`) + Framer Motion**.
|
||||
|
||||
## 1. Why This Stack
|
||||
|
||||
### Tailwind v4 is the right baseline
|
||||
- Fastest path to a coherent, reusable system in Next.js 15.
|
||||
- CSS-first token model (`@theme`) fits our need for semantic design tokens.
|
||||
- Lets us avoid scattered inline styles and ad-hoc CSS files.
|
||||
|
||||
### Framer Motion should be scoped
|
||||
- Use for state transitions (card changes, panel enter/exit, filtered results).
|
||||
- Avoid decorative over-animation that hurts readability in a dense dashboard.
|
||||
|
||||
### Risks and mitigations
|
||||
- Risk: “generic Tailwind look”
|
||||
- Mitigation: strict token palette + component contracts + typography rules.
|
||||
- Risk: visual inconsistency
|
||||
- Mitigation: no direct color literals in component markup except token definitions.
|
||||
|
||||
## 2. Baseline-First Sequencing
|
||||
|
||||
This should happen **now**, not later.
|
||||
|
||||
1. Foundation (tokens, layout, core components)
|
||||
2. Motion and interaction polish
|
||||
3. Accessibility and responsive hardening
|
||||
4. Continue other tracer bullets
|
||||
|
||||
## 3. Visual Language (v1)
|
||||
|
||||
### Product feel
|
||||
- High-signal operations UI.
|
||||
- Calm neutral surfaces with sharp status accents.
|
||||
- Dense information without visual clutter.
|
||||
|
||||
### Typography
|
||||
- Primary UI: `DM Sans` (or `Inter` fallback decision at implementation time)
|
||||
- Metadata/IDs: `JetBrains Mono`
|
||||
|
||||
### Color model
|
||||
- Semantic tokens only:
|
||||
- `background`, `foreground`, `surface`, `muted`
|
||||
- `status-open`, `status-in-progress`, `status-blocked`, `status-deferred`, `status-closed`
|
||||
- `priority-p0` ... `priority-p4`
|
||||
- Contrast target: at least WCAG AA for normal text.
|
||||
|
||||
## 4. Component Contract
|
||||
|
||||
Required first-class components:
|
||||
- `KanbanPageShell`
|
||||
- `KanbanControls`
|
||||
- `KanbanBoard`
|
||||
- `KanbanColumn`
|
||||
- `KanbanCard`
|
||||
- `KanbanDetailPanel`
|
||||
- shared: `Badge`, `Chip`, `StatPill`
|
||||
|
||||
Rules:
|
||||
- Component variants defined via class composition (CVA optional but preferred).
|
||||
- No inline style objects for production components.
|
||||
- All spacing/radius/shadow/color come from tokens/utilities.
|
||||
|
||||
## 5. Layout Contract
|
||||
|
||||
### Desktop
|
||||
- Sticky top header with filters + stats.
|
||||
- Main grid: board + detail panel.
|
||||
- Columns scroll horizontally as needed.
|
||||
|
||||
### Mobile
|
||||
- Stacked controls.
|
||||
- Board in horizontal swipe/scroll mode.
|
||||
- Detail panel becomes full-screen drawer.
|
||||
|
||||
## 6. Motion Contract (Framer Motion)
|
||||
|
||||
Use motion for:
|
||||
- Card appear/disappear on filtering.
|
||||
- Detail panel slide-in/out.
|
||||
- Subtle status count transitions.
|
||||
|
||||
Do not animate:
|
||||
- Global page container on every render.
|
||||
- Constant hover effects that reduce legibility/performance.
|
||||
|
||||
## 7. Tailwind v4 Implementation Plan
|
||||
|
||||
### Phase A: Design System Foundation (P0)
|
||||
- Add Tailwind v4 pipeline with `@import "tailwindcss"` in global stylesheet.
|
||||
- Define `@theme` token set (colors, radius, spacing aliases, shadows, motion tokens).
|
||||
- Add base layer typography/background defaults.
|
||||
- Replace inline styles in tracer-1 components with tokenized Tailwind classes.
|
||||
|
||||
Acceptance criteria:
|
||||
- No inline style usage in `src/components/kanban/*` and shared primitives (except truly dynamic edge cases).
|
||||
- UI at `localhost:3000` has coherent baseline styling.
|
||||
|
||||
### Phase B: Motion + Interaction Polish (P1)
|
||||
- Integrate Framer Motion transitions for board and panel.
|
||||
- Improve visual hierarchy of card metadata.
|
||||
- Add polished empty/loading/error states.
|
||||
|
||||
Acceptance criteria:
|
||||
- Motion communicates state changes without jitter.
|
||||
- Filtering and detail interactions feel intentional.
|
||||
|
||||
### Phase C: Accessibility + Responsive Hardening (P1)
|
||||
- Keyboard focus and traversal for cards/panel.
|
||||
- Verify color contrast and focus visibility.
|
||||
- Tune mobile breakpoints and touch targets.
|
||||
|
||||
Acceptance criteria:
|
||||
- Keyboard-only flow works for core Kanban actions.
|
||||
- Mobile experience is usable and visually consistent.
|
||||
|
||||
## 8. Technical Boundaries
|
||||
|
||||
- Read path remains `.beads/issues.jsonl` / `.beads/issues.jsonl.new`.
|
||||
- No direct write path to JSONL.
|
||||
- Styling changes must not alter read/write boundary behavior.
|
||||
|
||||
## 9. Definition of Done (Tracer-1 Design Baseline)
|
||||
|
||||
- Tailwind v4 configured and used as primary styling framework.
|
||||
- Tokenized design system applied across tracer-1 Kanban components.
|
||||
- Framer Motion integrated for key transitions.
|
||||
- Tests/typecheck pass, app runs on `localhost:3000`.
|
||||
- Visual result is clearly beyond prototype/demo quality.
|
||||
|
|
|
|||
|
|
@ -1,52 +1,52 @@
|
|||
# Project Context Model Design
|
||||
|
||||
## Summary
|
||||
Aggregate views need stable project identity attached to each issue so cross-project Kanban, timeline, and session views can filter and display project metadata consistently. This design adds a normalized `ProjectContext` payload to every issue returned from read flows while keeping the raw JSONL format untouched.
|
||||
|
||||
## Requirements
|
||||
- Use existing Windows-safe path normalization for stable identity.
|
||||
- Attach project identity on every issue returned from read services.
|
||||
- Include fields: `key`, `root`, `displayPath`, `name`, `source`, `addedAt`.
|
||||
- Default single-project reads to `source="local"` and `addedAt=null`.
|
||||
|
||||
## Data Model
|
||||
```ts
|
||||
export type ProjectSource = 'local' | 'registry' | 'scanner';
|
||||
|
||||
export interface ProjectContext {
|
||||
key: string; // windowsPathKey(root)
|
||||
root: string; // canonicalizeWindowsPath(root)
|
||||
displayPath: string; // toDisplayPath(root)
|
||||
name: string; // path.basename(root)
|
||||
source: ProjectSource;
|
||||
addedAt: string | null;
|
||||
}
|
||||
|
||||
export type BeadIssueWithProject = BeadIssue & { project: ProjectContext };
|
||||
```
|
||||
|
||||
## Construction
|
||||
- Add a helper (e.g., `buildProjectContext`) that accepts `projectRoot`, `source`, and `addedAt`.
|
||||
- Normalize the root with `canonicalizeWindowsPath`, compute the key with `windowsPathKey`, display path with `toDisplayPath`, and name from `path.basename`.
|
||||
- No filesystem checks are required; this is identity metadata only.
|
||||
|
||||
## Read Flow Integration
|
||||
- Update `readIssuesFromDisk` to attach `project` to each parsed issue.
|
||||
- Default `projectRoot` to `process.cwd()` when not provided.
|
||||
- Keep the existing `BeadIssue` shape for raw parsing; project context is added in read services only.
|
||||
|
||||
## Error Handling
|
||||
- If `projectRoot` is empty, throw a clear error early in `buildProjectContext`.
|
||||
- Otherwise, treat normalization as pure string ops and do not swallow exceptions.
|
||||
|
||||
## Tests
|
||||
- Add unit tests for `buildProjectContext` field derivation (key/root/displayPath/name/source/addedAt).
|
||||
- Update `readIssuesFromDisk` tests to assert `project` is attached with expected fields.
|
||||
|
||||
## Alternatives Considered
|
||||
1. **Wrapper object `{ project, issue }`**
|
||||
Pro: explicit separation; Con: more refactors across UI filtering and query shapes.
|
||||
2. **`metadata.project` on issues**
|
||||
Pro: zero type changes; Con: weak typing and harder discoverability.
|
||||
3. **Chosen: `issue.project` field**
|
||||
Clear typing, predictable access, and minimal friction for UI + aggregate queries.
|
||||
# Project Context Model Design
|
||||
|
||||
## Summary
|
||||
Aggregate views need stable project identity attached to each issue so cross-project Kanban, timeline, and session views can filter and display project metadata consistently. This design adds a normalized `ProjectContext` payload to every issue returned from read flows while keeping the raw JSONL format untouched.
|
||||
|
||||
## Requirements
|
||||
- Use existing Windows-safe path normalization for stable identity.
|
||||
- Attach project identity on every issue returned from read services.
|
||||
- Include fields: `key`, `root`, `displayPath`, `name`, `source`, `addedAt`.
|
||||
- Default single-project reads to `source="local"` and `addedAt=null`.
|
||||
|
||||
## Data Model
|
||||
```ts
|
||||
export type ProjectSource = 'local' | 'registry' | 'scanner';
|
||||
|
||||
export interface ProjectContext {
|
||||
key: string; // windowsPathKey(root)
|
||||
root: string; // canonicalizeWindowsPath(root)
|
||||
displayPath: string; // toDisplayPath(root)
|
||||
name: string; // path.basename(root)
|
||||
source: ProjectSource;
|
||||
addedAt: string | null;
|
||||
}
|
||||
|
||||
export type BeadIssueWithProject = BeadIssue & { project: ProjectContext };
|
||||
```
|
||||
|
||||
## Construction
|
||||
- Add a helper (e.g., `buildProjectContext`) that accepts `projectRoot`, `source`, and `addedAt`.
|
||||
- Normalize the root with `canonicalizeWindowsPath`, compute the key with `windowsPathKey`, display path with `toDisplayPath`, and name from `path.basename`.
|
||||
- No filesystem checks are required; this is identity metadata only.
|
||||
|
||||
## Read Flow Integration
|
||||
- Update `readIssuesFromDisk` to attach `project` to each parsed issue.
|
||||
- Default `projectRoot` to `process.cwd()` when not provided.
|
||||
- Keep the existing `BeadIssue` shape for raw parsing; project context is added in read services only.
|
||||
|
||||
## Error Handling
|
||||
- If `projectRoot` is empty, throw a clear error early in `buildProjectContext`.
|
||||
- Otherwise, treat normalization as pure string ops and do not swallow exceptions.
|
||||
|
||||
## Tests
|
||||
- Add unit tests for `buildProjectContext` field derivation (key/root/displayPath/name/source/addedAt).
|
||||
- Update `readIssuesFromDisk` tests to assert `project` is attached with expected fields.
|
||||
|
||||
## Alternatives Considered
|
||||
1. **Wrapper object `{ project, issue }`**
|
||||
Pro: explicit separation; Con: more refactors across UI filtering and query shapes.
|
||||
2. **`metadata.project` on issues**
|
||||
Pro: zero type changes; Con: weak typing and harder discoverability.
|
||||
3. **Chosen: `issue.project` field**
|
||||
Clear typing, predictable access, and minimal friction for UI + aggregate queries.
|
||||
|
|
|
|||
|
|
@ -1,139 +1,139 @@
|
|||
# Multi-Project UI Contract (bb-6aj.6)
|
||||
|
||||
Date: 2026-02-13
|
||||
Owner: `bb-6aj.6`
|
||||
Scope: Convert existing registry/scanner backend into stable, user-facing project scope workflows for Kanban and Graph.
|
||||
|
||||
## 1) Product Workflow Contract
|
||||
|
||||
Primary user flow:
|
||||
1. Select project scope (`local` or one registry project).
|
||||
2. View project-scoped issues in Kanban and Graph using the same selected scope.
|
||||
3. Manage registry roots (add/remove) from a single shared manager panel.
|
||||
4. Discover import candidates from safe scan roots and add selected projects to registry.
|
||||
5. (Later phase) Optionally switch to aggregate mode for cross-project read-only views.
|
||||
|
||||
Rules:
|
||||
- Project scope is always explicit in URL query (`?project=`).
|
||||
- Scope change affects reads only; mutations continue to target current scope root.
|
||||
- Project scope must persist when navigating between `/` and `/graph`.
|
||||
- No direct JSONL writes at any point.
|
||||
|
||||
## 2) Screen Ownership
|
||||
|
||||
Kanban (`/`):
|
||||
- Primary triage and mutation workspace.
|
||||
- Owns project scope picker entry point and registry manager entry.
|
||||
- Displays selected project context in header.
|
||||
|
||||
Graph (`/graph`):
|
||||
- Readability-first dependency exploration for selected scope.
|
||||
- Shares same project scope query + model as Kanban.
|
||||
- Must preserve current scope when linking back to Kanban.
|
||||
|
||||
Shared controls:
|
||||
- Project scope resolver utility (server-safe).
|
||||
- URL serialization/parsing for project selection.
|
||||
- Scope badge/pill visual token (consistent across pages).
|
||||
|
||||
Out of scope for this contract:
|
||||
- Timeline/session epics behavior changes.
|
||||
- Full graph redesign beyond scope persistence/read correctness.
|
||||
|
||||
## 3) URL and State Contract
|
||||
|
||||
Query key:
|
||||
- `project`: scope key string.
|
||||
|
||||
Key encoding:
|
||||
- `local`: current workspace (`process.cwd()`).
|
||||
- registry project: `windowsPathKey(project.path)` derived from registry entry.
|
||||
|
||||
Resolution behavior:
|
||||
1. Build scope options: `local` + registry projects (dedup by key).
|
||||
2. If `project` query matches an option key, use that root.
|
||||
3. If missing or invalid, fallback to `local`.
|
||||
4. Reads use resolved root; returned issues include resolved `project` context.
|
||||
|
||||
Navigation behavior:
|
||||
- `Kanban -> Graph` carries `?project=<key>`.
|
||||
- `Graph -> Kanban` carries `?project=<key>`.
|
||||
- Any scope picker action rewrites URL query without losing active route.
|
||||
|
||||
## 4) Aggregate Mode Contract (Deferred to bb-6aj.11)
|
||||
|
||||
- Aggregate mode is read-only across multiple project roots.
|
||||
- Aggregate mode does not become default.
|
||||
- Aggregate mode must visually mark per-project source on each card/row.
|
||||
- Mutations from aggregate mode are disabled until explicit target scope is chosen.
|
||||
|
||||
## 5) Empty and Error States
|
||||
|
||||
No projects in registry:
|
||||
- Show local project as selected.
|
||||
- Show non-blocking empty hint in manager panel.
|
||||
|
||||
Invalid query key:
|
||||
- Fallback to local scope.
|
||||
- Keep page functional; do not hard fail.
|
||||
|
||||
Read failure for selected root:
|
||||
- Preserve selected scope in UI.
|
||||
- Show actionable error card with path and retry affordance.
|
||||
|
||||
Scanner failures:
|
||||
- Show root-level failure summary with skipped/error counts.
|
||||
- Do not alter current selection automatically.
|
||||
|
||||
## 6) Phased Execution Plan
|
||||
|
||||
Phase A (`bb-6aj.7`): Shared scope model + URL persistence
|
||||
- Add server utility to resolve active scope from query + registry.
|
||||
- Wire `/` and `/graph` to resolved scope.
|
||||
- Ensure cross-links preserve `?project=`.
|
||||
|
||||
Phase B (`bb-6aj.8`): Registry manager panel
|
||||
- List registry projects with add/remove actions.
|
||||
- Validate Windows absolute paths with clear error text.
|
||||
|
||||
Phase C (`bb-6aj.9`): Scanner UX
|
||||
- Scan safe roots with mode/depth controls.
|
||||
- Allow selective import to registry.
|
||||
|
||||
Phase D (`bb-6aj.10`): Project-scoped reads in core views
|
||||
- Ensure all read endpoints/components use selected scope root.
|
||||
- Validate no regressions in local-only flow.
|
||||
|
||||
Phase E (`bb-6aj.11`): Aggregate mode
|
||||
- Add cross-project read view with project badges.
|
||||
- Keep mutations disabled without explicit project selection.
|
||||
|
||||
Phase F (`bb-6aj.12`): Verification and guardrails
|
||||
- Typecheck + tests + Playwright evidence at required breakpoints.
|
||||
|
||||
## 7) Acceptance Criteria Matrix
|
||||
|
||||
Functional:
|
||||
- Same `project` key yields same root and same issue set on both pages.
|
||||
- Invalid `project` key falls back to local root cleanly.
|
||||
- Route transitions preserve selected scope.
|
||||
|
||||
Boundary safety:
|
||||
- No direct `.beads/issues.jsonl` writes.
|
||||
- Existing mutation API boundaries unchanged.
|
||||
|
||||
Verification:
|
||||
- Unit tests for scope resolution and URL behavior.
|
||||
- Existing tests remain green.
|
||||
- Playwright captures prove scope persistence on `/` and `/graph`.
|
||||
|
||||
## 8) Risks and Mitigations
|
||||
|
||||
Risk: Query value leaks absolute paths.
|
||||
- Mitigation: use opaque normalized key, not raw path.
|
||||
|
||||
Risk: Registry drift vs URL key stale.
|
||||
- Mitigation: deterministic fallback to local + visible selected-scope indicator.
|
||||
|
||||
Risk: UX churn from adding controls too early.
|
||||
- Mitigation: enforce phase order and keep Phase A minimal.
|
||||
# Multi-Project UI Contract (bb-6aj.6)
|
||||
|
||||
Date: 2026-02-13
|
||||
Owner: `bb-6aj.6`
|
||||
Scope: Convert existing registry/scanner backend into stable, user-facing project scope workflows for Kanban and Graph.
|
||||
|
||||
## 1) Product Workflow Contract
|
||||
|
||||
Primary user flow:
|
||||
1. Select project scope (`local` or one registry project).
|
||||
2. View project-scoped issues in Kanban and Graph using the same selected scope.
|
||||
3. Manage registry roots (add/remove) from a single shared manager panel.
|
||||
4. Discover import candidates from safe scan roots and add selected projects to registry.
|
||||
5. (Later phase) Optionally switch to aggregate mode for cross-project read-only views.
|
||||
|
||||
Rules:
|
||||
- Project scope is always explicit in URL query (`?project=`).
|
||||
- Scope change affects reads only; mutations continue to target current scope root.
|
||||
- Project scope must persist when navigating between `/` and `/graph`.
|
||||
- No direct JSONL writes at any point.
|
||||
|
||||
## 2) Screen Ownership
|
||||
|
||||
Kanban (`/`):
|
||||
- Primary triage and mutation workspace.
|
||||
- Owns project scope picker entry point and registry manager entry.
|
||||
- Displays selected project context in header.
|
||||
|
||||
Graph (`/graph`):
|
||||
- Readability-first dependency exploration for selected scope.
|
||||
- Shares same project scope query + model as Kanban.
|
||||
- Must preserve current scope when linking back to Kanban.
|
||||
|
||||
Shared controls:
|
||||
- Project scope resolver utility (server-safe).
|
||||
- URL serialization/parsing for project selection.
|
||||
- Scope badge/pill visual token (consistent across pages).
|
||||
|
||||
Out of scope for this contract:
|
||||
- Timeline/session epics behavior changes.
|
||||
- Full graph redesign beyond scope persistence/read correctness.
|
||||
|
||||
## 3) URL and State Contract
|
||||
|
||||
Query key:
|
||||
- `project`: scope key string.
|
||||
|
||||
Key encoding:
|
||||
- `local`: current workspace (`process.cwd()`).
|
||||
- registry project: `windowsPathKey(project.path)` derived from registry entry.
|
||||
|
||||
Resolution behavior:
|
||||
1. Build scope options: `local` + registry projects (dedup by key).
|
||||
2. If `project` query matches an option key, use that root.
|
||||
3. If missing or invalid, fallback to `local`.
|
||||
4. Reads use resolved root; returned issues include resolved `project` context.
|
||||
|
||||
Navigation behavior:
|
||||
- `Kanban -> Graph` carries `?project=<key>`.
|
||||
- `Graph -> Kanban` carries `?project=<key>`.
|
||||
- Any scope picker action rewrites URL query without losing active route.
|
||||
|
||||
## 4) Aggregate Mode Contract (Deferred to bb-6aj.11)
|
||||
|
||||
- Aggregate mode is read-only across multiple project roots.
|
||||
- Aggregate mode does not become default.
|
||||
- Aggregate mode must visually mark per-project source on each card/row.
|
||||
- Mutations from aggregate mode are disabled until explicit target scope is chosen.
|
||||
|
||||
## 5) Empty and Error States
|
||||
|
||||
No projects in registry:
|
||||
- Show local project as selected.
|
||||
- Show non-blocking empty hint in manager panel.
|
||||
|
||||
Invalid query key:
|
||||
- Fallback to local scope.
|
||||
- Keep page functional; do not hard fail.
|
||||
|
||||
Read failure for selected root:
|
||||
- Preserve selected scope in UI.
|
||||
- Show actionable error card with path and retry affordance.
|
||||
|
||||
Scanner failures:
|
||||
- Show root-level failure summary with skipped/error counts.
|
||||
- Do not alter current selection automatically.
|
||||
|
||||
## 6) Phased Execution Plan
|
||||
|
||||
Phase A (`bb-6aj.7`): Shared scope model + URL persistence
|
||||
- Add server utility to resolve active scope from query + registry.
|
||||
- Wire `/` and `/graph` to resolved scope.
|
||||
- Ensure cross-links preserve `?project=`.
|
||||
|
||||
Phase B (`bb-6aj.8`): Registry manager panel
|
||||
- List registry projects with add/remove actions.
|
||||
- Validate Windows absolute paths with clear error text.
|
||||
|
||||
Phase C (`bb-6aj.9`): Scanner UX
|
||||
- Scan safe roots with mode/depth controls.
|
||||
- Allow selective import to registry.
|
||||
|
||||
Phase D (`bb-6aj.10`): Project-scoped reads in core views
|
||||
- Ensure all read endpoints/components use selected scope root.
|
||||
- Validate no regressions in local-only flow.
|
||||
|
||||
Phase E (`bb-6aj.11`): Aggregate mode
|
||||
- Add cross-project read view with project badges.
|
||||
- Keep mutations disabled without explicit project selection.
|
||||
|
||||
Phase F (`bb-6aj.12`): Verification and guardrails
|
||||
- Typecheck + tests + Playwright evidence at required breakpoints.
|
||||
|
||||
## 7) Acceptance Criteria Matrix
|
||||
|
||||
Functional:
|
||||
- Same `project` key yields same root and same issue set on both pages.
|
||||
- Invalid `project` key falls back to local root cleanly.
|
||||
- Route transitions preserve selected scope.
|
||||
|
||||
Boundary safety:
|
||||
- No direct `.beads/issues.jsonl` writes.
|
||||
- Existing mutation API boundaries unchanged.
|
||||
|
||||
Verification:
|
||||
- Unit tests for scope resolution and URL behavior.
|
||||
- Existing tests remain green.
|
||||
- Playwright captures prove scope persistence on `/` and `/graph`.
|
||||
|
||||
## 8) Risks and Mitigations
|
||||
|
||||
Risk: Query value leaks absolute paths.
|
||||
- Mitigation: use opaque normalized key, not raw path.
|
||||
|
||||
Risk: Registry drift vs URL key stale.
|
||||
- Mitigation: deterministic fallback to local + visible selected-scope indicator.
|
||||
|
||||
Risk: UX churn from adding controls too early.
|
||||
- Mitigation: enforce phase order and keep Phase A minimal.
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
# Unified UX PRD - Swimlane Social Hub
|
||||
|
||||
# Unified UX PRD - Swimlane Social Hub
|
||||
|
||||
> **Version**: 2.0
|
||||
> **Date**: 2026-02-16
|
||||
> **Status**: UPDATED - Complete Design Specification
|
||||
|
|
@ -19,356 +19,356 @@
|
|||
### Phase 1-3: Not Started
|
||||
- Planning complete, implementation pending Phase 0 completion
|
||||
|
||||
|
||||
---
|
||||
|
||||
## Executive Summary
|
||||
|
||||
### Problem
|
||||
BeadBoard has 4 fragmented pages with no shared navigation, no shared state, and inconsistent design language. The current Aero Chrome glass-morphism visual style has been rejected by users. Users want ONE cohesive experience for supervising multi-agent teams and managing tasks.
|
||||
|
||||
### Solution
|
||||
Single unified shell at `/` with 4 switchable views (Social Feed, Swimlanes, Graph, Timeline), new earthy-dark design system, agent-prominent UX, and thoughtful interaction patterns throughout.
|
||||
|
||||
---
|
||||
|
||||
## Key Decisions (Immutable)
|
||||
|
||||
| # | Decision | Choice | Rationale |
|
||||
|---|----------|--------|-----------|
|
||||
| 1 | Routing | Single page + client tabs at / | Preserves selection state, panels never unmount |
|
||||
| 2 | State Source | URL is Single Source of Truth | Prevents race conditions |
|
||||
| 3 | Activity Feed | Context-aware (filters to selection) | Most useful for supervision workflow |
|
||||
| 4 | Mobile | Hamburger left + slide-over right + bottom tabs | Standard pattern |
|
||||
| 5 | Build Order | Tokens → Shell → Views (tracer bullet) | Real dependency chain |
|
||||
| 6 | Card Interaction | Selection + detail strip below grid (desktop) | Grid stays uniform, split-view for conversation |
|
||||
| 7 | Mobile Detail | Full-screen overlay (not split) | Keyboard takes 40% of screen |
|
||||
| 8 | Visual Style | Earthy-dark design system (NOT Aero Chrome) | User provided full token spec |
|
||||
| 9 | Agent Presence | Prominent - agents are the star | Avatars on every card, role-colored borders |
|
||||
| 10 | Left Panel | Minimal with counts, nested epic tree | Status dots, hover tooltips |
|
||||
| 11 | Card View-Jump | Small icons at card bottom | Jump to views with task pre-selected |
|
||||
| 12 | Units | rem-based | Accessibility |
|
||||
|
||||
---
|
||||
|
||||
## Design Token Specification
|
||||
|
||||
### Color Palette
|
||||
|
||||
**Backgrounds:**
|
||||
```css
|
||||
--color-bg-base: #2D2D2D /* primary background */
|
||||
--color-bg-card: #363636 /* cards, elevated surfaces */
|
||||
--color-bg-input: #404040 /* inputs, hover states */
|
||||
```
|
||||
|
||||
**Accents:**
|
||||
```css
|
||||
--color-accent-green: #7CB97A /* primary CTA, success, in-progress */
|
||||
--color-accent-amber: #D4A574 /* warning, blocked */
|
||||
--color-accent-teal: #5BA8A0 /* secondary, open/ready */
|
||||
```
|
||||
|
||||
**Text:**
|
||||
```css
|
||||
--color-text-primary: #FFFFFF
|
||||
--color-text-secondary: #B8B8B8
|
||||
--color-text-muted: #888888
|
||||
--color-text-on-primary: #1A1A1A
|
||||
```
|
||||
|
||||
**Borders:**
|
||||
```css
|
||||
--color-border-default: #4A4A4A
|
||||
--color-border-subtle: #3A3A3A
|
||||
```
|
||||
|
||||
**Status Mapping:**
|
||||
- open/ready → teal `#5BA8A0`
|
||||
- in_progress → green `#7CB97A`
|
||||
- blocked → amber `#D4A574`
|
||||
- closed → muted `#888888`
|
||||
|
||||
**Agent Role Colors:**
|
||||
- ui → `#6B9BD2` (steel blue)
|
||||
- graph → `#7CB97A` (green)
|
||||
- orchestrator → `#B08ED6` (soft purple)
|
||||
- agent → `#B8B8B8` (neutral)
|
||||
- researcher → `#D4A574` (amber)
|
||||
|
||||
**Liveness Colors:**
|
||||
- active → `#7CB97A` (green, pulsing)
|
||||
- stale → `#D4A574` (amber)
|
||||
- evicted → `#C97A7A` (muted rose)
|
||||
- idle → `#888888` (muted)
|
||||
|
||||
### Radii
|
||||
```css
|
||||
--radius-sm: 0.375rem /* 6px */
|
||||
--radius-card: 0.625rem /* 10px */
|
||||
--radius-modal: 1rem /* 16px */
|
||||
--radius-pill: 9999px
|
||||
```
|
||||
|
||||
### Shadows
|
||||
```css
|
||||
--shadow-sm: 0 1px 2px rgba(0,0,0,0.1)
|
||||
--shadow-md: 0 4px 12px rgba(0,0,0,0.15)
|
||||
```
|
||||
|
||||
### Typography
|
||||
- Font: system sans-serif (Inter if available)
|
||||
- H1: 2rem/700, H2: 1.5rem/600, H3: 1.125rem/600
|
||||
- Body: 0.875rem/400, Small: 0.75rem/400, Tiny: 0.6875rem/500
|
||||
- Line-height: headings 1.2, body 1.5
|
||||
|
||||
### Spacing
|
||||
- Base: 0.25rem (4px)
|
||||
- Card padding: 1rem-1.25rem
|
||||
- Gaps: 1rem
|
||||
- Section gaps: 2rem-2.5rem
|
||||
|
||||
### Icons & Transitions
|
||||
- Icons: Lucide React, 1.5-2px stroke, 1rem-1.5rem size
|
||||
- Transitions: 150-200ms ease-out for all hover/focus
|
||||
|
||||
---
|
||||
|
||||
## Component Anatomy
|
||||
|
||||
### Social Feed Card
|
||||
|
||||
```
|
||||
┌─────────────────────────────────────┐
|
||||
│ [⊕] (top-R)│ expand icon
|
||||
│ │
|
||||
│ bb-buff.1.1 │ task ID (tiny, teal)
|
||||
│ Fix login bug on mobile │ title (bold, white)
|
||||
│ │
|
||||
│ UNLOCKS: │ blocked-by (ROSE tint)
|
||||
│ ● #123 Blocker task │
|
||||
│ │
|
||||
│ BLOCKS: │ downstream (AMBER tint)
|
||||
│ ● #234 Dependent task │
|
||||
│ │
|
||||
│ "Found the issue in the auth..." │ latest message (muted)
|
||||
│ │
|
||||
│ [●a-1] [●a-2] │ agent avatars (PROMINENT)
|
||||
│ [≡] [◊] [≋]│ view-jump icons
|
||||
└─────────────────────────────────────┘
|
||||
```
|
||||
|
||||
**Card Specs:**
|
||||
- Background: `#363636`
|
||||
- Border: 1px status-colored (teal/green/amber/muted)
|
||||
- Border-radius: 10px
|
||||
- Status dot on card matches status mapping
|
||||
- Agent avatars have **role-colored left border**
|
||||
- Blocks/unlocks have tinted backgrounds (rose #E57373/10%, amber #D4A574/10%)
|
||||
|
||||
**Blocks/Unlocks Pattern (reuse from task-card-grid.tsx):**
|
||||
```tsx
|
||||
// Container
|
||||
rounded-lg p-2 border border-white/5
|
||||
|
||||
// "Unlocks" header (rose tint)
|
||||
text-[9px] font-bold uppercase tracking-widest text-rose-400/80
|
||||
bg-rose-500/10 // background tint
|
||||
|
||||
// "Blocks" header (amber tint)
|
||||
text-[9px] font-bold uppercase tracking-widest text-amber-400/80
|
||||
bg-amber-500/10 // background tint
|
||||
|
||||
// Individual item
|
||||
rounded border border-white/5 bg-white/5 px-2.5 py-2
|
||||
hover:border-sky-400/30 hover:bg-white/10 transition-colors
|
||||
```
|
||||
|
||||
### ZFC Agent State Visuals
|
||||
|
||||
| State | Visual |
|
||||
|-------|--------|
|
||||
| idle | `#888888` static dot |
|
||||
| spawning | `#5BA8A0` pulsing dot |
|
||||
| running | `#7CB97A` animated dot |
|
||||
| working | `#7CB97A` pulsing glow |
|
||||
| stuck | `#D4A574` attention dot (needs help!) |
|
||||
| done | `#7CB97A` check |
|
||||
| stopped | `#888888` no animation |
|
||||
| dead | `#C97A7A` warning |
|
||||
|
||||
### Agent Card (Right Panel)
|
||||
|
||||
```
|
||||
┌──────────────────────┐
|
||||
│ [●avatar] agent-1 │ role-colored left border
|
||||
│ role: ui │ role label
|
||||
│ ● working · 2m ago │ ZFC state dot + age
|
||||
│ Task: buff.1.1 │ current task
|
||||
│ [≡] [◊] [≋] [💬] │ view-jump + message
|
||||
└──────────────────────┘
|
||||
```
|
||||
|
||||
### Swimlane Header
|
||||
- Swarm name + computed counts: "3/8 done · 2 active · 1 ready · 1 blocked"
|
||||
- Agent roster with ZFC state labels
|
||||
- Collapsible
|
||||
|
||||
---
|
||||
|
||||
## Layout Architecture
|
||||
|
||||
### Shell Structure (CSS Grid)
|
||||
|
||||
```
|
||||
┌──────────────────────────────────────────────────────────────────┐
|
||||
│ TOP BAR (fixed, 3rem) │
|
||||
│ ≡ [Swimlanes|Graph|Timeline|Social] ◢ │
|
||||
├──────────┬──────────────────────────────────┬────────────────────┤
|
||||
│ LEFT │ MIDDLE │ RIGHT │
|
||||
│ 13.75rem │ flex-1 │ 17.5rem │
|
||||
│ │ │ │
|
||||
│ Channel │ View content (swaps on tab) │ Agents (~40%) │
|
||||
│ tree │ │ ────────────────── │
|
||||
│ │ │ Activity (~60%) │
|
||||
└──────────┴──────────────────────────────────┴────────────────────┘
|
||||
```
|
||||
|
||||
**Grid:** `grid-template-columns: 13.75rem 1fr 17.5rem`
|
||||
|
||||
### Detail Strip Behavior
|
||||
|
||||
**Desktop (≥1024px):**
|
||||
- Grid splits: cards (~45%) | detail strip (~55%)
|
||||
- Strip slides in below grid when card selected
|
||||
- Cards remain visible above
|
||||
|
||||
**Mobile (<768px):**
|
||||
- Full-screen overlay (z-index above bottom tabs)
|
||||
- Required: virtual keyboard takes 40% of screen
|
||||
- Split view would leave 0px for conversation
|
||||
|
||||
### Responsive Behavior
|
||||
|
||||
| Size | Left | Middle | Right | Detail Strip |
|
||||
|------|------|--------|-------|--------------|
|
||||
| Desktop (≥1024px) | 13.75rem fixed | flex-1 | 17.5rem fixed | Below grid |
|
||||
| Tablet (768-1024px) | Overlay | flex-1 | Overlay | Slide-over |
|
||||
| Mobile (<768px) | Overlay | flex-1 | Hidden | Full-screen |
|
||||
|
||||
---
|
||||
|
||||
## Anti-Patterns (Forbidden)
|
||||
|
||||
- NO glass-morphism / backdrop-blur effects
|
||||
- NO arbitrary Tailwind color values (use tokens)
|
||||
- NO agent-unaware cards (every card shows agents)
|
||||
- NO page-per-view routing (use client tabs)
|
||||
- NO localStorage for view state (use URL)
|
||||
- NO direct JSONL writes (use bd CLI)
|
||||
|
||||
---
|
||||
|
||||
## Recommended Bead Structure
|
||||
|
||||
### Phase 0: Design Foundation
|
||||
**Goal:** Tokens + Primitives only. No views.
|
||||
|
||||
**bb-ui2.1a** - Token System Update
|
||||
- Update tokens.css with complete spec above
|
||||
- Ensure all status/liveness/role colors defined
|
||||
- Migrate away from Aero Chrome gradients
|
||||
|
||||
**bb-ui2.2a** - Card Primitive with Blocks/Unlocks
|
||||
- Build reusable Card component
|
||||
- Implement blocks/unlocks section pattern (reuse task-card-grid.tsx logic)
|
||||
- Status-colored borders
|
||||
- Soft gradient backgrounds (amber/teal tints, not harsh Aero Chrome)
|
||||
|
||||
**bb-ui2.3a** - Agent Avatar Primitive
|
||||
- Avatar with role-colored ring
|
||||
- ZFC state indicator (dot/pulse/glow)
|
||||
- Size variants (sm, md, lg)
|
||||
|
||||
**bb-ui2.4a** - Status Utilities Update
|
||||
- Rewrite status-utils.tsx for new tokens
|
||||
- Status badge component with pill + dot
|
||||
- Liveness indicator component
|
||||
|
||||
### Phase 1: Layout Polish
|
||||
**Goal:** Fix current layout issues, preserve structure
|
||||
|
||||
**bb-ui2.22** - Detail Strip Positioning Fix
|
||||
- Move from side drawer to below-grid (desktop)
|
||||
- Full-screen overlay (mobile)
|
||||
- Preserve URL state behavior
|
||||
- Thread content actually shows selected bead data
|
||||
|
||||
**bb-ui2.23** - Activity Panel Polish
|
||||
- Split right panel: Agents (40%) + Activity (60%)
|
||||
- Agent cards with ZFC states
|
||||
- Context-aware activity filtering
|
||||
|
||||
**bb-ui2.24** - Mobile Responsive Polish
|
||||
- Bottom tab bar
|
||||
- Panel overlays
|
||||
- Touch-friendly targets
|
||||
|
||||
### Phase 2: Card Design Implementation
|
||||
**Goal:** Implement complete card anatomy
|
||||
|
||||
**bb-ui2.25** - Social Feed Card Redesign
|
||||
- Full card anatomy from spec
|
||||
- Blocks/unlocks with rose/amber tints
|
||||
- Prominent agent avatars
|
||||
- View-jump icons
|
||||
- Expand icon → full-page popup
|
||||
|
||||
**bb-ui2.26** - Swimlane Card Redesign
|
||||
- Agent-first layout
|
||||
- ZFC state prominent
|
||||
- Status-colored border
|
||||
- Drag-drop preserved
|
||||
|
||||
**bb-ui2.27** - Graph Node Redesign
|
||||
- New design tokens
|
||||
- Agent avatars on nodes
|
||||
- Selection syncs with store
|
||||
|
||||
### Phase 3: Cross-Cutting Polish
|
||||
**Goal:** Deep links, mobile, final gates
|
||||
|
||||
**bb-ui2.28** - Deep Link Verification
|
||||
- All URL patterns work
|
||||
- Browser back/forward
|
||||
- Shareable URLs
|
||||
|
||||
**bb-ui2.29** - Screenshot Evidence
|
||||
- All breakpoints
|
||||
- All views
|
||||
- Mobile + desktop
|
||||
|
||||
**bb-ui2.30** - Final Gates
|
||||
- typecheck, lint, test
|
||||
- Close epic
|
||||
|
||||
---
|
||||
|
||||
## Verification Strategy
|
||||
|
||||
After each bead:
|
||||
```bash
|
||||
npm run typecheck
|
||||
npm run lint
|
||||
npm run test
|
||||
```
|
||||
|
||||
Visual verification:
|
||||
- Screenshots at 390px, 768px, 1440px
|
||||
- Compare against design spec
|
||||
- Agent avatars visible on all cards
|
||||
- Blocks/unlocks sections tinted correctly
|
||||
|
||||
---
|
||||
|
||||
*End of PRD v2.0 - Ready for Implementation*
|
||||
|
||||
---
|
||||
|
||||
## Executive Summary
|
||||
|
||||
### Problem
|
||||
BeadBoard has 4 fragmented pages with no shared navigation, no shared state, and inconsistent design language. The current Aero Chrome glass-morphism visual style has been rejected by users. Users want ONE cohesive experience for supervising multi-agent teams and managing tasks.
|
||||
|
||||
### Solution
|
||||
Single unified shell at `/` with 4 switchable views (Social Feed, Swimlanes, Graph, Timeline), new earthy-dark design system, agent-prominent UX, and thoughtful interaction patterns throughout.
|
||||
|
||||
---
|
||||
|
||||
## Key Decisions (Immutable)
|
||||
|
||||
| # | Decision | Choice | Rationale |
|
||||
|---|----------|--------|-----------|
|
||||
| 1 | Routing | Single page + client tabs at / | Preserves selection state, panels never unmount |
|
||||
| 2 | State Source | URL is Single Source of Truth | Prevents race conditions |
|
||||
| 3 | Activity Feed | Context-aware (filters to selection) | Most useful for supervision workflow |
|
||||
| 4 | Mobile | Hamburger left + slide-over right + bottom tabs | Standard pattern |
|
||||
| 5 | Build Order | Tokens → Shell → Views (tracer bullet) | Real dependency chain |
|
||||
| 6 | Card Interaction | Selection + detail strip below grid (desktop) | Grid stays uniform, split-view for conversation |
|
||||
| 7 | Mobile Detail | Full-screen overlay (not split) | Keyboard takes 40% of screen |
|
||||
| 8 | Visual Style | Earthy-dark design system (NOT Aero Chrome) | User provided full token spec |
|
||||
| 9 | Agent Presence | Prominent - agents are the star | Avatars on every card, role-colored borders |
|
||||
| 10 | Left Panel | Minimal with counts, nested epic tree | Status dots, hover tooltips |
|
||||
| 11 | Card View-Jump | Small icons at card bottom | Jump to views with task pre-selected |
|
||||
| 12 | Units | rem-based | Accessibility |
|
||||
|
||||
---
|
||||
|
||||
## Design Token Specification
|
||||
|
||||
### Color Palette
|
||||
|
||||
**Backgrounds:**
|
||||
```css
|
||||
--color-bg-base: #2D2D2D /* primary background */
|
||||
--color-bg-card: #363636 /* cards, elevated surfaces */
|
||||
--color-bg-input: #404040 /* inputs, hover states */
|
||||
```
|
||||
|
||||
**Accents:**
|
||||
```css
|
||||
--color-accent-green: #7CB97A /* primary CTA, success, in-progress */
|
||||
--color-accent-amber: #D4A574 /* warning, blocked */
|
||||
--color-accent-teal: #5BA8A0 /* secondary, open/ready */
|
||||
```
|
||||
|
||||
**Text:**
|
||||
```css
|
||||
--color-text-primary: #FFFFFF
|
||||
--color-text-secondary: #B8B8B8
|
||||
--color-text-muted: #888888
|
||||
--color-text-on-primary: #1A1A1A
|
||||
```
|
||||
|
||||
**Borders:**
|
||||
```css
|
||||
--color-border-default: #4A4A4A
|
||||
--color-border-subtle: #3A3A3A
|
||||
```
|
||||
|
||||
**Status Mapping:**
|
||||
- open/ready → teal `#5BA8A0`
|
||||
- in_progress → green `#7CB97A`
|
||||
- blocked → amber `#D4A574`
|
||||
- closed → muted `#888888`
|
||||
|
||||
**Agent Role Colors:**
|
||||
- ui → `#6B9BD2` (steel blue)
|
||||
- graph → `#7CB97A` (green)
|
||||
- orchestrator → `#B08ED6` (soft purple)
|
||||
- agent → `#B8B8B8` (neutral)
|
||||
- researcher → `#D4A574` (amber)
|
||||
|
||||
**Liveness Colors:**
|
||||
- active → `#7CB97A` (green, pulsing)
|
||||
- stale → `#D4A574` (amber)
|
||||
- evicted → `#C97A7A` (muted rose)
|
||||
- idle → `#888888` (muted)
|
||||
|
||||
### Radii
|
||||
```css
|
||||
--radius-sm: 0.375rem /* 6px */
|
||||
--radius-card: 0.625rem /* 10px */
|
||||
--radius-modal: 1rem /* 16px */
|
||||
--radius-pill: 9999px
|
||||
```
|
||||
|
||||
### Shadows
|
||||
```css
|
||||
--shadow-sm: 0 1px 2px rgba(0,0,0,0.1)
|
||||
--shadow-md: 0 4px 12px rgba(0,0,0,0.15)
|
||||
```
|
||||
|
||||
### Typography
|
||||
- Font: system sans-serif (Inter if available)
|
||||
- H1: 2rem/700, H2: 1.5rem/600, H3: 1.125rem/600
|
||||
- Body: 0.875rem/400, Small: 0.75rem/400, Tiny: 0.6875rem/500
|
||||
- Line-height: headings 1.2, body 1.5
|
||||
|
||||
### Spacing
|
||||
- Base: 0.25rem (4px)
|
||||
- Card padding: 1rem-1.25rem
|
||||
- Gaps: 1rem
|
||||
- Section gaps: 2rem-2.5rem
|
||||
|
||||
### Icons & Transitions
|
||||
- Icons: Lucide React, 1.5-2px stroke, 1rem-1.5rem size
|
||||
- Transitions: 150-200ms ease-out for all hover/focus
|
||||
|
||||
---
|
||||
|
||||
## Component Anatomy
|
||||
|
||||
### Social Feed Card
|
||||
|
||||
```
|
||||
┌─────────────────────────────────────┐
|
||||
│ [⊕] (top-R)│ expand icon
|
||||
│ │
|
||||
│ bb-buff.1.1 │ task ID (tiny, teal)
|
||||
│ Fix login bug on mobile │ title (bold, white)
|
||||
│ │
|
||||
│ UNLOCKS: │ blocked-by (ROSE tint)
|
||||
│ ● #123 Blocker task │
|
||||
│ │
|
||||
│ BLOCKS: │ downstream (AMBER tint)
|
||||
│ ● #234 Dependent task │
|
||||
│ │
|
||||
│ "Found the issue in the auth..." │ latest message (muted)
|
||||
│ │
|
||||
│ [●a-1] [●a-2] │ agent avatars (PROMINENT)
|
||||
│ [≡] [◊] [≋]│ view-jump icons
|
||||
└─────────────────────────────────────┘
|
||||
```
|
||||
|
||||
**Card Specs:**
|
||||
- Background: `#363636`
|
||||
- Border: 1px status-colored (teal/green/amber/muted)
|
||||
- Border-radius: 10px
|
||||
- Status dot on card matches status mapping
|
||||
- Agent avatars have **role-colored left border**
|
||||
- Blocks/unlocks have tinted backgrounds (rose #E57373/10%, amber #D4A574/10%)
|
||||
|
||||
**Blocks/Unlocks Pattern (reuse from task-card-grid.tsx):**
|
||||
```tsx
|
||||
// Container
|
||||
rounded-lg p-2 border border-white/5
|
||||
|
||||
// "Unlocks" header (rose tint)
|
||||
text-[9px] font-bold uppercase tracking-widest text-rose-400/80
|
||||
bg-rose-500/10 // background tint
|
||||
|
||||
// "Blocks" header (amber tint)
|
||||
text-[9px] font-bold uppercase tracking-widest text-amber-400/80
|
||||
bg-amber-500/10 // background tint
|
||||
|
||||
// Individual item
|
||||
rounded border border-white/5 bg-white/5 px-2.5 py-2
|
||||
hover:border-sky-400/30 hover:bg-white/10 transition-colors
|
||||
```
|
||||
|
||||
### ZFC Agent State Visuals
|
||||
|
||||
| State | Visual |
|
||||
|-------|--------|
|
||||
| idle | `#888888` static dot |
|
||||
| spawning | `#5BA8A0` pulsing dot |
|
||||
| running | `#7CB97A` animated dot |
|
||||
| working | `#7CB97A` pulsing glow |
|
||||
| stuck | `#D4A574` attention dot (needs help!) |
|
||||
| done | `#7CB97A` check |
|
||||
| stopped | `#888888` no animation |
|
||||
| dead | `#C97A7A` warning |
|
||||
|
||||
### Agent Card (Right Panel)
|
||||
|
||||
```
|
||||
┌──────────────────────┐
|
||||
│ [●avatar] agent-1 │ role-colored left border
|
||||
│ role: ui │ role label
|
||||
│ ● working · 2m ago │ ZFC state dot + age
|
||||
│ Task: buff.1.1 │ current task
|
||||
│ [≡] [◊] [≋] [💬] │ view-jump + message
|
||||
└──────────────────────┘
|
||||
```
|
||||
|
||||
### Swimlane Header
|
||||
- Swarm name + computed counts: "3/8 done · 2 active · 1 ready · 1 blocked"
|
||||
- Agent roster with ZFC state labels
|
||||
- Collapsible
|
||||
|
||||
---
|
||||
|
||||
## Layout Architecture
|
||||
|
||||
### Shell Structure (CSS Grid)
|
||||
|
||||
```
|
||||
┌──────────────────────────────────────────────────────────────────┐
|
||||
│ TOP BAR (fixed, 3rem) │
|
||||
│ ≡ [Swimlanes|Graph|Timeline|Social] ◢ │
|
||||
├──────────┬──────────────────────────────────┬────────────────────┤
|
||||
│ LEFT │ MIDDLE │ RIGHT │
|
||||
│ 13.75rem │ flex-1 │ 17.5rem │
|
||||
│ │ │ │
|
||||
│ Channel │ View content (swaps on tab) │ Agents (~40%) │
|
||||
│ tree │ │ ────────────────── │
|
||||
│ │ │ Activity (~60%) │
|
||||
└──────────┴──────────────────────────────────┴────────────────────┘
|
||||
```
|
||||
|
||||
**Grid:** `grid-template-columns: 13.75rem 1fr 17.5rem`
|
||||
|
||||
### Detail Strip Behavior
|
||||
|
||||
**Desktop (≥1024px):**
|
||||
- Grid splits: cards (~45%) | detail strip (~55%)
|
||||
- Strip slides in below grid when card selected
|
||||
- Cards remain visible above
|
||||
|
||||
**Mobile (<768px):**
|
||||
- Full-screen overlay (z-index above bottom tabs)
|
||||
- Required: virtual keyboard takes 40% of screen
|
||||
- Split view would leave 0px for conversation
|
||||
|
||||
### Responsive Behavior
|
||||
|
||||
| Size | Left | Middle | Right | Detail Strip |
|
||||
|------|------|--------|-------|--------------|
|
||||
| Desktop (≥1024px) | 13.75rem fixed | flex-1 | 17.5rem fixed | Below grid |
|
||||
| Tablet (768-1024px) | Overlay | flex-1 | Overlay | Slide-over |
|
||||
| Mobile (<768px) | Overlay | flex-1 | Hidden | Full-screen |
|
||||
|
||||
---
|
||||
|
||||
## Anti-Patterns (Forbidden)
|
||||
|
||||
- NO glass-morphism / backdrop-blur effects
|
||||
- NO arbitrary Tailwind color values (use tokens)
|
||||
- NO agent-unaware cards (every card shows agents)
|
||||
- NO page-per-view routing (use client tabs)
|
||||
- NO localStorage for view state (use URL)
|
||||
- NO direct JSONL writes (use bd CLI)
|
||||
|
||||
---
|
||||
|
||||
## Recommended Bead Structure
|
||||
|
||||
### Phase 0: Design Foundation
|
||||
**Goal:** Tokens + Primitives only. No views.
|
||||
|
||||
**bb-ui2.1a** - Token System Update
|
||||
- Update tokens.css with complete spec above
|
||||
- Ensure all status/liveness/role colors defined
|
||||
- Migrate away from Aero Chrome gradients
|
||||
|
||||
**bb-ui2.2a** - Card Primitive with Blocks/Unlocks
|
||||
- Build reusable Card component
|
||||
- Implement blocks/unlocks section pattern (reuse task-card-grid.tsx logic)
|
||||
- Status-colored borders
|
||||
- Soft gradient backgrounds (amber/teal tints, not harsh Aero Chrome)
|
||||
|
||||
**bb-ui2.3a** - Agent Avatar Primitive
|
||||
- Avatar with role-colored ring
|
||||
- ZFC state indicator (dot/pulse/glow)
|
||||
- Size variants (sm, md, lg)
|
||||
|
||||
**bb-ui2.4a** - Status Utilities Update
|
||||
- Rewrite status-utils.tsx for new tokens
|
||||
- Status badge component with pill + dot
|
||||
- Liveness indicator component
|
||||
|
||||
### Phase 1: Layout Polish
|
||||
**Goal:** Fix current layout issues, preserve structure
|
||||
|
||||
**bb-ui2.22** - Detail Strip Positioning Fix
|
||||
- Move from side drawer to below-grid (desktop)
|
||||
- Full-screen overlay (mobile)
|
||||
- Preserve URL state behavior
|
||||
- Thread content actually shows selected bead data
|
||||
|
||||
**bb-ui2.23** - Activity Panel Polish
|
||||
- Split right panel: Agents (40%) + Activity (60%)
|
||||
- Agent cards with ZFC states
|
||||
- Context-aware activity filtering
|
||||
|
||||
**bb-ui2.24** - Mobile Responsive Polish
|
||||
- Bottom tab bar
|
||||
- Panel overlays
|
||||
- Touch-friendly targets
|
||||
|
||||
### Phase 2: Card Design Implementation
|
||||
**Goal:** Implement complete card anatomy
|
||||
|
||||
**bb-ui2.25** - Social Feed Card Redesign
|
||||
- Full card anatomy from spec
|
||||
- Blocks/unlocks with rose/amber tints
|
||||
- Prominent agent avatars
|
||||
- View-jump icons
|
||||
- Expand icon → full-page popup
|
||||
|
||||
**bb-ui2.26** - Swimlane Card Redesign
|
||||
- Agent-first layout
|
||||
- ZFC state prominent
|
||||
- Status-colored border
|
||||
- Drag-drop preserved
|
||||
|
||||
**bb-ui2.27** - Graph Node Redesign
|
||||
- New design tokens
|
||||
- Agent avatars on nodes
|
||||
- Selection syncs with store
|
||||
|
||||
### Phase 3: Cross-Cutting Polish
|
||||
**Goal:** Deep links, mobile, final gates
|
||||
|
||||
**bb-ui2.28** - Deep Link Verification
|
||||
- All URL patterns work
|
||||
- Browser back/forward
|
||||
- Shareable URLs
|
||||
|
||||
**bb-ui2.29** - Screenshot Evidence
|
||||
- All breakpoints
|
||||
- All views
|
||||
- Mobile + desktop
|
||||
|
||||
**bb-ui2.30** - Final Gates
|
||||
- typecheck, lint, test
|
||||
- Close epic
|
||||
|
||||
---
|
||||
|
||||
## Verification Strategy
|
||||
|
||||
After each bead:
|
||||
```bash
|
||||
npm run typecheck
|
||||
npm run lint
|
||||
npm run test
|
||||
```
|
||||
|
||||
Visual verification:
|
||||
- Screenshots at 390px, 768px, 1440px
|
||||
- Compare against design spec
|
||||
- Agent avatars visible on all cards
|
||||
- Blocks/unlocks sections tinted correctly
|
||||
|
||||
---
|
||||
|
||||
*End of PRD v2.0 - Ready for Implementation*
|
||||
|
|
|
|||
|
|
@ -1,171 +1,171 @@
|
|||
# Swarm View Remake - Product Requirements Document (PRD)
|
||||
|
||||
## Overview
|
||||
The goal is to completely remake the Beadboard "Swarm" view (`/view=swarm`) into a powerful, command-center style workspace. The current flat grid of mission cards will be replaced with a deep, context-aware interface that integrates with the Gastown/Beads orchestration model, introducing the concepts of Agent Archetypes and Swarm Templates.
|
||||
|
||||
This document serves as the comprehensive technical specification for implementation.
|
||||
|
||||
---
|
||||
|
||||
## 1. Core Concepts & Data Models
|
||||
|
||||
### 1.1 Agent Archetypes
|
||||
Archetypes define specialized roles that worker agents (Polecats) can adopt.
|
||||
|
||||
* **Storage Path:** `.beads/archetypes/*.json` (Git-tracked alongside the project).
|
||||
* **Seeding:** The application must check for the existence of this directory on startup (or via a specific API route). If empty, it must create the directory and write default archetypes (e.g., `architect.json`, `reviewer.json`, `implementer.json`).
|
||||
* **Data Interface (`src/lib/types-swarm.ts`):**
|
||||
```typescript
|
||||
export interface AgentArchetype {
|
||||
id: string; // The filename without .json (e.g., 'architect')
|
||||
name: string; // Display name (e.g., 'Software Architect')
|
||||
description: string;
|
||||
systemPrompt: string; // The core behavioral instructions
|
||||
capabilities: string[]; // e.g., ['planning', 'code_review']
|
||||
color: string; // e.g., 'primary', 'destructive', 'warn', etc.
|
||||
createdAt: string; // ISO timestamp
|
||||
updatedAt: string; // ISO timestamp
|
||||
isBuiltIn: boolean; // True if seeded by default, false if user-created
|
||||
}
|
||||
```
|
||||
|
||||
### 1.2 Swarm Templates
|
||||
Templates define mission blueprints—a preset team composition and standard workflow.
|
||||
|
||||
* **Storage Path:** `.beads/templates/*.json`.
|
||||
* **Seeding:** Similar to archetypes, provide robust defaults (e.g., `feature-sprint.json`, `bug-blitz.json`).
|
||||
* **Data Interface (`src/lib/types-swarm.ts`):**
|
||||
```typescript
|
||||
export interface SwarmTemplate {
|
||||
id: string; // The filename without .json
|
||||
name: string; // Display name
|
||||
description: string;
|
||||
team: {
|
||||
archetypeId: string; // Must match an AgentArchetype.id
|
||||
count: number;
|
||||
}[];
|
||||
protoFormula?: string; // Optional: Maps to a `bd` formula name (e.g., 'release')
|
||||
createdAt: string;
|
||||
updatedAt: string;
|
||||
isBuiltIn: boolean;
|
||||
}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 2. API Contracts & Backend Architecture
|
||||
|
||||
The UI needs a robust Next.js API layer to manage these new files and interface with the CLI. All routes should be under `src/app/api/swarm/`.
|
||||
|
||||
### 2.1 Archetypes API (`/api/swarm/archetypes`)
|
||||
* **GET:** Returns `AgentArchetype[]`. Reads all `.json` files from `.beads/archetypes/`.
|
||||
* **POST:** Creates a new archetype. Validates payload, writes to `.beads/archetypes/{id}.json`.
|
||||
* **PUT /:id:** Updates an existing archetype.
|
||||
* **DELETE /:id:** Deletes an archetype (prevent deletion if `isBuiltIn` is true).
|
||||
|
||||
### 2.2 Templates API (`/api/swarm/templates`)
|
||||
* **GET:** Returns `SwarmTemplate[]`. Reads from `.beads/templates/`.
|
||||
* **POST, PUT, DELETE:** Standard CRUD mirroring Archetypes.
|
||||
|
||||
### 2.3 Orchestration API (`/api/swarm/orchestration`)
|
||||
* **POST `/launch`:**
|
||||
* **Payload:** `{ templateId: string, missionName: string, projectRoot: string }`
|
||||
* **Action:** Reads the template. If `protoFormula` exists, executes `bd mol pour <protoFormula> --title <missionName>`. If no formula, executes `bd create epic <missionName>`. Then executes `gt sling` or equivalent to assign the specific roster to the new Epic.
|
||||
* **Response:** The new Epic ID to immediately select in the UI.
|
||||
|
||||
---
|
||||
|
||||
## 3. Frontend Architecture & Component Structure
|
||||
|
||||
The current `src/components/swarm/swarm-page.tsx` will be completely replaced. The new architecture pushes state down into specialized components.
|
||||
|
||||
### 3.1 Shell Integration (`src/components/shared/unified-shell.tsx`)
|
||||
The `UnifiedShell` must dynamically alter its layout based on the active view.
|
||||
|
||||
* **When `view === 'swarm'`:**
|
||||
* **Left Panel:** Do NOT render the standard Epic Tree. Render `<SwarmMissionPicker />`.
|
||||
* **Middle Column:** Render `<SwarmWorkspace />`.
|
||||
* **Right Panel:** Remain as the `<ActivityPanel />` (Agent pool monitor).
|
||||
|
||||
### 3.2 The Swarm Workspace (`src/components/swarm/swarm-workspace.tsx`)
|
||||
The main container for the middle column. Manages the active sub-tab state.
|
||||
|
||||
```tsx
|
||||
// State: activeTab: 'operations' | 'archetypes' | 'templates'
|
||||
<div className="swarm-workspace">
|
||||
<SwarmWorkspaceNav activeTab={activeTab} onTabChange={setTab} />
|
||||
|
||||
{activeTab === 'operations' && <SwarmOperationsmissionId={selectedMissionId} />}
|
||||
{activeTab === 'archetypes' && <ArchetypesArmory />}
|
||||
{activeTab === 'templates' && <TemplatesManager />}
|
||||
</div>
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 4. UI/UX Details by Sub-Tab
|
||||
|
||||
### 4.1 Left Panel: `<SwarmMissionPicker />`
|
||||
A dense, scannable list replacing the left panel.
|
||||
* Fetches epics (like the current `useMissionList` hook).
|
||||
* **Row Design:**
|
||||
* `[Health Dot] [Mission Title] (ID)`
|
||||
* A micro-progress bar underneath the title.
|
||||
* **Interaction:** Clicking sets the `swarmId` URL param and automatically switches the `SwarmWorkspace` to the 'operations' tab.
|
||||
|
||||
### 4.2 Tab 1: `<SwarmOperations />` (The Operations Command Center)
|
||||
This view only renders if a mission (Epic) is selected. It completely replaces the redundant Graph view with a focused, control-oriented dashboard for agent orchestration.
|
||||
|
||||
* **Header Section:**
|
||||
* Mission Title, Epic ID, and overall health status.
|
||||
* **Action Strip:** Buttons for "Summon Polecats" (assign agents based on a template), "Halt Swarm", and "Run Debrief".
|
||||
* **Convoy Stepper:** The visual orchestration pipeline (Planning -> Deployment -> Execution -> Debrief).
|
||||
* **The Telemetry Grid (Hybrid Layout):**
|
||||
* **Top/Left Pane (Specialized Agent DAG):** Unlike the generic global graph, this graph specifically visualizes *who* is doing *what*. Nodes should emphasize Agent Avatars and archetype colors. Edges should represent the flow of work between agents (e.g., Coder -> Reviewer) rather than just raw task dependencies.
|
||||
* **Bottom/Right Pane (Metrics & Attention):**
|
||||
* **Priority Attention (What is blocked?):** A highly focused feed of *only* the `blocked` beads or beads that require Human-In-The-Loop (HITL) intervention for this specific mission.
|
||||
* **Mission Roster:** A quick summary of active agents.
|
||||
|
||||
### 4.3 Tab 2: `<ArchetypesArmory />`
|
||||
* **Layout:** CSS Grid of archetype cards.
|
||||
* **Card Design:** Shows Name, Color badge, Capabilities tags, and truncated description.
|
||||
* **Interaction:**
|
||||
* Cards are highly interactive. Clicking a card opens a central popup (reusing the app's existing Dialog/Popup pattern) to edit the metadata.
|
||||
* Includes a focused text area to edit the raw `systemPrompt`.
|
||||
* A primary "Create New Archetype" button exists at the top.
|
||||
|
||||
### 4.4 Tab 3: `<TemplatesManager />`
|
||||
* **Layout:** List or Grid view of templates.
|
||||
* **Interaction:**
|
||||
* Cards are highly interactive. Clicking a card opens a central `<TemplateEditor />` popup.
|
||||
* **Key UI Feature:** An intuitive interface to build the `team` array (e.g., click "Add Role", select "Architect" from the Archetypes list, set count to "1").
|
||||
* A primary "Create New Template" button exists at the top.
|
||||
|
||||
---
|
||||
|
||||
## 5. Engine Integration & Visual Hooks
|
||||
|
||||
Raw terminal panes are rejected. Orchestration must feel native to the React application.
|
||||
|
||||
### 5.1 The Convoy Stepper (`<ConvoyOrchestrationStepper />`)
|
||||
When `<LaunchSwarmDialog />` is submitted, a prominent overlay or banner appears in the Operations view:
|
||||
|
||||
* **Phase 1: Planning.** (Spinning) -> API calls `bd mol pour` -> (Check)
|
||||
* **Phase 2: Graph Generation.** (Spinning) -> UI polls API for new beads -> (Check)
|
||||
* **Phase 3: Deployment.** (Spinning) -> API calls `gt sling` -> (Check)
|
||||
* The stepper fades out after 3 seconds of full completion, revealing the live DAG.
|
||||
|
||||
### 5.2 Responsive Graph Expansion
|
||||
The Graph view in the Operations tab must smoothly handle rapid influxes of nodes (which happens when a template is poured). The physics simulation (if applicable) or layout engine should be robust enough to handle ~20-50 nodes appearing simultaneously without throwing errors or causing heavy layout thrashing.
|
||||
|
||||
---
|
||||
|
||||
## 6. Implementation Phasing Strategy
|
||||
|
||||
To avoid massive, monolithic PRs, implementation should follow this order:
|
||||
|
||||
1. **Phase 1: Data Layer & API.** Implement `src/lib/types-swarm.ts`, the seed logic, and the CRUD API routes for Archetypes and Templates.
|
||||
2. **Phase 2: Shell Routing & Sub-tabs.** Update `UnifiedShell` to intercept the Swarm view, implement the `SwarmMissionPicker` for the left panel, and scaffold the empty 3 sub-tabs.
|
||||
3. **Phase 3: Armory & Templates UI.** Build out the CRUD interfaces for Archetypes and Templates.
|
||||
4. **Phase 4: The Operations Dashboard.** Build the complex detail view, integrating the existing graph components and agent roster.
|
||||
5. **Phase 5: Orchestration (The glue).** Hook up the "Launch" button to the new templates, implement the `ConvoyStepper`, and wire the API to `bd` and `gt`.
|
||||
# Swarm View Remake - Product Requirements Document (PRD)
|
||||
|
||||
## Overview
|
||||
The goal is to completely remake the Beadboard "Swarm" view (`/view=swarm`) into a powerful, command-center style workspace. The current flat grid of mission cards will be replaced with a deep, context-aware interface that integrates with the Gastown/Beads orchestration model, introducing the concepts of Agent Archetypes and Swarm Templates.
|
||||
|
||||
This document serves as the comprehensive technical specification for implementation.
|
||||
|
||||
---
|
||||
|
||||
## 1. Core Concepts & Data Models
|
||||
|
||||
### 1.1 Agent Archetypes
|
||||
Archetypes define specialized roles that worker agents (Polecats) can adopt.
|
||||
|
||||
* **Storage Path:** `.beads/archetypes/*.json` (Git-tracked alongside the project).
|
||||
* **Seeding:** The application must check for the existence of this directory on startup (or via a specific API route). If empty, it must create the directory and write default archetypes (e.g., `architect.json`, `reviewer.json`, `implementer.json`).
|
||||
* **Data Interface (`src/lib/types-swarm.ts`):**
|
||||
```typescript
|
||||
export interface AgentArchetype {
|
||||
id: string; // The filename without .json (e.g., 'architect')
|
||||
name: string; // Display name (e.g., 'Software Architect')
|
||||
description: string;
|
||||
systemPrompt: string; // The core behavioral instructions
|
||||
capabilities: string[]; // e.g., ['planning', 'code_review']
|
||||
color: string; // e.g., 'primary', 'destructive', 'warn', etc.
|
||||
createdAt: string; // ISO timestamp
|
||||
updatedAt: string; // ISO timestamp
|
||||
isBuiltIn: boolean; // True if seeded by default, false if user-created
|
||||
}
|
||||
```
|
||||
|
||||
### 1.2 Swarm Templates
|
||||
Templates define mission blueprints—a preset team composition and standard workflow.
|
||||
|
||||
* **Storage Path:** `.beads/templates/*.json`.
|
||||
* **Seeding:** Similar to archetypes, provide robust defaults (e.g., `feature-sprint.json`, `bug-blitz.json`).
|
||||
* **Data Interface (`src/lib/types-swarm.ts`):**
|
||||
```typescript
|
||||
export interface SwarmTemplate {
|
||||
id: string; // The filename without .json
|
||||
name: string; // Display name
|
||||
description: string;
|
||||
team: {
|
||||
archetypeId: string; // Must match an AgentArchetype.id
|
||||
count: number;
|
||||
}[];
|
||||
protoFormula?: string; // Optional: Maps to a `bd` formula name (e.g., 'release')
|
||||
createdAt: string;
|
||||
updatedAt: string;
|
||||
isBuiltIn: boolean;
|
||||
}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 2. API Contracts & Backend Architecture
|
||||
|
||||
The UI needs a robust Next.js API layer to manage these new files and interface with the CLI. All routes should be under `src/app/api/swarm/`.
|
||||
|
||||
### 2.1 Archetypes API (`/api/swarm/archetypes`)
|
||||
* **GET:** Returns `AgentArchetype[]`. Reads all `.json` files from `.beads/archetypes/`.
|
||||
* **POST:** Creates a new archetype. Validates payload, writes to `.beads/archetypes/{id}.json`.
|
||||
* **PUT /:id:** Updates an existing archetype.
|
||||
* **DELETE /:id:** Deletes an archetype (prevent deletion if `isBuiltIn` is true).
|
||||
|
||||
### 2.2 Templates API (`/api/swarm/templates`)
|
||||
* **GET:** Returns `SwarmTemplate[]`. Reads from `.beads/templates/`.
|
||||
* **POST, PUT, DELETE:** Standard CRUD mirroring Archetypes.
|
||||
|
||||
### 2.3 Orchestration API (`/api/swarm/orchestration`)
|
||||
* **POST `/launch`:**
|
||||
* **Payload:** `{ templateId: string, missionName: string, projectRoot: string }`
|
||||
* **Action:** Reads the template. If `protoFormula` exists, executes `bd mol pour <protoFormula> --title <missionName>`. If no formula, executes `bd create epic <missionName>`. Then executes `gt sling` or equivalent to assign the specific roster to the new Epic.
|
||||
* **Response:** The new Epic ID to immediately select in the UI.
|
||||
|
||||
---
|
||||
|
||||
## 3. Frontend Architecture & Component Structure
|
||||
|
||||
The current `src/components/swarm/swarm-page.tsx` will be completely replaced. The new architecture pushes state down into specialized components.
|
||||
|
||||
### 3.1 Shell Integration (`src/components/shared/unified-shell.tsx`)
|
||||
The `UnifiedShell` must dynamically alter its layout based on the active view.
|
||||
|
||||
* **When `view === 'swarm'`:**
|
||||
* **Left Panel:** Do NOT render the standard Epic Tree. Render `<SwarmMissionPicker />`.
|
||||
* **Middle Column:** Render `<SwarmWorkspace />`.
|
||||
* **Right Panel:** Remain as the `<ActivityPanel />` (Agent pool monitor).
|
||||
|
||||
### 3.2 The Swarm Workspace (`src/components/swarm/swarm-workspace.tsx`)
|
||||
The main container for the middle column. Manages the active sub-tab state.
|
||||
|
||||
```tsx
|
||||
// State: activeTab: 'operations' | 'archetypes' | 'templates'
|
||||
<div className="swarm-workspace">
|
||||
<SwarmWorkspaceNav activeTab={activeTab} onTabChange={setTab} />
|
||||
|
||||
{activeTab === 'operations' && <SwarmOperationsmissionId={selectedMissionId} />}
|
||||
{activeTab === 'archetypes' && <ArchetypesArmory />}
|
||||
{activeTab === 'templates' && <TemplatesManager />}
|
||||
</div>
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 4. UI/UX Details by Sub-Tab
|
||||
|
||||
### 4.1 Left Panel: `<SwarmMissionPicker />`
|
||||
A dense, scannable list replacing the left panel.
|
||||
* Fetches epics (like the current `useMissionList` hook).
|
||||
* **Row Design:**
|
||||
* `[Health Dot] [Mission Title] (ID)`
|
||||
* A micro-progress bar underneath the title.
|
||||
* **Interaction:** Clicking sets the `swarmId` URL param and automatically switches the `SwarmWorkspace` to the 'operations' tab.
|
||||
|
||||
### 4.2 Tab 1: `<SwarmOperations />` (The Operations Command Center)
|
||||
This view only renders if a mission (Epic) is selected. It completely replaces the redundant Graph view with a focused, control-oriented dashboard for agent orchestration.
|
||||
|
||||
* **Header Section:**
|
||||
* Mission Title, Epic ID, and overall health status.
|
||||
* **Action Strip:** Buttons for "Summon Polecats" (assign agents based on a template), "Halt Swarm", and "Run Debrief".
|
||||
* **Convoy Stepper:** The visual orchestration pipeline (Planning -> Deployment -> Execution -> Debrief).
|
||||
* **The Telemetry Grid (Hybrid Layout):**
|
||||
* **Top/Left Pane (Specialized Agent DAG):** Unlike the generic global graph, this graph specifically visualizes *who* is doing *what*. Nodes should emphasize Agent Avatars and archetype colors. Edges should represent the flow of work between agents (e.g., Coder -> Reviewer) rather than just raw task dependencies.
|
||||
* **Bottom/Right Pane (Metrics & Attention):**
|
||||
* **Priority Attention (What is blocked?):** A highly focused feed of *only* the `blocked` beads or beads that require Human-In-The-Loop (HITL) intervention for this specific mission.
|
||||
* **Mission Roster:** A quick summary of active agents.
|
||||
|
||||
### 4.3 Tab 2: `<ArchetypesArmory />`
|
||||
* **Layout:** CSS Grid of archetype cards.
|
||||
* **Card Design:** Shows Name, Color badge, Capabilities tags, and truncated description.
|
||||
* **Interaction:**
|
||||
* Cards are highly interactive. Clicking a card opens a central popup (reusing the app's existing Dialog/Popup pattern) to edit the metadata.
|
||||
* Includes a focused text area to edit the raw `systemPrompt`.
|
||||
* A primary "Create New Archetype" button exists at the top.
|
||||
|
||||
### 4.4 Tab 3: `<TemplatesManager />`
|
||||
* **Layout:** List or Grid view of templates.
|
||||
* **Interaction:**
|
||||
* Cards are highly interactive. Clicking a card opens a central `<TemplateEditor />` popup.
|
||||
* **Key UI Feature:** An intuitive interface to build the `team` array (e.g., click "Add Role", select "Architect" from the Archetypes list, set count to "1").
|
||||
* A primary "Create New Template" button exists at the top.
|
||||
|
||||
---
|
||||
|
||||
## 5. Engine Integration & Visual Hooks
|
||||
|
||||
Raw terminal panes are rejected. Orchestration must feel native to the React application.
|
||||
|
||||
### 5.1 The Convoy Stepper (`<ConvoyOrchestrationStepper />`)
|
||||
When `<LaunchSwarmDialog />` is submitted, a prominent overlay or banner appears in the Operations view:
|
||||
|
||||
* **Phase 1: Planning.** (Spinning) -> API calls `bd mol pour` -> (Check)
|
||||
* **Phase 2: Graph Generation.** (Spinning) -> UI polls API for new beads -> (Check)
|
||||
* **Phase 3: Deployment.** (Spinning) -> API calls `gt sling` -> (Check)
|
||||
* The stepper fades out after 3 seconds of full completion, revealing the live DAG.
|
||||
|
||||
### 5.2 Responsive Graph Expansion
|
||||
The Graph view in the Operations tab must smoothly handle rapid influxes of nodes (which happens when a template is poured). The physics simulation (if applicable) or layout engine should be robust enough to handle ~20-50 nodes appearing simultaneously without throwing errors or causing heavy layout thrashing.
|
||||
|
||||
---
|
||||
|
||||
## 6. Implementation Phasing Strategy
|
||||
|
||||
To avoid massive, monolithic PRs, implementation should follow this order:
|
||||
|
||||
1. **Phase 1: Data Layer & API.** Implement `src/lib/types-swarm.ts`, the seed logic, and the CRUD API routes for Archetypes and Templates.
|
||||
2. **Phase 2: Shell Routing & Sub-tabs.** Update `UnifiedShell` to intercept the Swarm view, implement the `SwarmMissionPicker` for the left panel, and scaffold the empty 3 sub-tabs.
|
||||
3. **Phase 3: Armory & Templates UI.** Build out the CRUD interfaces for Archetypes and Templates.
|
||||
4. **Phase 4: The Operations Dashboard.** Build the complex detail view, integrating the existing graph components and agent roster.
|
||||
5. **Phase 5: Orchestration (The glue).** Hook up the "Launch" button to the new templates, implement the `ConvoyStepper`, and wire the API to `bd` and `gt`.
|
||||
|
|
|
|||
|
|
@ -1,49 +1,49 @@
|
|||
# DAG Views & Command Center UX Overhaul
|
||||
|
||||
## The Problem
|
||||
The current `/grid` and `/swarm` views are fragmented. The left sidebar changes shape and color depending on the mode, causing jarring context switches. The Swarm DAG needs animation enhancements, the Grid view needs clarity, and the Right Panel gets cut off and is filled with noisy, irrelevant data (e.g., dead agents from days ago).
|
||||
|
||||
## The Goal
|
||||
Create a unified "Mission Control" experience designed specifically for a single Commander observing and managing AI agents. Eliminate context switching while separating the noise of real-time execution from the quiet of architectural planning.
|
||||
|
||||
## The Solution: Macro vs. Micro Architecture
|
||||
|
||||
Instead of arbitrary "Grid" and "Swarm" routing modes, we move to a **Depth-Based Context** model.
|
||||
|
||||
### 1. The Macro View (Planning / The Grid)
|
||||
**Trigger:** Looking at the entire workspace or multiple epics.
|
||||
- **The DAG:** Structural and quiet. Shows task dependencies and static statuses (Ready, Blocked, Done). No noisy agent animations or live data flows.
|
||||
- **Left Panel:** The unified Task/Epic tree. Clean, consistent UI.
|
||||
- **Right Panel (Global Events):** A high-level timeline of events (e.g., "Agent X completed Task Y", "Task Z is blocked"), essentially a git-log of the workspace.
|
||||
|
||||
### 2. The Micro View (Execution / The Swarm)
|
||||
**Trigger:** Selecting a specific Epic or an active Task. The view zooms in to focus only on localized context.
|
||||
- **The DAG:** Comes alive. You only see the tasks actively being worked on and their immediate neighbors. Nodes pulse to indicate agent activity, and edges show animated data-flow passing between tasks/agents.
|
||||
- **Left Panel:** Remains the unified Task/Epic tree, but highlights the active epic and places "Active Agent" indicator badges next to tasks currently in progress.
|
||||
- **Right Panel (The Command Feed):** Splits into a stacked or tabbed view optimized for live operations:
|
||||
- **Active Squad Roster:** Only lists agents assigned to *this specific Epic context*. Dead agents from previous sessions are completely hidden. Shows current token usage and active task assignments.
|
||||
- **Live Telemetry (The Swarm Activity Feed):** A highly readable streaming feed of what the agents are thinking and doing *right now* ("Agent X evaluating `lib/utils.ts`", "Agent Y blocked on API key"). This replaces the current messy telemetry grid into a focused, scrolling terminal-like feed on the right.
|
||||
|
||||
## Technical Execution Plan
|
||||
|
||||
### 1. Left Panel Unification
|
||||
- Remove the `SwarmMissionPicker` override.
|
||||
- Update `unified-shell.tsx` to always render `<LeftPanel />`.
|
||||
- Enhance `<LeftPanel />` to display active agent indicators based on live telemetry data.
|
||||
|
||||
### 2. Right Panel Fixes & Contextual Rendering
|
||||
- Fix the CSS grid width causing the Right Panel to be cut off (`rightPanelWidth` adjustments in `unified-shell.tsx`).
|
||||
- Introduce `<ContextualRightPanel />` that reads the URL state (`epicId` / `taskId` vs `null`).
|
||||
- Component swap:
|
||||
- No Epic Selected -> `<GlobalActivityFeed />`
|
||||
- Epic/Task Selected -> `<SwarmCommandFeed />` (Roster + Telemetry)
|
||||
|
||||
### 3. DAG Component Merging
|
||||
- Merge `GraphView` and `SwarmWorkspace` core logic into a single `<SmartDag />` component.
|
||||
- The `<SmartDag />` will read the `epicId` context to determine its zoom level and animation states.
|
||||
- Introduce framer-motion (or existing animation libraries) for data flow and node pulsing.
|
||||
|
||||
### 4. Overhauling the Swarm Activity Feed & Roster
|
||||
- **Contextual Agent Roster:** Instead of pulling all agents globally (like `ActivityPanel` currently does), we extract the active roster logic from `TelemetryGrid` to only show agents actively assigned to `in_progress` tasks within the currently selected `epicId`.
|
||||
- **Streaming Telemetry Feed:** We reuse the `/api/events` SSE connection from `ActivityPanel`, but we filter the incoming events `beadId` to match the children of the current `epicId`. We format this feed as a terminal-like streaming log with concise, color-coded badges indicating what the agents are currently doing.
|
||||
- **Cleanup the Graveyard:** Dead agents and old task logs will be entirely stripped from this contextual right panel, ensuring it remains a focused "Command Feed" of live operations.
|
||||
# DAG Views & Command Center UX Overhaul
|
||||
|
||||
## The Problem
|
||||
The current `/grid` and `/swarm` views are fragmented. The left sidebar changes shape and color depending on the mode, causing jarring context switches. The Swarm DAG needs animation enhancements, the Grid view needs clarity, and the Right Panel gets cut off and is filled with noisy, irrelevant data (e.g., dead agents from days ago).
|
||||
|
||||
## The Goal
|
||||
Create a unified "Mission Control" experience designed specifically for a single Commander observing and managing AI agents. Eliminate context switching while separating the noise of real-time execution from the quiet of architectural planning.
|
||||
|
||||
## The Solution: Macro vs. Micro Architecture
|
||||
|
||||
Instead of arbitrary "Grid" and "Swarm" routing modes, we move to a **Depth-Based Context** model.
|
||||
|
||||
### 1. The Macro View (Planning / The Grid)
|
||||
**Trigger:** Looking at the entire workspace or multiple epics.
|
||||
- **The DAG:** Structural and quiet. Shows task dependencies and static statuses (Ready, Blocked, Done). No noisy agent animations or live data flows.
|
||||
- **Left Panel:** The unified Task/Epic tree. Clean, consistent UI.
|
||||
- **Right Panel (Global Events):** A high-level timeline of events (e.g., "Agent X completed Task Y", "Task Z is blocked"), essentially a git-log of the workspace.
|
||||
|
||||
### 2. The Micro View (Execution / The Swarm)
|
||||
**Trigger:** Selecting a specific Epic or an active Task. The view zooms in to focus only on localized context.
|
||||
- **The DAG:** Comes alive. You only see the tasks actively being worked on and their immediate neighbors. Nodes pulse to indicate agent activity, and edges show animated data-flow passing between tasks/agents.
|
||||
- **Left Panel:** Remains the unified Task/Epic tree, but highlights the active epic and places "Active Agent" indicator badges next to tasks currently in progress.
|
||||
- **Right Panel (The Command Feed):** Splits into a stacked or tabbed view optimized for live operations:
|
||||
- **Active Squad Roster:** Only lists agents assigned to *this specific Epic context*. Dead agents from previous sessions are completely hidden. Shows current token usage and active task assignments.
|
||||
- **Live Telemetry (The Swarm Activity Feed):** A highly readable streaming feed of what the agents are thinking and doing *right now* ("Agent X evaluating `lib/utils.ts`", "Agent Y blocked on API key"). This replaces the current messy telemetry grid into a focused, scrolling terminal-like feed on the right.
|
||||
|
||||
## Technical Execution Plan
|
||||
|
||||
### 1. Left Panel Unification
|
||||
- Remove the `SwarmMissionPicker` override.
|
||||
- Update `unified-shell.tsx` to always render `<LeftPanel />`.
|
||||
- Enhance `<LeftPanel />` to display active agent indicators based on live telemetry data.
|
||||
|
||||
### 2. Right Panel Fixes & Contextual Rendering
|
||||
- Fix the CSS grid width causing the Right Panel to be cut off (`rightPanelWidth` adjustments in `unified-shell.tsx`).
|
||||
- Introduce `<ContextualRightPanel />` that reads the URL state (`epicId` / `taskId` vs `null`).
|
||||
- Component swap:
|
||||
- No Epic Selected -> `<GlobalActivityFeed />`
|
||||
- Epic/Task Selected -> `<SwarmCommandFeed />` (Roster + Telemetry)
|
||||
|
||||
### 3. DAG Component Merging
|
||||
- Merge `GraphView` and `SwarmWorkspace` core logic into a single `<SmartDag />` component.
|
||||
- The `<SmartDag />` will read the `epicId` context to determine its zoom level and animation states.
|
||||
- Introduce framer-motion (or existing animation libraries) for data flow and node pulsing.
|
||||
|
||||
### 4. Overhauling the Swarm Activity Feed & Roster
|
||||
- **Contextual Agent Roster:** Instead of pulling all agents globally (like `ActivityPanel` currently does), we extract the active roster logic from `TelemetryGrid` to only show agents actively assigned to `in_progress` tasks within the currently selected `epicId`.
|
||||
- **Streaming Telemetry Feed:** We reuse the `/api/events` SSE connection from `ActivityPanel`, but we filter the incoming events `beadId` to match the children of the current `epicId`. We format this feed as a terminal-like streaming log with concise, color-coded badges indicating what the agents are currently doing.
|
||||
- **Cleanup the Graveyard:** Dead agents and old task logs will be entirely stripped from this contextual right panel, ensuring it remains a focused "Command Feed" of live operations.
|
||||
|
|
|
|||
533
docs/plans/2026-03-03-global-install-runtime-manager.md
Normal file
533
docs/plans/2026-03-03-global-install-runtime-manager.md
Normal file
|
|
@ -0,0 +1,533 @@
|
|||
# BeadBoard Global Install Runtime Manager Implementation Plan
|
||||
|
||||
> **For Claude:** REQUIRED SUB-SKILL: Use superpowers:executing-plans to implement this plan task-by-task.
|
||||
|
||||
**Goal:** Replace repo-path shim install behavior with a robust global install model where `beadboard` runs from managed runtime home and works from any directory.
|
||||
|
||||
**Architecture:** Keep a hybrid install strategy with npm-global as primary and script bootstrap as fallback, but unify both paths behind one runtime manager contract (`~/.beadboard/runtime/<version>` + stable shims). Preserve backward compatibility by detecting legacy repo-bound shims and offering migration. Implement with strict TDD and explicit installer smoke tests.
|
||||
|
||||
**Tech Stack:** Node.js (ESM), TypeScript/tsx for CLI code, PowerShell + POSIX shell wrappers, GitHub Actions, Node test runner.
|
||||
|
||||
---
|
||||
|
||||
## Pre-Implementation Checklist
|
||||
|
||||
### Task 0: Baseline and Safety Snapshot
|
||||
|
||||
**Files:**
|
||||
- Modify: `beadboard/.beads/issues.jsonl` via `bd` commands only
|
||||
- Read: `/mnt/c/Users/Zenchant/codex/beadboard/AGENTS.md`
|
||||
- Read: `/mnt/c/Users/Zenchant/codex/beadboard/NEXT_SESSION_PROMPT.md`
|
||||
|
||||
**Step 1: Claim/track implementation bead(s)**
|
||||
|
||||
Run:
|
||||
```bash
|
||||
cd /mnt/c/Users/Zenchant/codex/beadboard
|
||||
bd create --title="Global installer runtime manager implementation" --description="Implement npm-global-first runtime manager with migration from repo-path shims" --type=task --priority=1 --label="installation,cli,runtime"
|
||||
bd update <new-bead-id> --status in_progress --assignee <agent-bead-id>
|
||||
```
|
||||
|
||||
**Step 2: Capture baseline gate status**
|
||||
|
||||
Run:
|
||||
```bash
|
||||
npm run typecheck
|
||||
npm run lint
|
||||
npm run test
|
||||
```
|
||||
|
||||
Expected: existing known unrelated failures may appear; record exact failing files/tests in bead notes.
|
||||
|
||||
**Step 3: Commit checkpoint**
|
||||
|
||||
No code changes yet. Do not commit.
|
||||
|
||||
---
|
||||
|
||||
## Phase 1: Define Runtime Manager Contract
|
||||
|
||||
### Task 1: Add runtime manager ADR and package contract
|
||||
|
||||
**Files:**
|
||||
- Create: `docs/adr/2026-03-03-runtime-manager-global-install.md`
|
||||
- Modify: `docs/adr/2026-03-03-global-installer-contract-and-manifest.md`
|
||||
|
||||
**Step 1: Write failing docs contract test**
|
||||
|
||||
Create:
|
||||
- `tests/docs/runtime-manager-adr-contract.test.ts`
|
||||
|
||||
```ts
|
||||
import test from 'node:test';
|
||||
import assert from 'node:assert/strict';
|
||||
import fs from 'node:fs/promises';
|
||||
import path from 'node:path';
|
||||
|
||||
test('runtime manager ADR exists and declares runtime home strategy', async () => {
|
||||
const raw = await fs.readFile(path.resolve('docs/adr/2026-03-03-runtime-manager-global-install.md'), 'utf8');
|
||||
assert.match(raw, /~\/\.beadboard\/runtime/i);
|
||||
assert.match(raw, /npm i -g beadboard/i);
|
||||
assert.match(raw, /legacy repo-bound shim migration/i);
|
||||
});
|
||||
```
|
||||
|
||||
**Step 2: Run test to verify it fails**
|
||||
|
||||
Run:
|
||||
```bash
|
||||
node --import tsx --test tests/docs/runtime-manager-adr-contract.test.ts
|
||||
```
|
||||
|
||||
Expected: FAIL (`ENOENT` for missing ADR file).
|
||||
|
||||
**Step 3: Write minimal implementation**
|
||||
|
||||
Add ADR with:
|
||||
- runtime directory layout
|
||||
- shim strategy
|
||||
- update/uninstall model
|
||||
- compatibility migration model
|
||||
- failure modes and rollback
|
||||
|
||||
**Step 4: Run test to verify it passes**
|
||||
|
||||
Run:
|
||||
```bash
|
||||
node --import tsx --test tests/docs/runtime-manager-adr-contract.test.ts
|
||||
```
|
||||
|
||||
Expected: PASS.
|
||||
|
||||
**Step 5: Commit**
|
||||
|
||||
```bash
|
||||
git add tests/docs/runtime-manager-adr-contract.test.ts docs/adr/2026-03-03-runtime-manager-global-install.md docs/adr/2026-03-03-global-installer-contract-and-manifest.md
|
||||
git commit -m "docs: define runtime manager global install contract"
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Phase 2: Implement Runtime Manager Library
|
||||
|
||||
### Task 2: Add runtime manager core module with strict validation
|
||||
|
||||
**Files:**
|
||||
- Create: `src/lib/runtime-manager.ts`
|
||||
- Create: `tests/lib/runtime-manager.test.ts`
|
||||
|
||||
**Step 1: Write failing test**
|
||||
|
||||
```ts
|
||||
import test from 'node:test';
|
||||
import assert from 'node:assert/strict';
|
||||
import { getRuntimePaths, normalizeVersion } from '../../src/lib/runtime-manager';
|
||||
|
||||
test('normalizeVersion supports semver and rejects empty', () => {
|
||||
assert.equal(normalizeVersion('1.2.3'), '1.2.3');
|
||||
assert.throws(() => normalizeVersion(''));
|
||||
});
|
||||
|
||||
test('getRuntimePaths builds ~/.beadboard/runtime/<version> layout', () => {
|
||||
const p = getRuntimePaths('/tmp/home', '1.2.3');
|
||||
assert.match(p.runtimeRoot, /runtime\/1\.2\.3$/);
|
||||
assert.match(p.shimDir, /\.beadboard\/bin$/);
|
||||
});
|
||||
```
|
||||
|
||||
**Step 2: Run test to verify it fails**
|
||||
|
||||
Run:
|
||||
```bash
|
||||
node --import tsx --test tests/lib/runtime-manager.test.ts
|
||||
```
|
||||
|
||||
Expected: FAIL (`Cannot find module '../../src/lib/runtime-manager'`).
|
||||
|
||||
**Step 3: Write minimal implementation**
|
||||
|
||||
Implement exports:
|
||||
- `normalizeVersion(version: string): string`
|
||||
- `getRuntimePaths(home: string, version: string)`
|
||||
- `resolveInstallHome(env)`
|
||||
|
||||
Keep pure and side-effect free.
|
||||
|
||||
**Step 4: Run test to verify it passes**
|
||||
|
||||
Run:
|
||||
```bash
|
||||
node --import tsx --test tests/lib/runtime-manager.test.ts
|
||||
```
|
||||
|
||||
Expected: PASS.
|
||||
|
||||
**Step 5: Commit**
|
||||
|
||||
```bash
|
||||
git add src/lib/runtime-manager.ts tests/lib/runtime-manager.test.ts
|
||||
git commit -m "feat(installer): add runtime manager core library"
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Phase 3: Move Launcher to Runtime-Aware Execution
|
||||
|
||||
### Task 3: Update launcher to run from managed runtime root
|
||||
|
||||
**Files:**
|
||||
- Modify: `install/beadboard.mjs`
|
||||
- Modify: `tests/scripts/beadboard-launcher.test.ts`
|
||||
- Create: `tests/scripts/beadboard-launcher-runtime.test.ts`
|
||||
|
||||
**Step 1: Write failing test**
|
||||
|
||||
```ts
|
||||
import test from 'node:test';
|
||||
import assert from 'node:assert/strict';
|
||||
import { execFile } from 'node:child_process';
|
||||
import { promisify } from 'node:util';
|
||||
import path from 'node:path';
|
||||
|
||||
const execFileAsync = promisify(execFile);
|
||||
const launcherPath = path.resolve('install/beadboard.mjs');
|
||||
|
||||
test('status --json reports runtime root and install mode', async () => {
|
||||
const { stdout } = await execFileAsync(process.execPath, [launcherPath, 'status', '--json']);
|
||||
const payload = JSON.parse(stdout);
|
||||
assert.ok(payload.runtimeRoot);
|
||||
assert.ok(payload.installMode);
|
||||
});
|
||||
```
|
||||
|
||||
**Step 2: Run test to verify it fails**
|
||||
|
||||
Run:
|
||||
```bash
|
||||
node --import tsx --test tests/scripts/beadboard-launcher-runtime.test.ts
|
||||
```
|
||||
|
||||
Expected: FAIL (missing fields).
|
||||
|
||||
**Step 3: Write minimal implementation**
|
||||
|
||||
In launcher:
|
||||
- derive runtime home/version
|
||||
- include `runtimeRoot`, `installMode`, `shimTarget` in JSON status
|
||||
- preserve existing `start/open/status` behavior
|
||||
|
||||
**Step 4: Run tests to verify pass**
|
||||
|
||||
Run:
|
||||
```bash
|
||||
node --import tsx --test tests/scripts/beadboard-launcher.test.ts
|
||||
node --import tsx --test tests/scripts/beadboard-launcher-runtime.test.ts
|
||||
```
|
||||
|
||||
Expected: PASS.
|
||||
|
||||
**Step 5: Commit**
|
||||
|
||||
```bash
|
||||
git add install/beadboard.mjs tests/scripts/beadboard-launcher.test.ts tests/scripts/beadboard-launcher-runtime.test.ts
|
||||
git commit -m "feat(launcher): add runtime-aware status metadata"
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Phase 4: Replace Repo-Bound Shim Targets
|
||||
|
||||
### Task 4: Make install wrappers point at runtime-managed target
|
||||
|
||||
**Files:**
|
||||
- Modify: `install/install.sh`
|
||||
- Modify: `install/install.ps1`
|
||||
- Modify: `tests/scripts/install-wrappers-contract.test.ts`
|
||||
- Modify: `tests/scripts/install-sh-smoke.test.ts`
|
||||
- Create: `tests/scripts/install-legacy-migration.test.ts`
|
||||
|
||||
**Step 1: Write failing migration test**
|
||||
|
||||
```ts
|
||||
import test from 'node:test';
|
||||
import assert from 'node:assert/strict';
|
||||
// simulate legacy shim text and verify installer rewrites to runtime target
|
||||
test('installer migrates legacy repo-bound shim to runtime-managed shim', async () => {
|
||||
assert.fail('implement');
|
||||
});
|
||||
```
|
||||
|
||||
**Step 2: Run test to verify it fails**
|
||||
|
||||
Run:
|
||||
```bash
|
||||
node --import tsx --test tests/scripts/install-legacy-migration.test.ts
|
||||
```
|
||||
|
||||
Expected: FAIL.
|
||||
|
||||
**Step 3: Write minimal implementation**
|
||||
|
||||
In both wrappers:
|
||||
- install runtime metadata file (`~/.beadboard/runtime/current.json`)
|
||||
- rewrite `bb`/`beadboard` shims to resolve runtime target first
|
||||
- detect old shim signatures and replace atomically
|
||||
|
||||
**Step 4: Run wrapper tests**
|
||||
|
||||
Run:
|
||||
```bash
|
||||
node --import tsx --test tests/scripts/install-wrappers-contract.test.ts
|
||||
node --import tsx --test tests/scripts/install-sh-smoke.test.ts
|
||||
node --import tsx --test tests/scripts/install-legacy-migration.test.ts
|
||||
```
|
||||
|
||||
Expected: PASS.
|
||||
|
||||
**Step 5: Commit**
|
||||
|
||||
```bash
|
||||
git add install/install.sh install/install.ps1 tests/scripts/install-wrappers-contract.test.ts tests/scripts/install-sh-smoke.test.ts tests/scripts/install-legacy-migration.test.ts
|
||||
git commit -m "feat(installer): migrate shims to runtime-managed targets"
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Phase 5: Add npm-Global Entry and Self-Management Commands
|
||||
|
||||
### Task 5: Add CLI entrypoint commands (`self-update`, `uninstall`, `doctor`)
|
||||
|
||||
**Files:**
|
||||
- Modify: `package.json`
|
||||
- Create: `bin/beadboard.js`
|
||||
- Create: `src/cli/beadboard-cli.ts`
|
||||
- Create: `tests/cli/beadboard-cli.test.ts`
|
||||
|
||||
**Step 1: Write failing CLI tests**
|
||||
|
||||
```ts
|
||||
import test from 'node:test';
|
||||
import assert from 'node:assert/strict';
|
||||
import { runCli } from '../../src/cli/beadboard-cli';
|
||||
|
||||
test('doctor returns structured install diagnostics', async () => {
|
||||
const out = await runCli(['doctor', '--json']);
|
||||
assert.equal(out.ok, true);
|
||||
assert.ok(out.installMode);
|
||||
});
|
||||
```
|
||||
|
||||
**Step 2: Run test to verify it fails**
|
||||
|
||||
Run:
|
||||
```bash
|
||||
node --import tsx --test tests/cli/beadboard-cli.test.ts
|
||||
```
|
||||
|
||||
Expected: FAIL (missing module/command).
|
||||
|
||||
**Step 3: Write minimal implementation**
|
||||
|
||||
Add commands:
|
||||
- `beadboard doctor --json`
|
||||
- `beadboard self-update` (placeholder behavior with explicit output if publish not configured)
|
||||
- `beadboard uninstall` (remove shims/runtime with `--yes` guard)
|
||||
|
||||
Add `bin` mapping in `package.json`.
|
||||
|
||||
**Step 4: Run test to verify pass**
|
||||
|
||||
Run:
|
||||
```bash
|
||||
node --import tsx --test tests/cli/beadboard-cli.test.ts
|
||||
```
|
||||
|
||||
Expected: PASS.
|
||||
|
||||
**Step 5: Commit**
|
||||
|
||||
```bash
|
||||
git add package.json bin/beadboard.js src/cli/beadboard-cli.ts tests/cli/beadboard-cli.test.ts
|
||||
git commit -m "feat(cli): add global entrypoint with doctor/update/uninstall commands"
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Phase 6: Driver Alignment + Remediation UX Finalization
|
||||
|
||||
### Task 6: Update driver preflight/remediation copy for npm-global-first flow
|
||||
|
||||
**Files:**
|
||||
- Modify: `skills/beadboard-driver/scripts/lib/driver-lib.mjs`
|
||||
- Modify: `skills/beadboard-driver/scripts/session-preflight.mjs`
|
||||
- Modify: `tests/skills/beadboard-driver/resolve-bb.test.ts`
|
||||
- Modify: `tests/skills/beadboard-driver/session-preflight.test.ts`
|
||||
|
||||
**Step 1: Write failing test assertion**
|
||||
|
||||
Add expectation:
|
||||
- remediation mentions `npm i -g beadboard` as primary
|
||||
- install script remains fallback
|
||||
|
||||
**Step 2: Run test to verify it fails**
|
||||
|
||||
Run:
|
||||
```bash
|
||||
node --import tsx --test tests/skills/beadboard-driver/resolve-bb.test.ts
|
||||
node --import tsx --test tests/skills/beadboard-driver/session-preflight.test.ts
|
||||
```
|
||||
|
||||
Expected: FAIL (copy mismatch).
|
||||
|
||||
**Step 3: Write minimal implementation**
|
||||
|
||||
Update remediation strings to:
|
||||
1. npm-global install
|
||||
2. fallback installer wrapper
|
||||
3. BB_REPO override guidance
|
||||
|
||||
**Step 4: Re-run tests**
|
||||
|
||||
Run:
|
||||
```bash
|
||||
node --import tsx --test tests/skills/beadboard-driver/resolve-bb.test.ts
|
||||
node --import tsx --test tests/skills/beadboard-driver/session-preflight.test.ts
|
||||
```
|
||||
|
||||
Expected: PASS.
|
||||
|
||||
**Step 5: Commit**
|
||||
|
||||
```bash
|
||||
git add skills/beadboard-driver/scripts/lib/driver-lib.mjs skills/beadboard-driver/scripts/session-preflight.mjs tests/skills/beadboard-driver/resolve-bb.test.ts tests/skills/beadboard-driver/session-preflight.test.ts
|
||||
git commit -m "feat(driver): prefer npm-global remediation with installer fallback"
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Phase 7: CI, Docs, and Release Readiness
|
||||
|
||||
### Task 7: Expand CI smoke and operator docs for global model
|
||||
|
||||
**Files:**
|
||||
- Modify: `.github/workflows/installer-smoke.yml`
|
||||
- Modify: `README.md`
|
||||
- Modify: `docs/adr/2026-03-03-runtime-manager-global-install.md`
|
||||
- Create: `docs/ops/global-install-rollout.md`
|
||||
- Modify: `tests/scripts/installer-ci-contract.test.ts`
|
||||
- Modify: `tests/docs/installer-quickstart-contract.test.ts`
|
||||
|
||||
**Step 1: Write failing test updates**
|
||||
|
||||
Add assertions for:
|
||||
- npm-global command in docs
|
||||
- runtime home path mentions
|
||||
- CI step validating `beadboard doctor --json`
|
||||
|
||||
**Step 2: Run tests to verify fail**
|
||||
|
||||
Run:
|
||||
```bash
|
||||
node --import tsx --test tests/scripts/installer-ci-contract.test.ts
|
||||
node --import tsx --test tests/docs/installer-quickstart-contract.test.ts
|
||||
```
|
||||
|
||||
Expected: FAIL.
|
||||
|
||||
**Step 3: Write minimal implementation**
|
||||
|
||||
Update docs and workflow:
|
||||
- install paths
|
||||
- migration notes
|
||||
- recovery playbook
|
||||
- supported platforms matrix
|
||||
|
||||
**Step 4: Re-run tests**
|
||||
|
||||
Run:
|
||||
```bash
|
||||
node --import tsx --test tests/scripts/installer-ci-contract.test.ts
|
||||
node --import tsx --test tests/docs/installer-quickstart-contract.test.ts
|
||||
```
|
||||
|
||||
Expected: PASS.
|
||||
|
||||
**Step 5: Commit**
|
||||
|
||||
```bash
|
||||
git add .github/workflows/installer-smoke.yml README.md docs/adr/2026-03-03-runtime-manager-global-install.md docs/ops/global-install-rollout.md tests/scripts/installer-ci-contract.test.ts tests/docs/installer-quickstart-contract.test.ts
|
||||
git commit -m "docs(ci): finalize global install runtime docs and smoke coverage"
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Phase 8: Final Verification + Bead Closeout
|
||||
|
||||
### Task 8: Full-gate verification and close
|
||||
|
||||
**Files:**
|
||||
- Modify: `beadboard` issue notes via `bd update`
|
||||
- Modify: `NEXT_SESSION_PROMPT.md`
|
||||
|
||||
**Step 1: Run full gates**
|
||||
|
||||
Run:
|
||||
```bash
|
||||
npm run typecheck
|
||||
npm run lint
|
||||
npm run test
|
||||
```
|
||||
|
||||
Expected: PASS; if unrelated failures exist, capture exact files/tests.
|
||||
|
||||
**Step 2: Run targeted installer acceptance checks**
|
||||
|
||||
Run:
|
||||
```bash
|
||||
node --import tsx --test tests/lib/runtime-manager.test.ts
|
||||
node --import tsx --test tests/scripts/beadboard-launcher-runtime.test.ts
|
||||
node --import tsx --test tests/scripts/install-legacy-migration.test.ts
|
||||
node --import tsx --test tests/skills/beadboard-driver/resolve-bb.test.ts
|
||||
```
|
||||
|
||||
Expected: PASS.
|
||||
|
||||
**Step 3: Update beads with evidence**
|
||||
|
||||
Run:
|
||||
```bash
|
||||
bd update <bead-id> --notes "<commands run + pass/fail details>"
|
||||
bd close <bead-id> --reason "<completed outcome>"
|
||||
```
|
||||
|
||||
**Step 4: Update handoff**
|
||||
|
||||
Modify:
|
||||
- `NEXT_SESSION_PROMPT.md` with shipped state + residual risks + next bead.
|
||||
|
||||
**Step 5: Commit**
|
||||
|
||||
```bash
|
||||
git add NEXT_SESSION_PROMPT.md
|
||||
git commit -m "chore: close runtime-manager rollout with verification evidence"
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## References and Required Skills During Execution
|
||||
|
||||
1. `@test-driven-development`
|
||||
2. `@verification-before-completion`
|
||||
3. `@linus-beads-discipline`
|
||||
4. `@beadboard-driver`
|
||||
5. `@executing-plans` (required for implementation phase)
|
||||
|
||||
---
|
||||
|
||||
Plan complete and saved to `docs/plans/2026-03-03-global-install-runtime-manager.md`. Two execution options:
|
||||
|
||||
**1. Subagent-Driven (this session)** - I dispatch fresh subagent per task, review between tasks, fast iteration
|
||||
|
||||
**2. Parallel Session (separate)** - Open new session with executing-plans, batch execution with checkpoints
|
||||
|
||||
Which approach?
|
||||
File diff suppressed because it is too large
Load diff
|
|
@ -29,5 +29,5 @@ const eslintConfig = [
|
|||
},
|
||||
},
|
||||
];
|
||||
|
||||
export default eslintConfig;
|
||||
|
||||
export default eslintConfig;
|
||||
|
|
|
|||
|
|
@ -1,71 +1,71 @@
|
|||
bb-atf
|
||||
bb-z6s
|
||||
bb-54x
|
||||
bb-nuy
|
||||
bb-98c
|
||||
bb-3ha
|
||||
bb-22l
|
||||
bb-5am
|
||||
bb-dwz
|
||||
bb-3dv
|
||||
bb-only-ui-agent
|
||||
bb-graph-agent-1
|
||||
bb-ui-agent-2
|
||||
bb-ui-agent-1
|
||||
bb-verify-mlnavzwu
|
||||
bb-final-mlnar702
|
||||
bb-verify2-mlnaouad
|
||||
bb-final-mlnalaqz
|
||||
bb-bridge-fix-mlnaja4j
|
||||
bb-verify-mlnadaip
|
||||
bb-switch-mlna9nbo
|
||||
bb-join-mlna9nbo
|
||||
bb-invepic-mln9perd
|
||||
bb-m2-mln9perd
|
||||
bb-invalid-epic-mln9hraq
|
||||
bb-m1-mln9perd
|
||||
bb-leave-mln9perd
|
||||
bb-member3-mln9hraq
|
||||
bb-member2-mln9hraq
|
||||
bb-member1-mln9hraq
|
||||
bb-switch-mln9perd
|
||||
bb-nolabel-test-mln9hraq
|
||||
bb-join-mln9perd
|
||||
bb-leave-test-mln9hraq
|
||||
bb-idem-test-mln9hraq
|
||||
bb-debug-mln9knzs
|
||||
bb-switch-test-mln9hraq
|
||||
bb-join-test-mln9hraq
|
||||
bb-smoke-mln9e525
|
||||
bb-idem-test-mln97lyt
|
||||
bb-switch-test-mln97lyt
|
||||
bb-join-test-mln97lyt
|
||||
bb-switch-test-mln8xxn4
|
||||
bb-join-test-mln8xxn4
|
||||
bb-nolabel-test-mln8pdgh
|
||||
bb-leave-test-mln8pdgh
|
||||
bb-idem-test-mln8pdgh
|
||||
bb-switch-test-mln8pdgh
|
||||
bb-join-test-mln8pdgh
|
||||
bb-leave-test-mln8hp8j
|
||||
bb-idem-test-mln8hp8j
|
||||
bb-switch-test-mln8hp8j
|
||||
bb-join-test-mln8hp8j
|
||||
bb-daemon-test-mln8e4tf
|
||||
bb-fresh-test-mln8canu
|
||||
bb-upd-test-mln8981k
|
||||
bb-step-test-mln872rm
|
||||
bb-debug-test-mln83q18
|
||||
bb-switch-test-mln7xyls
|
||||
bb-join-test-mln7xyls
|
||||
bb-linus-swarm
|
||||
bb-agent-graph-1
|
||||
bb-1xj
|
||||
bb-agent-a
|
||||
bb-agent-b
|
||||
bb-active-agent
|
||||
bb-agent-ui-1
|
||||
bb-green-falcon
|
||||
bb-zenchantlive
|
||||
bb-silver-castle
|
||||
bb-test-agent
|
||||
bb-atf
|
||||
bb-z6s
|
||||
bb-54x
|
||||
bb-nuy
|
||||
bb-98c
|
||||
bb-3ha
|
||||
bb-22l
|
||||
bb-5am
|
||||
bb-dwz
|
||||
bb-3dv
|
||||
bb-only-ui-agent
|
||||
bb-graph-agent-1
|
||||
bb-ui-agent-2
|
||||
bb-ui-agent-1
|
||||
bb-verify-mlnavzwu
|
||||
bb-final-mlnar702
|
||||
bb-verify2-mlnaouad
|
||||
bb-final-mlnalaqz
|
||||
bb-bridge-fix-mlnaja4j
|
||||
bb-verify-mlnadaip
|
||||
bb-switch-mlna9nbo
|
||||
bb-join-mlna9nbo
|
||||
bb-invepic-mln9perd
|
||||
bb-m2-mln9perd
|
||||
bb-invalid-epic-mln9hraq
|
||||
bb-m1-mln9perd
|
||||
bb-leave-mln9perd
|
||||
bb-member3-mln9hraq
|
||||
bb-member2-mln9hraq
|
||||
bb-member1-mln9hraq
|
||||
bb-switch-mln9perd
|
||||
bb-nolabel-test-mln9hraq
|
||||
bb-join-mln9perd
|
||||
bb-leave-test-mln9hraq
|
||||
bb-idem-test-mln9hraq
|
||||
bb-debug-mln9knzs
|
||||
bb-switch-test-mln9hraq
|
||||
bb-join-test-mln9hraq
|
||||
bb-smoke-mln9e525
|
||||
bb-idem-test-mln97lyt
|
||||
bb-switch-test-mln97lyt
|
||||
bb-join-test-mln97lyt
|
||||
bb-switch-test-mln8xxn4
|
||||
bb-join-test-mln8xxn4
|
||||
bb-nolabel-test-mln8pdgh
|
||||
bb-leave-test-mln8pdgh
|
||||
bb-idem-test-mln8pdgh
|
||||
bb-switch-test-mln8pdgh
|
||||
bb-join-test-mln8pdgh
|
||||
bb-leave-test-mln8hp8j
|
||||
bb-idem-test-mln8hp8j
|
||||
bb-switch-test-mln8hp8j
|
||||
bb-join-test-mln8hp8j
|
||||
bb-daemon-test-mln8e4tf
|
||||
bb-fresh-test-mln8canu
|
||||
bb-upd-test-mln8981k
|
||||
bb-step-test-mln872rm
|
||||
bb-debug-test-mln83q18
|
||||
bb-switch-test-mln7xyls
|
||||
bb-join-test-mln7xyls
|
||||
bb-linus-swarm
|
||||
bb-agent-graph-1
|
||||
bb-1xj
|
||||
bb-agent-a
|
||||
bb-agent-b
|
||||
bb-active-agent
|
||||
bb-agent-ui-1
|
||||
bb-green-falcon
|
||||
bb-zenchantlive
|
||||
bb-silver-castle
|
||||
bb-test-agent
|
||||
|
|
|
|||
|
|
@ -1,53 +1,53 @@
|
|||
# Agent Workflow for Beadboard
|
||||
|
||||
As an agent working in this repository, you must follow these rules when managing tasks using `bd`.
|
||||
|
||||
---
|
||||
|
||||
## 1. Finding Work
|
||||
Before starting any new work, check if there's already an open task for it.
|
||||
```bash
|
||||
bd ready
|
||||
```
|
||||
*If a task is ready, pick it up instead of creating a duplicate.*
|
||||
|
||||
## 2. Starting Work / Tracking Plans
|
||||
When asked to perform non-trivial work without an existing task, **always create a task**.
|
||||
Do **not** keep your plan in free-form text. Create a task with `priority 0`.
|
||||
```bash
|
||||
bd create "Short descriptive title of the work" -p 0
|
||||
```
|
||||
Update the status to `in_progress` if you are working on it:
|
||||
```bash
|
||||
bd set-state <task-id> in_progress
|
||||
```
|
||||
|
||||
## 3. Working within Tasks (task.md)
|
||||
Update the local `<appDataDir>/brain/<conversation-id>/task.md` using the checklist `[ ]`, `[/]`, `[x]` to maintain your internal progress while working. Also update the `bd` task if you have significant architectural notes.
|
||||
|
||||
## 4. Dependencies
|
||||
If your task depends on another task being completed first, declare the block:
|
||||
```bash
|
||||
# Link: your task is blocked by another task
|
||||
# First run bd dep add, it will prompt you interactively.
|
||||
# Or use the appropriate arguments if you know them.
|
||||
# The user prefers bd handle these rather than prose "do X after Y"
|
||||
```
|
||||
|
||||
## 5. Finishing Work
|
||||
When you have finished a task, completed your tests, and verified it works (run your lint/typecheck steps), you must close the task.
|
||||
|
||||
1. **Verify completion**: `bun run typecheck && bun run lint`
|
||||
2. **Close the bead**:
|
||||
```bash
|
||||
# You can use bd update or bd close
|
||||
bd status <task-id> # To view it
|
||||
bd close <task-id> # To mark it closed
|
||||
```
|
||||
3. **Summarize**: Leave a summary of what changed. (You can do this by using bd edit or through a comment if bd supports it, otherwise summarize in your git commit).
|
||||
|
||||
## 6. Verifying Past Work (Recently Closed Beads)
|
||||
If you need to know what was just finished (e.g. to see if a bead was successfully closed), view the recently closed beads:
|
||||
```bash
|
||||
bd query "status=closed" --sort closed --reverse --limit 5
|
||||
```
|
||||
# Agent Workflow for Beadboard
|
||||
|
||||
As an agent working in this repository, you must follow these rules when managing tasks using `bd`.
|
||||
|
||||
---
|
||||
|
||||
## 1. Finding Work
|
||||
Before starting any new work, check if there's already an open task for it.
|
||||
```bash
|
||||
bd ready
|
||||
```
|
||||
*If a task is ready, pick it up instead of creating a duplicate.*
|
||||
|
||||
## 2. Starting Work / Tracking Plans
|
||||
When asked to perform non-trivial work without an existing task, **always create a task**.
|
||||
Do **not** keep your plan in free-form text. Create a task with `priority 0`.
|
||||
```bash
|
||||
bd create "Short descriptive title of the work" -p 0
|
||||
```
|
||||
Update the status to `in_progress` if you are working on it:
|
||||
```bash
|
||||
bd set-state <task-id> in_progress
|
||||
```
|
||||
|
||||
## 3. Working within Tasks (task.md)
|
||||
Update the local `<appDataDir>/brain/<conversation-id>/task.md` using the checklist `[ ]`, `[/]`, `[x]` to maintain your internal progress while working. Also update the `bd` task if you have significant architectural notes.
|
||||
|
||||
## 4. Dependencies
|
||||
If your task depends on another task being completed first, declare the block:
|
||||
```bash
|
||||
# Link: your task is blocked by another task
|
||||
# First run bd dep add, it will prompt you interactively.
|
||||
# Or use the appropriate arguments if you know them.
|
||||
# The user prefers bd handle these rather than prose "do X after Y"
|
||||
```
|
||||
|
||||
## 5. Finishing Work
|
||||
When you have finished a task, completed your tests, and verified it works (run your lint/typecheck steps), you must close the task.
|
||||
|
||||
1. **Verify completion**: `bun run typecheck && bun run lint`
|
||||
2. **Close the bead**:
|
||||
```bash
|
||||
# You can use bd update or bd close
|
||||
bd status <task-id> # To view it
|
||||
bd close <task-id> # To mark it closed
|
||||
```
|
||||
3. **Summarize**: Leave a summary of what changed. (You can do this by using bd edit or through a comment if bd supports it, otherwise summarize in your git commit).
|
||||
|
||||
## 6. Verifying Past Work (Recently Closed Beads)
|
||||
If you need to know what was just finished (e.g. to see if a bead was successfully closed), view the recently closed beads:
|
||||
```bash
|
||||
bd query "status=closed" --sort closed --reverse --limit 5
|
||||
```
|
||||
|
|
|
|||
|
|
@ -1,52 +1,52 @@
|
|||
# Beadboard Dolt System Workflow
|
||||
|
||||
Beadboard supports an optional **Dolt storage backend**. Dolt is a SQL database with git-like version control, enabling advanced features like branching, merging, and historic diffs for your issue data.
|
||||
|
||||
If your environment has Dolt enabled (no CGO build errors when using `bd`), you have access to powerful new version control commands. They behave similarly to `git` but operate purely on Beadboard issues.
|
||||
|
||||
## 1. Branching
|
||||
You can create branches of your issue database, to test speculative features or isolate a swarm of issues before merging them into main.
|
||||
|
||||
- **List all branches**:
|
||||
```bash
|
||||
bd branch
|
||||
```
|
||||
- **Create a new branch**:
|
||||
```bash
|
||||
bd branch <branch-name>
|
||||
```
|
||||
|
||||
## 2. Version Control (Commit & Merge)
|
||||
Use `bd vc` to manage commits on your branch.
|
||||
|
||||
- **View status of current branch**:
|
||||
```bash
|
||||
bd vc status
|
||||
```
|
||||
- **Create a commit**:
|
||||
```bash
|
||||
bd vc commit
|
||||
```
|
||||
- **Merge a branch**:
|
||||
```bash
|
||||
bd vc merge <branch-to-merge>
|
||||
```
|
||||
|
||||
*Note: You can also rely on `--dolt-auto-commit=on` (which can be set in config) to automatically commit changes after write operations like `bd create` or `bd update`.*
|
||||
|
||||
## 3. Viewing Diffs
|
||||
You can view the exact issue changes (created, deleted, modified) between two commits or branches.
|
||||
|
||||
- **Compare current state against a branch**:
|
||||
```bash
|
||||
bd diff main feature-branch
|
||||
```
|
||||
- **Compare history**:
|
||||
```bash
|
||||
bd diff HEAD~5 HEAD # Show changes in the last 5 commits
|
||||
```
|
||||
|
||||
## Summary for Agents
|
||||
If you receive an error about `dolt backend requires CGO` when running `bd ready`, it means the Dolt features are not available on this specific build. You must fall back to standard `bd` commands which use SQLite by default and sync via JSONL files.
|
||||
|
||||
However, when working in a Dolt-enabled environment, you should proactively create a branch when starting a large Epic (`bd branch feature-xyz`), commit your `bd` issue changes natively tracking the state (`bd vc commit`), and merge them back when the epic is verified (`bd vc merge`).
|
||||
# Beadboard Dolt System Workflow
|
||||
|
||||
Beadboard supports an optional **Dolt storage backend**. Dolt is a SQL database with git-like version control, enabling advanced features like branching, merging, and historic diffs for your issue data.
|
||||
|
||||
If your environment has Dolt enabled (no CGO build errors when using `bd`), you have access to powerful new version control commands. They behave similarly to `git` but operate purely on Beadboard issues.
|
||||
|
||||
## 1. Branching
|
||||
You can create branches of your issue database, to test speculative features or isolate a swarm of issues before merging them into main.
|
||||
|
||||
- **List all branches**:
|
||||
```bash
|
||||
bd branch
|
||||
```
|
||||
- **Create a new branch**:
|
||||
```bash
|
||||
bd branch <branch-name>
|
||||
```
|
||||
|
||||
## 2. Version Control (Commit & Merge)
|
||||
Use `bd vc` to manage commits on your branch.
|
||||
|
||||
- **View status of current branch**:
|
||||
```bash
|
||||
bd vc status
|
||||
```
|
||||
- **Create a commit**:
|
||||
```bash
|
||||
bd vc commit
|
||||
```
|
||||
- **Merge a branch**:
|
||||
```bash
|
||||
bd vc merge <branch-to-merge>
|
||||
```
|
||||
|
||||
*Note: You can also rely on `--dolt-auto-commit=on` (which can be set in config) to automatically commit changes after write operations like `bd create` or `bd update`.*
|
||||
|
||||
## 3. Viewing Diffs
|
||||
You can view the exact issue changes (created, deleted, modified) between two commits or branches.
|
||||
|
||||
- **Compare current state against a branch**:
|
||||
```bash
|
||||
bd diff main feature-branch
|
||||
```
|
||||
- **Compare history**:
|
||||
```bash
|
||||
bd diff HEAD~5 HEAD # Show changes in the last 5 commits
|
||||
```
|
||||
|
||||
## Summary for Agents
|
||||
If you receive an error about `dolt backend requires CGO` when running `bd ready`, it means the Dolt features are not available on this specific build. You must fall back to standard `bd` commands which use SQLite by default and sync via JSONL files.
|
||||
|
||||
However, when working in a Dolt-enabled environment, you should proactively create a branch when starting a large Epic (`bd branch feature-xyz`), commit your `bd` issue changes natively tracking the state (`bd vc commit`), and merge them back when the epic is verified (`bd vc merge`).
|
||||
|
|
|
|||
|
|
@ -1,49 +1,49 @@
|
|||
# Viewing Recently Closed Beads
|
||||
|
||||
When you need to find beads (tasks, issues) that were recently closed, use `bd query` or `bd list` with date filters.
|
||||
The user rule indicates a need to "correctly view the last closed beads (there is some sort of filter for recency)".
|
||||
|
||||
## Method 1: Using `bd query`
|
||||
|
||||
`bd query` supports a simple query language with relative and absolute dates.
|
||||
|
||||
1. **View closed beads in the last X days**
|
||||
```bash
|
||||
bd query "status=closed AND updated>2d" --sort updated
|
||||
```
|
||||
*This finds beads closed and updated within the last 2 days, sorted chronologically with newest at the bottom.*
|
||||
|
||||
2. **View closed beads in the last 24 hours**
|
||||
```bash
|
||||
bd query "status=closed AND updated>24h" --sort updated
|
||||
```
|
||||
|
||||
3. **View everything closed**
|
||||
```bash
|
||||
bd query "status=closed" --sort closed --limit 10 --reverse
|
||||
```
|
||||
*This shows the 10 most recently closed beads (requires --reverse so limit grabs the newest).*
|
||||
|
||||
## Method 2: Using `bd list`
|
||||
|
||||
`bd list` has specific flags for filtering by closure date.
|
||||
|
||||
1. **View closed beads using --closed-after**
|
||||
```bash
|
||||
bd list --status closed --closed-after "7d" --sort closed --reverse
|
||||
```
|
||||
Wait, the `--closed-after` flag expects YYYY-MM-DD or RFC3339. The better approach for relative dates is `bd query`.
|
||||
|
||||
However, if using absolute dates:
|
||||
```bash
|
||||
bd list --status closed --closed-after 2025-01-01 --sort closed --reverse
|
||||
```
|
||||
|
||||
## Summary for Agents:
|
||||
**Always use `bd query` with relative time for the best results** when checking recency.
|
||||
|
||||
To view recently closed beads (within the last 3 days) in standard terminal chronological order (oldest at top, newest at bottom):
|
||||
**`bd query "status=closed AND closed>3d" --sort closed`**
|
||||
|
||||
To get just the last 5 closed beads (note: you must use --reverse to get the most recent ones when using --limit):
|
||||
**`bd query "status=closed" --sort closed --reverse --limit 5`**
|
||||
# Viewing Recently Closed Beads
|
||||
|
||||
When you need to find beads (tasks, issues) that were recently closed, use `bd query` or `bd list` with date filters.
|
||||
The user rule indicates a need to "correctly view the last closed beads (there is some sort of filter for recency)".
|
||||
|
||||
## Method 1: Using `bd query`
|
||||
|
||||
`bd query` supports a simple query language with relative and absolute dates.
|
||||
|
||||
1. **View closed beads in the last X days**
|
||||
```bash
|
||||
bd query "status=closed AND updated>2d" --sort updated
|
||||
```
|
||||
*This finds beads closed and updated within the last 2 days, sorted chronologically with newest at the bottom.*
|
||||
|
||||
2. **View closed beads in the last 24 hours**
|
||||
```bash
|
||||
bd query "status=closed AND updated>24h" --sort updated
|
||||
```
|
||||
|
||||
3. **View everything closed**
|
||||
```bash
|
||||
bd query "status=closed" --sort closed --limit 10 --reverse
|
||||
```
|
||||
*This shows the 10 most recently closed beads (requires --reverse so limit grabs the newest).*
|
||||
|
||||
## Method 2: Using `bd list`
|
||||
|
||||
`bd list` has specific flags for filtering by closure date.
|
||||
|
||||
1. **View closed beads using --closed-after**
|
||||
```bash
|
||||
bd list --status closed --closed-after "7d" --sort closed --reverse
|
||||
```
|
||||
Wait, the `--closed-after` flag expects YYYY-MM-DD or RFC3339. The better approach for relative dates is `bd query`.
|
||||
|
||||
However, if using absolute dates:
|
||||
```bash
|
||||
bd list --status closed --closed-after 2025-01-01 --sort closed --reverse
|
||||
```
|
||||
|
||||
## Summary for Agents:
|
||||
**Always use `bd query` with relative time for the best results** when checking recency.
|
||||
|
||||
To view recently closed beads (within the last 3 days) in standard terminal chronological order (oldest at top, newest at bottom):
|
||||
**`bd query "status=closed AND closed>3d" --sort closed`**
|
||||
|
||||
To get just the last 5 closed beads (note: you must use --reverse to get the most recent ones when using --limit):
|
||||
**`bd query "status=closed" --sort closed --reverse --limit 5`**
|
||||
|
|
|
|||
25
install/manifest.json
Normal file
25
install/manifest.json
Normal file
|
|
@ -0,0 +1,25 @@
|
|||
{
|
||||
"version": "installer.v1",
|
||||
"distribution": {
|
||||
"packageName": "beadboard",
|
||||
"shimNames": ["bb", "beadboard"]
|
||||
},
|
||||
"wrappers": {
|
||||
"windows": {
|
||||
"script": "install.ps1"
|
||||
},
|
||||
"posix": {
|
||||
"script": "install.sh"
|
||||
}
|
||||
},
|
||||
"runtime": {
|
||||
"start": "beadboard start",
|
||||
"open": "beadboard open",
|
||||
"status": "beadboard status"
|
||||
},
|
||||
"driver": {
|
||||
"remediationMode": "detect_only",
|
||||
"installSideEffects": false
|
||||
}
|
||||
}
|
||||
|
||||
12
next-env.d.ts
vendored
12
next-env.d.ts
vendored
|
|
@ -1,6 +1,6 @@
|
|||
/// <reference types="next" />
|
||||
/// <reference types="next/image-types/global" />
|
||||
/// <reference path="./.next/types/routes.d.ts" />
|
||||
|
||||
// NOTE: This file should not be edited
|
||||
// see https://nextjs.org/docs/app/api-reference/config/typescript for more information.
|
||||
/// <reference types="next" />
|
||||
/// <reference types="next/image-types/global" />
|
||||
/// <reference path="./.next/types/routes.d.ts" />
|
||||
|
||||
// NOTE: This file should not be edited
|
||||
// see https://nextjs.org/docs/app/api-reference/config/typescript for more information.
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
import type { NextConfig } from 'next';
|
||||
import path from 'node:path';
|
||||
|
||||
import type { NextConfig } from 'next';
|
||||
import path from 'node:path';
|
||||
|
||||
const nextConfig: NextConfig = {
|
||||
reactStrictMode: true,
|
||||
outputFileTracingRoot: path.join(process.cwd()),
|
||||
|
|
@ -32,9 +32,9 @@ const nextConfig: NextConfig = {
|
|||
if (dev) {
|
||||
// Avoid intermittent Windows ENOENT errors from webpack filesystem pack cache.
|
||||
config.cache = false;
|
||||
}
|
||||
return config;
|
||||
},
|
||||
};
|
||||
|
||||
export default nextConfig;
|
||||
}
|
||||
return config;
|
||||
},
|
||||
};
|
||||
|
||||
export default nextConfig;
|
||||
|
|
|
|||
|
|
@ -1,39 +1,39 @@
|
|||
import { DependencyGraphPage } from '../../components/graph/dependency-graph-page';
|
||||
|
||||
export const dynamic = 'force-dynamic';
|
||||
import { readIssuesForScope } from '../../lib/aggregate-read';
|
||||
import { resolveProjectScope } from '../../lib/project-scope';
|
||||
import { listProjects } from '../../lib/registry';
|
||||
|
||||
interface GraphPageProps {
|
||||
searchParams?: Promise<Record<string, string | string[] | undefined>>;
|
||||
}
|
||||
|
||||
export default async function GraphPage({ searchParams }: GraphPageProps) {
|
||||
const params = (await searchParams) ?? {};
|
||||
const requestedProjectKey = typeof params.project === 'string' ? params.project : null;
|
||||
const requestedMode = typeof params.mode === 'string' ? params.mode : null;
|
||||
const registryProjects = await listProjects();
|
||||
const scope = resolveProjectScope({
|
||||
currentProjectRoot: process.cwd(),
|
||||
registryProjects,
|
||||
requestedProjectKey,
|
||||
requestedMode,
|
||||
});
|
||||
|
||||
import { DependencyGraphPage } from '../../components/graph/dependency-graph-page';
|
||||
|
||||
export const dynamic = 'force-dynamic';
|
||||
import { readIssuesForScope } from '../../lib/aggregate-read';
|
||||
import { resolveProjectScope } from '../../lib/project-scope';
|
||||
import { listProjects } from '../../lib/registry';
|
||||
|
||||
interface GraphPageProps {
|
||||
searchParams?: Promise<Record<string, string | string[] | undefined>>;
|
||||
}
|
||||
|
||||
export default async function GraphPage({ searchParams }: GraphPageProps) {
|
||||
const params = (await searchParams) ?? {};
|
||||
const requestedProjectKey = typeof params.project === 'string' ? params.project : null;
|
||||
const requestedMode = typeof params.mode === 'string' ? params.mode : null;
|
||||
const registryProjects = await listProjects();
|
||||
const scope = resolveProjectScope({
|
||||
currentProjectRoot: process.cwd(),
|
||||
registryProjects,
|
||||
requestedProjectKey,
|
||||
requestedMode,
|
||||
});
|
||||
|
||||
const issues = await readIssuesForScope({
|
||||
mode: scope.mode,
|
||||
selected: scope.selected,
|
||||
scopeOptions: scope.options,
|
||||
preferBd: true,
|
||||
});
|
||||
return (
|
||||
<DependencyGraphPage
|
||||
issues={issues}
|
||||
projectRoot={scope.selected.root}
|
||||
projectScopeKey={scope.selected.key}
|
||||
projectScopeOptions={scope.options}
|
||||
projectScopeMode={scope.mode}
|
||||
/>
|
||||
);
|
||||
}
|
||||
return (
|
||||
<DependencyGraphPage
|
||||
issues={issues}
|
||||
projectRoot={scope.selected.root}
|
||||
projectScopeKey={scope.selected.key}
|
||||
projectScopeOptions={scope.options}
|
||||
projectScopeMode={scope.mode}
|
||||
/>
|
||||
);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,37 +1,37 @@
|
|||
import { KanbanPage } from '../components/kanban/kanban-page';
|
||||
import { readIssuesForScope } from '../lib/aggregate-read';
|
||||
import { resolveProjectScope } from '../lib/project-scope';
|
||||
import { listProjects } from '../lib/registry';
|
||||
|
||||
interface PageProps {
|
||||
searchParams?: Promise<Record<string, string | string[] | undefined>>;
|
||||
}
|
||||
|
||||
export default async function Page({ searchParams }: PageProps) {
|
||||
const params = (await searchParams) ?? {};
|
||||
const requestedProjectKey = typeof params.project === 'string' ? params.project : null;
|
||||
const requestedMode = typeof params.mode === 'string' ? params.mode : null;
|
||||
const registryProjects = await listProjects();
|
||||
const scope = resolveProjectScope({
|
||||
currentProjectRoot: process.cwd(),
|
||||
registryProjects,
|
||||
requestedProjectKey,
|
||||
requestedMode,
|
||||
});
|
||||
|
||||
import { KanbanPage } from '../components/kanban/kanban-page';
|
||||
import { readIssuesForScope } from '../lib/aggregate-read';
|
||||
import { resolveProjectScope } from '../lib/project-scope';
|
||||
import { listProjects } from '../lib/registry';
|
||||
|
||||
interface PageProps {
|
||||
searchParams?: Promise<Record<string, string | string[] | undefined>>;
|
||||
}
|
||||
|
||||
export default async function Page({ searchParams }: PageProps) {
|
||||
const params = (await searchParams) ?? {};
|
||||
const requestedProjectKey = typeof params.project === 'string' ? params.project : null;
|
||||
const requestedMode = typeof params.mode === 'string' ? params.mode : null;
|
||||
const registryProjects = await listProjects();
|
||||
const scope = resolveProjectScope({
|
||||
currentProjectRoot: process.cwd(),
|
||||
registryProjects,
|
||||
requestedProjectKey,
|
||||
requestedMode,
|
||||
});
|
||||
|
||||
const issues = await readIssuesForScope({
|
||||
mode: scope.mode,
|
||||
selected: scope.selected,
|
||||
scopeOptions: scope.options,
|
||||
preferBd: true,
|
||||
});
|
||||
return (
|
||||
<KanbanPage
|
||||
issues={issues}
|
||||
projectRoot={scope.selected.root}
|
||||
projectScopeKey={scope.selected.key}
|
||||
projectScopeOptions={scope.options}
|
||||
projectScopeMode={scope.mode}
|
||||
/>
|
||||
);
|
||||
}
|
||||
return (
|
||||
<KanbanPage
|
||||
issues={issues}
|
||||
projectRoot={scope.selected.root}
|
||||
projectScopeKey={scope.selected.key}
|
||||
projectScopeOptions={scope.options}
|
||||
projectScopeMode={scope.mode}
|
||||
/>
|
||||
);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,140 +1,140 @@
|
|||
#!/usr/bin/env node
|
||||
|
||||
/**
|
||||
* bb-init.mjs - Agent Session Bootstrapper (Lease-Based)
|
||||
*
|
||||
* Part of Operative Protocol v1 (bb-u6f.6.3)
|
||||
*
|
||||
* Responsibility:
|
||||
* 1. Resolve bb.ps1 path.
|
||||
* 2. Identify agent (adopt or register).
|
||||
* 3. Start the initial activity lease.
|
||||
*
|
||||
* Note: No background processes are spawned. Liveness is maintained
|
||||
* via passive side-effects of CLI commands (Activity-based model).
|
||||
*/
|
||||
|
||||
import { parseArgs } from 'node:util';
|
||||
import fs from 'node:fs/promises';
|
||||
import path from 'node:path';
|
||||
import os from 'node:os';
|
||||
import { execSync, execFileSync } from 'node:child_process';
|
||||
|
||||
function log(obj) {
|
||||
process.stdout.write(`${JSON.stringify(obj, null, 2)}
|
||||
`);
|
||||
}
|
||||
|
||||
function error(code, message) {
|
||||
log({ ok: false, error: { code, message } });
|
||||
process.exit(1);
|
||||
}
|
||||
|
||||
async function getUncommittedChanges(projectRoot) {
|
||||
try {
|
||||
const out = execSync('git status --porcelain', { cwd: projectRoot, encoding: 'utf8' });
|
||||
return out.split('\n')
|
||||
.filter(Boolean)
|
||||
.map(line => line.slice(3).trim())
|
||||
.filter(p => !p.startsWith('.beadboard') && !p.startsWith('.beads'));
|
||||
} catch {
|
||||
return [];
|
||||
}
|
||||
}
|
||||
|
||||
async function resolveBbPath() {
|
||||
const envRepo = process.env.BB_REPO;
|
||||
|
||||
const tsEntry = path.join(process.cwd(), 'tools', 'bb.ts');
|
||||
try {
|
||||
await fs.access(tsEntry);
|
||||
return { type: 'tsx', path: tsEntry };
|
||||
} catch {}
|
||||
|
||||
if (envRepo) {
|
||||
const p = path.join(envRepo, 'bb.ps1');
|
||||
try {
|
||||
await fs.access(p);
|
||||
return { type: 'powershell', path: p };
|
||||
} catch {}
|
||||
|
||||
const envTs = path.join(envRepo, 'tools', 'bb.ts');
|
||||
try {
|
||||
await fs.access(envTs);
|
||||
return { type: 'tsx', path: envTs };
|
||||
} catch {}
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
async function main() {
|
||||
const { values } = parseArgs({
|
||||
options: {
|
||||
'non-interactive': { type: 'boolean' },
|
||||
adopt: { type: 'string' },
|
||||
register: { type: 'string' },
|
||||
role: { type: 'string' },
|
||||
json: { type: 'boolean' },
|
||||
'project-root': { type: 'string' }
|
||||
}
|
||||
});
|
||||
|
||||
const isNonInteractive = values['non-interactive'];
|
||||
const projectRoot = values['project-root'] || process.cwd();
|
||||
const bbResult = await resolveBbPath();
|
||||
|
||||
if (!bbResult) {
|
||||
error('BB_NOT_FOUND', 'Could not resolve bb.ps1 or tools/bb.ts');
|
||||
}
|
||||
|
||||
let agentId = values.adopt || values.register;
|
||||
let mode = values.adopt ? 'adopt' : (values.register ? 'register' : 'auto');
|
||||
|
||||
if (mode === 'auto' && isNonInteractive) {
|
||||
error('AMBIGUOUS_SESSION', 'In non-interactive mode, --adopt or --register is required.');
|
||||
}
|
||||
|
||||
if (mode === 'adopt') {
|
||||
const changes = await getUncommittedChanges(projectRoot);
|
||||
if (changes.length === 0 && isNonInteractive) {
|
||||
error('ADOPTION_REJECTED', 'No evidence (uncommitted changes) to support identity adoption.');
|
||||
}
|
||||
}
|
||||
|
||||
try {
|
||||
// Compose environment fingerprint (Rig)
|
||||
const rigId = `${os.platform()}-${os.arch()}-${os.hostname()}`;
|
||||
|
||||
const env = { ...process.env, BD_DB: path.join(projectRoot, '.beads', 'beads.db') };
|
||||
|
||||
if (mode === 'register') {
|
||||
const role = values.role || 'agent';
|
||||
const registerArgs = bbResult.type === 'tsx'
|
||||
? ['tsx', bbResult.path, 'agent', 'register', '--name', agentId, '--role', role, '--rig', rigId, '--json']
|
||||
: ['agent', 'register', '--name', agentId, '--role', role, '--rig', rigId, '--json'];
|
||||
const registerCmd = bbResult.type === 'tsx' ? 'npx' : bbResult.path;
|
||||
execFileSync(registerCmd, registerArgs, { stdio: 'ignore', cwd: projectRoot, env });
|
||||
} else {
|
||||
// Start/Extend the lease to show we are now active
|
||||
const leaseArgs = bbResult.type === 'tsx'
|
||||
? ['tsx', bbResult.path, 'agent', 'activity-lease', '--agent', agentId, '--json']
|
||||
: ['agent', 'activity-lease', '--agent', agentId, '--json'];
|
||||
const leaseCmd = bbResult.type === 'tsx' ? 'npx' : bbResult.path;
|
||||
execFileSync(leaseCmd, leaseArgs, { stdio: 'ignore', cwd: projectRoot, env });
|
||||
}
|
||||
|
||||
log({
|
||||
ok: true,
|
||||
agent_id: agentId,
|
||||
mode,
|
||||
lease: { status: 'active', note: 'Activity lease started. Liveness maintained via real work.' },
|
||||
timestamp: new Date().toISOString()
|
||||
});
|
||||
|
||||
} catch (err) {
|
||||
error('INIT_FAILED', err.message);
|
||||
}
|
||||
}
|
||||
|
||||
#!/usr/bin/env node
|
||||
|
||||
/**
|
||||
* bb-init.mjs - Agent Session Bootstrapper (Lease-Based)
|
||||
*
|
||||
* Part of Operative Protocol v1 (bb-u6f.6.3)
|
||||
*
|
||||
* Responsibility:
|
||||
* 1. Resolve bb.ps1 path.
|
||||
* 2. Identify agent (adopt or register).
|
||||
* 3. Start the initial activity lease.
|
||||
*
|
||||
* Note: No background processes are spawned. Liveness is maintained
|
||||
* via passive side-effects of CLI commands (Activity-based model).
|
||||
*/
|
||||
|
||||
import { parseArgs } from 'node:util';
|
||||
import fs from 'node:fs/promises';
|
||||
import path from 'node:path';
|
||||
import os from 'node:os';
|
||||
import { execSync, execFileSync } from 'node:child_process';
|
||||
|
||||
function log(obj) {
|
||||
process.stdout.write(`${JSON.stringify(obj, null, 2)}
|
||||
`);
|
||||
}
|
||||
|
||||
function error(code, message) {
|
||||
log({ ok: false, error: { code, message } });
|
||||
process.exit(1);
|
||||
}
|
||||
|
||||
async function getUncommittedChanges(projectRoot) {
|
||||
try {
|
||||
const out = execSync('git status --porcelain', { cwd: projectRoot, encoding: 'utf8' });
|
||||
return out.split('\n')
|
||||
.filter(Boolean)
|
||||
.map(line => line.slice(3).trim())
|
||||
.filter(p => !p.startsWith('.beadboard') && !p.startsWith('.beads'));
|
||||
} catch {
|
||||
return [];
|
||||
}
|
||||
}
|
||||
|
||||
async function resolveBbPath() {
|
||||
const envRepo = process.env.BB_REPO;
|
||||
|
||||
const tsEntry = path.join(process.cwd(), 'tools', 'bb.ts');
|
||||
try {
|
||||
await fs.access(tsEntry);
|
||||
return { type: 'tsx', path: tsEntry };
|
||||
} catch {}
|
||||
|
||||
if (envRepo) {
|
||||
const p = path.join(envRepo, 'bb.ps1');
|
||||
try {
|
||||
await fs.access(p);
|
||||
return { type: 'powershell', path: p };
|
||||
} catch {}
|
||||
|
||||
const envTs = path.join(envRepo, 'tools', 'bb.ts');
|
||||
try {
|
||||
await fs.access(envTs);
|
||||
return { type: 'tsx', path: envTs };
|
||||
} catch {}
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
async function main() {
|
||||
const { values } = parseArgs({
|
||||
options: {
|
||||
'non-interactive': { type: 'boolean' },
|
||||
adopt: { type: 'string' },
|
||||
register: { type: 'string' },
|
||||
role: { type: 'string' },
|
||||
json: { type: 'boolean' },
|
||||
'project-root': { type: 'string' }
|
||||
}
|
||||
});
|
||||
|
||||
const isNonInteractive = values['non-interactive'];
|
||||
const projectRoot = values['project-root'] || process.cwd();
|
||||
const bbResult = await resolveBbPath();
|
||||
|
||||
if (!bbResult) {
|
||||
error('BB_NOT_FOUND', 'Could not resolve bb.ps1 or tools/bb.ts');
|
||||
}
|
||||
|
||||
let agentId = values.adopt || values.register;
|
||||
let mode = values.adopt ? 'adopt' : (values.register ? 'register' : 'auto');
|
||||
|
||||
if (mode === 'auto' && isNonInteractive) {
|
||||
error('AMBIGUOUS_SESSION', 'In non-interactive mode, --adopt or --register is required.');
|
||||
}
|
||||
|
||||
if (mode === 'adopt') {
|
||||
const changes = await getUncommittedChanges(projectRoot);
|
||||
if (changes.length === 0 && isNonInteractive) {
|
||||
error('ADOPTION_REJECTED', 'No evidence (uncommitted changes) to support identity adoption.');
|
||||
}
|
||||
}
|
||||
|
||||
try {
|
||||
// Compose environment fingerprint (Rig)
|
||||
const rigId = `${os.platform()}-${os.arch()}-${os.hostname()}`;
|
||||
|
||||
const env = { ...process.env, BD_DB: path.join(projectRoot, '.beads', 'beads.db') };
|
||||
|
||||
if (mode === 'register') {
|
||||
const role = values.role || 'agent';
|
||||
const registerArgs = bbResult.type === 'tsx'
|
||||
? ['tsx', bbResult.path, 'agent', 'register', '--name', agentId, '--role', role, '--rig', rigId, '--json']
|
||||
: ['agent', 'register', '--name', agentId, '--role', role, '--rig', rigId, '--json'];
|
||||
const registerCmd = bbResult.type === 'tsx' ? 'npx' : bbResult.path;
|
||||
execFileSync(registerCmd, registerArgs, { stdio: 'ignore', cwd: projectRoot, env });
|
||||
} else {
|
||||
// Start/Extend the lease to show we are now active
|
||||
const leaseArgs = bbResult.type === 'tsx'
|
||||
? ['tsx', bbResult.path, 'agent', 'activity-lease', '--agent', agentId, '--json']
|
||||
: ['agent', 'activity-lease', '--agent', agentId, '--json'];
|
||||
const leaseCmd = bbResult.type === 'tsx' ? 'npx' : bbResult.path;
|
||||
execFileSync(leaseCmd, leaseArgs, { stdio: 'ignore', cwd: projectRoot, env });
|
||||
}
|
||||
|
||||
log({
|
||||
ok: true,
|
||||
agent_id: agentId,
|
||||
mode,
|
||||
lease: { status: 'active', note: 'Activity lease started. Liveness maintained via real work.' },
|
||||
timestamp: new Date().toISOString()
|
||||
});
|
||||
|
||||
} catch (err) {
|
||||
error('INIT_FAILED', err.message);
|
||||
}
|
||||
}
|
||||
|
||||
main();
|
||||
|
|
@ -1,41 +1,41 @@
|
|||
import { chromium } from 'playwright';
|
||||
import path from 'node:path';
|
||||
import fs from 'node:fs/promises';
|
||||
|
||||
const url = process.argv[2];
|
||||
if (!url) {
|
||||
console.error('Usage: node scripts/capture-graph.mjs <url>');
|
||||
process.exit(1);
|
||||
}
|
||||
|
||||
const outputDir = path.join('artifacts');
|
||||
await fs.mkdir(outputDir, { recursive: true });
|
||||
|
||||
const browser = await chromium.launch({ headless: true });
|
||||
|
||||
async function screenshot(name, viewport, prepare) {
|
||||
const page = await browser.newPage({ viewport });
|
||||
await page.goto(url, { waitUntil: 'networkidle' });
|
||||
await page.waitForTimeout(1000);
|
||||
if (prepare) {
|
||||
await prepare(page);
|
||||
await page.waitForTimeout(450);
|
||||
}
|
||||
await page.screenshot({
|
||||
path: path.join(outputDir, name),
|
||||
fullPage: true,
|
||||
});
|
||||
await page.close();
|
||||
}
|
||||
|
||||
await screenshot('graph-next-1440.png', { width: 1440, height: 900 });
|
||||
await screenshot('graph-next-768.png', { width: 768, height: 1024 });
|
||||
await screenshot('graph-next-390-overview.png', { width: 390, height: 844 });
|
||||
await screenshot('graph-next-390-flow.png', { width: 390, height: 844 }, async (page) => {
|
||||
const flowButton = page.getByRole('button', { name: 'Switch to Graph' });
|
||||
if (await flowButton.count()) {
|
||||
await flowButton.first().click();
|
||||
}
|
||||
});
|
||||
|
||||
await browser.close();
|
||||
import { chromium } from 'playwright';
|
||||
import path from 'node:path';
|
||||
import fs from 'node:fs/promises';
|
||||
|
||||
const url = process.argv[2];
|
||||
if (!url) {
|
||||
console.error('Usage: node scripts/capture-graph.mjs <url>');
|
||||
process.exit(1);
|
||||
}
|
||||
|
||||
const outputDir = path.join('artifacts');
|
||||
await fs.mkdir(outputDir, { recursive: true });
|
||||
|
||||
const browser = await chromium.launch({ headless: true });
|
||||
|
||||
async function screenshot(name, viewport, prepare) {
|
||||
const page = await browser.newPage({ viewport });
|
||||
await page.goto(url, { waitUntil: 'networkidle' });
|
||||
await page.waitForTimeout(1000);
|
||||
if (prepare) {
|
||||
await prepare(page);
|
||||
await page.waitForTimeout(450);
|
||||
}
|
||||
await page.screenshot({
|
||||
path: path.join(outputDir, name),
|
||||
fullPage: true,
|
||||
});
|
||||
await page.close();
|
||||
}
|
||||
|
||||
await screenshot('graph-next-1440.png', { width: 1440, height: 900 });
|
||||
await screenshot('graph-next-768.png', { width: 768, height: 1024 });
|
||||
await screenshot('graph-next-390-overview.png', { width: 390, height: 844 });
|
||||
await screenshot('graph-next-390-flow.png', { width: 390, height: 844 }, async (page) => {
|
||||
const flowButton = page.getByRole('button', { name: 'Switch to Graph' });
|
||||
if (await flowButton.count()) {
|
||||
await flowButton.first().click();
|
||||
}
|
||||
});
|
||||
|
||||
await browser.close();
|
||||
|
|
|
|||
|
|
@ -1,31 +1,31 @@
|
|||
import { chromium } from 'playwright';
|
||||
import path from 'node:path';
|
||||
|
||||
const url = process.argv[2];
|
||||
const mode = process.argv[3];
|
||||
|
||||
if (!url || !mode) {
|
||||
console.error('Usage: node scripts/capture-kanban.mjs <url> <before|after>');
|
||||
process.exit(1);
|
||||
}
|
||||
|
||||
const shots = [
|
||||
{ name: 'mobile', width: 390, height: 844 },
|
||||
{ name: 'tablet', width: 768, height: 1024 },
|
||||
{ name: 'desktop', width: 1440, height: 900 },
|
||||
];
|
||||
|
||||
const browser = await chromium.launch({ headless: true });
|
||||
|
||||
for (const shot of shots) {
|
||||
const page = await browser.newPage({ viewport: { width: shot.width, height: shot.height } });
|
||||
await page.goto(url, { waitUntil: 'domcontentloaded' });
|
||||
await page.waitForTimeout(700);
|
||||
await page.screenshot({
|
||||
path: path.join('artifacts', `kanban-${shot.name}-${mode}.png`),
|
||||
fullPage: true,
|
||||
});
|
||||
await page.close();
|
||||
}
|
||||
|
||||
await browser.close();
|
||||
import { chromium } from 'playwright';
|
||||
import path from 'node:path';
|
||||
|
||||
const url = process.argv[2];
|
||||
const mode = process.argv[3];
|
||||
|
||||
if (!url || !mode) {
|
||||
console.error('Usage: node scripts/capture-kanban.mjs <url> <before|after>');
|
||||
process.exit(1);
|
||||
}
|
||||
|
||||
const shots = [
|
||||
{ name: 'mobile', width: 390, height: 844 },
|
||||
{ name: 'tablet', width: 768, height: 1024 },
|
||||
{ name: 'desktop', width: 1440, height: 900 },
|
||||
];
|
||||
|
||||
const browser = await chromium.launch({ headless: true });
|
||||
|
||||
for (const shot of shots) {
|
||||
const page = await browser.newPage({ viewport: { width: shot.width, height: shot.height } });
|
||||
await page.goto(url, { waitUntil: 'domcontentloaded' });
|
||||
await page.waitForTimeout(700);
|
||||
await page.screenshot({
|
||||
path: path.join('artifacts', `kanban-${shot.name}-${mode}.png`),
|
||||
fullPage: true,
|
||||
});
|
||||
await page.close();
|
||||
}
|
||||
|
||||
await browser.close();
|
||||
|
|
|
|||
|
|
@ -1,78 +1,158 @@
|
|||
---
|
||||
name: beadboard-driver
|
||||
description: Drive BeadBoard agent workflows with strict Operative Protocol v1 compliance. Use when handling bead lifecycle work that combines bd status commands with bb agent coordination (register/adopt, activity-lease, reserve/release, send/ack), especially in multi-agent sessions requiring silent observability and collision avoidance.
|
||||
description: Complete operating manual for agents running work in external repos while humans orchestrate from BeadBoard.
|
||||
---
|
||||
|
||||
# Beadboard Driver (Operative Protocol v1)
|
||||
# BeadBoard Driver
|
||||
|
||||
## Overview
|
||||
BeadBoard is for teams that want autonomous agents without losing control of the work.
|
||||
|
||||
Use this skill to run repeatable `bd` + `bb` workflows under the **Activity Lease** (Parking Permit) model. Resolve `bb` safely, bootstrap via `bb-init`, coordinate via traceable incursions, and maintain liveness through real work.
|
||||
Most agent setups break down the same way: work happens quickly, but visibility collapses, handoffs get fuzzy, and “done” starts meaning “probably done.” This skill fixes that operating problem.
|
||||
|
||||
## Core Workflow
|
||||
With BeadBoard Driver, agents execute inside the target project repo, while humans orchestrate from BeadBoard as the control plane: assign, redirect, intervene, verify, and keep a durable coordination record.
|
||||
|
||||
BeadBoard project:
|
||||
|
||||
- GitHub: `https://github.com/zenchantlive/beadboard`
|
||||
|
||||
## What This Changes
|
||||
|
||||
- Work becomes observable, not performative.
|
||||
- Ownership stays explicit at bead level.
|
||||
- Handoffs and blockers become machine-readable events.
|
||||
- Completion claims require evidence, not confidence.
|
||||
- Multi-agent execution stays coordinated instead of chaotic.
|
||||
|
||||
## Operating Reality
|
||||
|
||||
- Agents usually run in a non-BeadBoard target repo.
|
||||
- The user controls project scope from BeadBoard UI.
|
||||
- Agents execute the current repo context they were assigned.
|
||||
- `bd` remains source of truth for task/memory state.
|
||||
|
||||
## Start Here
|
||||
|
||||
Run this quick confidence check before you start a session:
|
||||
|
||||
1. **Bootstrap & Handshake**:
|
||||
Run `bb-init` to resolve paths and identify yourself. Use `--adopt` if resuming a task with uncommitted changes.
|
||||
```bash
|
||||
node scripts/bb-init.mjs --register <agent-name> --role <role> --json
|
||||
# OR
|
||||
node scripts/bb-init.mjs --adopt <prior-agent-id> --non-interactive --json
|
||||
bd --version
|
||||
node skills/beadboard-driver/scripts/session-preflight.mjs
|
||||
node skills/beadboard-driver/scripts/resolve-bb.mjs
|
||||
```
|
||||
|
||||
2. **Claim Territory**:
|
||||
Reserve your work surface before making edits to prevent silent collisions.
|
||||
If discovery fails, install/repair from:
|
||||
|
||||
- `https://github.com/zenchantlive/beadboard`
|
||||
|
||||
## Session Runbook
|
||||
|
||||
1. Diagnose environment.
|
||||
2. Confirm preflight/discovery.
|
||||
3. Establish session identity.
|
||||
4. Read memory + ready work.
|
||||
5. Claim bead with assignee.
|
||||
6. Execute and coordinate via events.
|
||||
7. Run verification gates.
|
||||
8. Publish evidence and close.
|
||||
9. Perform memory review.
|
||||
|
||||
## Core Commands
|
||||
|
||||
```bash
|
||||
& "$env:BB_REPO\bb.ps1" agent reserve --agent <agent-id> --scope "src/lib/*" --bead <bead-id>
|
||||
bd update <bead-id> --status in_progress --claim
|
||||
# Diagnostics and discovery
|
||||
node skills/beadboard-driver/scripts/diagnose-env.mjs
|
||||
node skills/beadboard-driver/scripts/session-preflight.mjs
|
||||
node skills/beadboard-driver/scripts/resolve-bb.mjs
|
||||
|
||||
# Ensure project context exists in the target repository
|
||||
node skills/beadboard-driver/scripts/ensure-project-context.mjs --project-root <repo>
|
||||
|
||||
# Identity helper
|
||||
node skills/beadboard-driver/scripts/generate-agent-name.mjs
|
||||
|
||||
# Closeout evidence envelope
|
||||
node skills/beadboard-driver/scripts/readiness-report.mjs --checks '<json>' --artifacts '<json>'
|
||||
|
||||
# Safe self-healing (dry-run default)
|
||||
node skills/beadboard-driver/scripts/heal-common-issues.mjs --project-root <repo>
|
||||
node skills/beadboard-driver/scripts/heal-common-issues.mjs --project-root <repo> --apply --fix-git-index-lock
|
||||
```
|
||||
|
||||
3. **Physical Change -> Contextual Lookup**:
|
||||
If you encounter uncommitted changes in a file you didn't personally edit: **STOP and Query**.
|
||||
## Bead Lifecycle (Minimum Contract)
|
||||
|
||||
```bash
|
||||
& "$env:BB_REPO\bb.ps1" agent status --agent <agent-id>
|
||||
& "$env:BB_REPO\bb.ps1" agent inbox --agent <agent-id> --state unread
|
||||
# Read context
|
||||
bd show <memory-or-task-id>
|
||||
bd ready
|
||||
|
||||
# Claim explicitly
|
||||
bd update <bead-id> --status in_progress --assignee <agent-bead-id>
|
||||
|
||||
# Record evidence and close
|
||||
bd update <bead-id> --notes "<commands + outputs>"
|
||||
bd close <bead-id> --reason "<completed outcome>"
|
||||
```
|
||||
|
||||
4. **Explain Deltas**:
|
||||
Send high-fidelity signals when you hit milestones or incursions.
|
||||
## Use-The-Right-Doc Map
|
||||
|
||||
### `references/memory-system.md`
|
||||
Use when you need to query/apply/create canonical memory, validate provenance, or decide whether a lesson belongs in memory vs task notes.
|
||||
|
||||
### `references/coord-events-sessions-ack.md`
|
||||
Use when you’re coordinating handoffs/blockers/incursions and need correct inbox/read/ack behavior.
|
||||
|
||||
### `references/session-lifecycle.md`
|
||||
Use for end-to-end session choreography and closeout hygiene.
|
||||
|
||||
### `references/archetypes-templates-swarms.md`
|
||||
Use when choosing team shape, role boundaries, and swarm ownership patterns.
|
||||
|
||||
### `references/missions-realtime.md`
|
||||
Use when assigning work and troubleshooting stale/live-update behavior from mission/event flow.
|
||||
|
||||
### `references/command-matrix.md`
|
||||
Use when you need exact command surfaces and argument shape.
|
||||
|
||||
### `references/failure-modes.md`
|
||||
Use when preflight/discovery/coordination fails and you need deterministic recovery.
|
||||
|
||||
## Project Context Template
|
||||
|
||||
The skill ships a source template file: `project.template.md`.
|
||||
|
||||
Runtime contract:
|
||||
|
||||
- Agents should use `<target-repo>/project.md` for project context.
|
||||
- If `<target-repo>/project.md` is missing, create it from `project.template.md`.
|
||||
- If `<target-repo>/project.md` already exists, do not overwrite it.
|
||||
|
||||
Helper command:
|
||||
|
||||
```bash
|
||||
& "$env:BB_REPO\bb.ps1" agent send --from <agent-id> --to <peer> --bead <bead-id> --category INFO --subject "Patched parser.ts for UI sync" --body "..."
|
||||
node skills/beadboard-driver/scripts/ensure-project-context.mjs --project-root <repo>
|
||||
```
|
||||
|
||||
5. **Liveness Maintenance**:
|
||||
Liveness is **Passive**. Any `bb agent` command extends your lease. Use `activity-lease` if you haven't run a command in > 10 minutes.
|
||||
## Tests
|
||||
|
||||
Skill-local contracts:
|
||||
|
||||
- `skills/beadboard-driver/tests/run-tests.mjs`
|
||||
- `skills/beadboard-driver/tests/*.contract.test.mjs`
|
||||
|
||||
Repo-level coverage:
|
||||
|
||||
- `tests/skills/beadboard-driver/*.test.ts`
|
||||
|
||||
## Verification Gates
|
||||
|
||||
```bash
|
||||
& "$env:BB_REPO\bb.ps1" agent activity-lease --agent <agent-id> --json
|
||||
npm run typecheck
|
||||
npm run lint
|
||||
npm run test
|
||||
```
|
||||
|
||||
6. **Closeout Evidence**:
|
||||
```bash
|
||||
node skills/beadboard-driver/scripts/readiness-report.mjs --checks '[{"name":"typecheck","ok":true}]' --artifacts '[{"path":"artifacts/final.png","required":true}]'
|
||||
bd close <bead-id> --reason "..."
|
||||
```
|
||||
If failures are outside your scope, cite exact failing files/tests and continue transparently.
|
||||
|
||||
## Identity & Adoption Policy
|
||||
## Bottom Line
|
||||
|
||||
- **Uniqueness**: Create one unique `adjective-noun` identity per session unless adopting.
|
||||
- **Adoption Guardrails**: Adoption is ONLY allowed if uncommitted changes exist in the scope OR you own an `in_progress` bead.
|
||||
- **Audit**: Every adoption triggers a `RESUME` event in the audit feed.
|
||||
|
||||
## Activity Lease (Parking Permit)
|
||||
|
||||
- **Active (0-15m)**: Lease is valid. You are protected from takeover.
|
||||
- **Stale (15-30m)**: Lease expired. Others can takeover with `--takeover-stale`.
|
||||
- **Evicted (30m+)**: Lease dead. Others should takeover and archive your reservation.
|
||||
- **Idle (60m+)**: Ghost state. You are considered gone.
|
||||
|
||||
## Red Flags - STOP and Start Over
|
||||
|
||||
- **Silent Incursion**: Editing a reserved file without sending an `INFO` message.
|
||||
- **Identity Reuse**: Reusing an agent ID from a previous session without an adoption handshake.
|
||||
- **Mocking**: Implementing mocks instead of coordinating with the domain owner.
|
||||
- **Terminal Pop-ups**: Spawning background workers that disrupt the user's desktop.
|
||||
|
||||
## References
|
||||
|
||||
- Command and argument contracts: `references/command-matrix.md`
|
||||
- End-to-end session choreography: `references/session-lifecycle.md`
|
||||
- Protocol Specification: `docs/protocols/operative-protocol-v1.md`
|
||||
This skill is the bridge between fast autonomous execution and human operator trust. Use it when speed matters, but coordination quality matters more.
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
interface:
|
||||
display_name: "Beadboard Driver"
|
||||
short_description: "Safe bd+bb agent workflow orchestration"
|
||||
default_prompt: "Use Beadboard Driver to resolve bb path, register a unique session agent, coordinate via bb agent commands, and produce verification-backed closeout notes."
|
||||
short_description: "BeadBoard control-plane workflow for agents in external repos"
|
||||
default_prompt: "Use BeadBoard Driver v4 to run evidence-backed bd workflow in the target repo while the user orchestrates via BeadBoard UI; do not mutate project scope, use coordination events/inbox acks, and publish verification-backed closeout notes."
|
||||
|
|
|
|||
85
skills/beadboard-driver/project.template.md
Normal file
85
skills/beadboard-driver/project.template.md
Normal file
|
|
@ -0,0 +1,85 @@
|
|||
# Project Driver Template
|
||||
|
||||
Use this file to define project-specific operating notes for agents using the BeadBoard Driver skill.
|
||||
|
||||
## Project Identity
|
||||
|
||||
- Project name:
|
||||
- Repository root:
|
||||
- Primary language/runtime:
|
||||
- Primary package manager:
|
||||
|
||||
## BeadBoard Relationship
|
||||
|
||||
- BeadBoard host/UI location:
|
||||
- Project registration identifier (if used):
|
||||
- Notes about how this project appears in BeadBoard UI:
|
||||
|
||||
## Scope and Authority
|
||||
|
||||
- User controls project scope selection in BeadBoard UI.
|
||||
- Agents do not change scope.
|
||||
- Agent execution context in this repo:
|
||||
|
||||
## Command Baseline
|
||||
|
||||
- Install command:
|
||||
- Build command:
|
||||
- Typecheck command:
|
||||
- Lint command:
|
||||
- Test command:
|
||||
- Smoke command (optional):
|
||||
|
||||
## Verification Policy Overrides
|
||||
|
||||
- Required gates for this project:
|
||||
- Known slow gates and timeout guidance:
|
||||
- Evidence format expected in bead notes:
|
||||
|
||||
## Environment Constraints
|
||||
|
||||
- OS/platform expectations:
|
||||
- Required environment variables:
|
||||
- Secrets handling guidance:
|
||||
- Known path/shell quirks:
|
||||
|
||||
## Known Workarounds
|
||||
|
||||
Document only stable, repeatable workarounds.
|
||||
|
||||
1. Trigger:
|
||||
- Symptom:
|
||||
- Workaround:
|
||||
- Verification:
|
||||
- Owner:
|
||||
|
||||
2. Trigger:
|
||||
- Symptom:
|
||||
- Workaround:
|
||||
- Verification:
|
||||
- Owner:
|
||||
|
||||
## Coordination Defaults
|
||||
|
||||
- Default role/archetype mapping used by this project:
|
||||
- Default handoff style:
|
||||
- Blocker escalation policy:
|
||||
- Ack expectations for blocker/handoff messages:
|
||||
|
||||
## Safety Guardrails
|
||||
|
||||
- Forbidden commands/actions for this repo:
|
||||
- Files/paths requiring explicit reservation before edit:
|
||||
- External systems that require human approval:
|
||||
|
||||
## Session Closeout Checklist
|
||||
|
||||
- [ ] Bead status/assignee updated
|
||||
- [ ] Verification commands executed and recorded
|
||||
- [ ] Artifacts attached/linked
|
||||
- [ ] Memory review performed
|
||||
- [ ] Follow-up beads created (if needed)
|
||||
|
||||
## Change Log
|
||||
|
||||
- YYYY-MM-DD: Initial project template completed.
|
||||
Some files were not shown because too many files have changed in this diff Show more
Loading…
Add table
Add a link
Reference in a new issue