---
name: ui
description: "Use when building or editing frontend UI components, layouts, styling, design system usage, colors, dark mode, or icons."
---
Source Cursor rule: `.cursor/rules/ui.mdc`.
Original Cursor alwaysApply: `true`.
# UI Components
## Design System Priority
1. **First choice:** `@trycompai/design-system`
2. **Fallback:** `@trycompai/ui` only if DS doesn't have the component
```tsx
// ✅ Design system
import { Button, Card, Input, Sheet, Badge } from '@trycompai/design-system';
import { Add, Close, ArrowRight } from '@trycompai/design-system/icons';
// ❌ Don't use when DS has it
import { Button } from '@trycompai/ui/button';
import { Plus } from 'lucide-react';
```
## No className on DS Components
DS components don't accept `className`. Use variants and props only.
```tsx
// ✅ Use variants
}>Continue
Active
// ❌ TypeScript will error
```
## Layout with Wrapper Divs
For layout concerns, wrap DS components:
```tsx
// ✅ Wrapper for width
// ✅ Use Stack for spacing
```
## Componentize Repeated Patterns
If a pattern appears 2+ times, extract it:
```tsx
// Repeated? Make a component
Active
// → Create
```
## Extension Strategy
When you need new styling:
1. **Check existing variants** - component may already support it
2. **Add a variant** to the component's `cva` definition
3. **Create a new component** if it's a genuinely new pattern
```tsx
// Adding a variant
const badgeVariants = cva("...", {
variants: {
variant: {
// existing...
counter: "bg-muted text-muted-foreground tabular-nums font-mono",
},
},
});
```
## Semantic Colors
Use CSS variables, not hardcoded colors:
```tsx
// ✅ Semantic tokens
// ❌ Hardcoded
```
## Dark Mode
Always support both modes:
```tsx
// Status colors with dark variants
```
## Icons
Carbon icons from DS, not lucide:
```tsx
// ✅ Design system icons with size prop
import { Add, Close, ChevronDown } from '@trycompai/design-system/icons';
// ❌ Don't use lucide
import { Plus, X } from 'lucide-react';
```
## Anti-Patterns
```tsx
// ❌ Never do these