name: potato:branding-components description: Use when creating or styling UI components in the web-react application
Potato Cannon UI Components & Branding
This skill documents the UI components, theme variables, and styling conventions for the web-react application. Use this as a reference when creating or modifying UI elements.
Theme Variables
All colors are defined in web-react/src/index.css under the @theme block:
Background Colors
| Variable | Value | Usage |
|---|---|---|
bg-primary |
#0d1117 |
Main app background |
bg-secondary |
#161b22 |
Cards, panels, modals |
bg-tertiary |
#21262d |
Input backgrounds, elevated surfaces |
bg-hover |
#30363d |
Hover states |
Text Colors
| Variable | Value | Usage |
|---|---|---|
text-primary |
#e6edf3 |
Primary text, headings |
text-secondary |
#8b949e |
Secondary text, labels |
text-muted |
#6e7681 |
Muted text, placeholders |
Accent Colors
| Variable | Value | Usage |
|---|---|---|
accent |
#58a6ff |
Links, primary actions |
accent-green |
#3fb950 |
Success states |
accent-yellow |
#d29922 |
Warning states, brand color |
accent-red |
#f85149 |
Error states, destructive actions |
accent-purple |
#a371f7 |
Decorative accents |
Border & Other
| Variable | Value | Usage |
|---|---|---|
border |
#30363d |
All borders |
destructive |
#f85149 |
Destructive button backgrounds |
Form Components
Input Component
Location: web-react/src/components/ui/input.tsx
Standard input styling:
import { Input } from "@/components/ui/input"
<Input
placeholder="Enter value"
value={value}
onChange={(e) => setValue(e.target.value)}
/>
Base classes (reference only - use the component):
border-border/50 bg-bg-tertiary/50 rounded-md h-9
focus-visible:border-border focus-visible:ring-border/30 focus-visible:ring-[2px]
placeholder:text-text-muted
Select Component
Location: web-react/src/components/ui/select.tsx
Standard select dropdown:
import {
Select,
SelectContent,
SelectItem,
SelectTrigger,
SelectValue,
} from "@/components/ui/select"
<Select value={value} onValueChange={setValue}>
<SelectTrigger className="w-[180px]">
<SelectValue placeholder="Select option" />
</SelectTrigger>
<SelectContent>
<SelectItem value="option1">Option 1</SelectItem>
<SelectItem value="option2">Option 2</SelectItem>
</SelectContent>
</Select>
Size variants:
- Default:
h-9(36px) - Small:
size="sm"→h-8(32px) - use for table rows
Important: Do NOT add custom background or border classes to Select components. The base component styles match the Input component automatically.
Textarea Component
Location: web-react/src/components/ui/textarea.tsx
import { Textarea } from "@/components/ui/textarea"
<Textarea
placeholder="Enter description"
value={value}
onChange={(e) => setValue(e.target.value)}
/>
Button Component
Location: web-react/src/components/ui/button.tsx
import { Button } from "@/components/ui/button"
<Button>Default</Button>
<Button variant="outline">Outline</Button>
<Button variant="ghost">Ghost</Button>
<Button variant="destructive">Destructive</Button>
<Button size="sm">Small</Button>
<Button size="icon">Icon only</Button>
Variants:
default- Primary action, filled backgroundoutline- Secondary action, borderedghost- Tertiary action, no borderdestructive- Dangerous action, red background
Modal/Dialog Component
Location: web-react/src/components/ui/dialog.tsx
See the potato:creating-modals skill for detailed modal patterns.
Basic structure:
import {
Dialog,
DialogContent,
DialogDescription,
DialogFooter,
DialogHeader,
DialogTitle,
} from "@/components/ui/dialog"
<Dialog open={isOpen} onOpenChange={setIsOpen}>
<DialogContent>
<DialogHeader>
<DialogTitle>Title</DialogTitle>
<DialogDescription>Description</DialogDescription>
</DialogHeader>
{/* Content */}
<DialogFooter>
<Button variant="outline" onClick={() => setIsOpen(false)}>Cancel</Button>
<Button onClick={handleSubmit}>Confirm</Button>
</DialogFooter>
</DialogContent>
</Dialog>
Badge Component
Location: web-react/src/components/ui/badge.tsx
import { Badge } from "@/components/ui/badge"
<Badge>Default</Badge>
<Badge variant="outline">Outline</Badge>
<Badge variant="secondary">Secondary</Badge>
<Badge variant="destructive">Destructive</Badge>
Focus States
All interactive elements should use consistent focus styling:
focus-visible:border-border focus-visible:ring-border/30 focus-visible:ring-[2px]
This provides:
- Border color change to
border(fromborder/50) - 2px ring with 30% opacity border color
- Visible only on keyboard focus (not mouse click)
Hover States
Use bg-bg-hover for hover backgrounds:
className="hover:bg-bg-hover"
For text hover:
className="hover:text-text-primary"
Common Patterns
Card with hover effect
<div className="bg-bg-secondary border border-border rounded-lg p-4 hover:bg-bg-hover transition-colors cursor-pointer">
{/* content */}
</div>
Muted label with value
<div className="space-y-1">
<span className="text-sm text-text-muted">Label</span>
<p className="text-text-primary">Value</p>
</div>
Icon + text row
<div className="flex items-center gap-2 text-text-secondary">
<Icon className="h-4 w-4" />
<span>Text</span>
</div>
Checklist
When creating UI components:
- Use theme variables from this document (not hardcoded colors)
- Use existing UI components from
@/components/ui/ - Apply consistent focus states with
focus-visible:ring-[2px] - Use
bg-bg-hoverfor hover backgrounds - Use
text-text-mutedfor placeholder text - Use
border-borderfor all borders - Test in dark mode (the app is dark-only)
- Verify keyboard navigation works
- Check component looks correct at different sizes
Anti-Patterns
DO NOT:
- Use
bg-popover,text-popover-foreground,bg-accent,text-accent-foreground- use our theme variables - Add custom
bg-bg-secondary border-borderto Select components - base styles handle this - Use
ring-ringorborder-ring- usering-borderandborder-border - Create new color values - use existing theme variables
- Override base component styles unless absolutely necessary