React components for the AI Ranch dashboard.
components/
├── ranch/ # Ranch-specific components
│ ├── dashboard.tsx # Main dashboard layout
│ ├── evolution-panel.tsx
│ ├── species-panel.tsx
│ └── task-panel.tsx
│
└── ui/ # Reusable UI primitives
├── badge.tsx
├── button.tsx
├── card.tsx
├── input.tsx
├── progress.tsx
├── scroll-area.tsx
├── tabs.tsx
└── textarea.tsx
Domain-specific components for the AI Ranch system:
| Component | Purpose |
|---|---|
Dashboard |
Main layout with metrics bar and tabs |
SpeciesPanel |
View and manage species registry |
TaskPanel |
Create and monitor tasks |
EvolutionPanel |
Night School evolution control |
Reusable primitives based on shadcn/ui (Radix + Tailwind):
| Component | Purpose |
|---|---|
Badge |
Status indicators and labels |
Button |
Interactive buttons |
Card |
Content containers |
Input |
Single-line text input |
Textarea |
Multi-line text input |
Progress |
Progress bars |
Tabs |
Tabbed navigation |
ScrollArea |
Scrollable containers |
Components use CSS variables for theming:
/* Light mode */
--background: 0 0% 100%;
--foreground: 222.2 84% 4.9%;
--primary: 222.2 47.4% 11.2%;
--muted: 210 40% 96.1%;
--accent: 210 40% 96.1%;
--border: 214.3 31.8% 91.4%;All components are mobile-first:
// Responsive grid example
<div className="grid gap-4 md:grid-cols-3">
{/* Mobile: 1 col, Tablet+: 3 cols */}
</div>Dark mode is handled via next-themes:
<ThemeProvider
attribute="class"
defaultTheme="system"
enableSystem
>
{children}
</ThemeProvider>All interactive components use 'use client':
'use client';
import { useState } from 'react';
// ... component codeUse TypeScript interfaces for props:
interface SpeciesPanelProps {
initialSpecies?: Species[];
onSpeciesSelect?: (species: Species) => void;
}
export function SpeciesPanel({ initialSpecies, onSpeciesSelect }: SpeciesPanelProps) {
// ...
}Use Tailwind utility classes:
<div className="flex items-center gap-2 p-4 bg-muted rounded-lg">
<Icon className="h-5 w-5 text-primary" />
<span className="font-medium">Content</span>
</div>Use React hooks for local state:
const [species, setSpecies] = useState<Species[]>([]);
const [loading, setLoading] = useState(true);Components fetch data from the API:
useEffect(() => {
const fetchData = async () => {
const response = await fetch('/api/ranch/species');
const data = await response.json();
if (data.success) {
setSpecies(data.data);
}
};
fetchData();
const interval = setInterval(fetchData, 5000);
return () => clearInterval(interval);
}, []);