| name | styling-ui |
| description | Enforces design system using Tailwind CSS v4 and shadcn/ui.
Use for: all styling, theming, responsive design, animations.
DO NOT use for: component logic (use developing-nextjs), data fetching (use managing-convex).
|
Styling UI
Tailwind CSS v4 + shadcn/ui design system. Semantic tokens are mandatory.
Source of Truth
- Globals + Tokens:
app/globals.css
- UI Primitives:
components/ui/ (shadcn/ui)
- Class Merger:
import { cn } from "@/lib/utils"
Mandatory Standards
| Requirement | Correct | Incorrect |
|---|
| Class merging | cn("base", className) | className={...} only |
| Colors | bg-background, text-foreground | bg-white, text-black |
| Spacing | gap-4, p-6 | gap-[18px], padding: 20px |
| Fonts | font-sans, font-brand, font-mono | font-family: Arial |
| Responsive | md:flex, lg:grid-cols-3 | Fixed widths |
Font System
| Token | Font | Usage |
|---|
font-sans | Geist | Default body/UI text |
font-brand | Bricolage Grotesque | Headings, brand moments |
font-mono | Geist Mono | Code, numbers, IDs |
Color Tokens (oklch-based)
Use semantic tokens exclusively:
--background
--foreground
--card
--muted
--muted-foreground
--primary
--accent
--destructive
--border
Animation Utilities
| Class | Effect | Duration |
|---|
animate-fade-in | Fade + slide up | 0.6s |
animate-scale-in | Pop in | 0.3s |
animate-shimmer | Loading shimmer | 2s loop |
animate-float | Levitation | 6s loop |
animate-pulse-glow | Attention glow | 3s loop |
animate-lightbulb-glow | Subtle glow | 1.5s loop |
animate-loading-bar | Progress bar | 1.5s loop |
Custom Utilities
| Class | Purpose |
|---|
glass-effect | Frosted glass panels (blur + transparency) |
glass-effect-home | Dark glass for landing page |
container | Centered content with responsive padding |
Workflow: Style Component
- [ ] 1. Import `cn` from `@/lib/utils`
- [ ] 2. Use semantic HTML (`<main>`, `<section>`, `<article>`)
- [ ] 3. Apply `font-sans` (default) or `font-brand` for headings
- [ ] 4. Use tokens: `bg-card`, `text-foreground`, `border-border`
- [ ] 5. Layout with `flex`/`grid` and `gap-*`
- [ ] 6. Add responsive: mobile-first, then `md:`, `lg:` overrides
- [ ] 7. Add interactivity: `hover:bg-muted/50 transition-colors cursor-pointer`
- [ ] 8. Polish: animations, `glass-effect` where appropriate
Common Patterns
Card Component
<div className={cn(
"rounded-lg border bg-card p-6 shadow-sm",
"hover:shadow-md transition-shadow",
className
)}>
{children}
</div>
Interactive Button
<button className={cn(
"px-4 py-2 rounded-md font-medium",
"bg-primary text-primary-foreground",
"hover:bg-primary/90 transition-colors",
"focus-visible:ring-2 focus-visible:ring-ring"
)}>
Click Me
</button>
Responsive Grid
<div className="grid grid-cols-1 gap-4 md:grid-cols-2 lg:grid-cols-3">
{items.map(item => <Card key={item.id} />)}
</div>
Glass Panel
<div className="glass-effect rounded-xl p-6">
{}
</div>
Breakpoints
| Token | Width | Target |
|---|
xs | 480px | Mobile landscape |
sm | 640px | Large mobile |
md | 768px | Tablet |
lg | 1024px | Laptop |
xl | 1280px | Desktop |
2xl | 1536px | Large desktop |
3xl | 2000px | 1440p monitors |
4xl | 2400px | 2K monitors |
5xl | 3600px | 4K monitors |
Guardrails
- Never use hardcoded colors (
#fff, rgb(...), bg-gray-100)
- Never use inline styles (
style={{ padding: 20 }})
- Never create custom CSS files — use
globals.css utilities only
- Always use
cn() for className props to enable overrides
- Always test mobile-first, then add
md: / lg: variants
Output Format
## Summary
Styled [component] with [pattern].
## Tokens Used
- Colors: `bg-card`, `text-foreground`
- Spacing: `p-4`, `gap-2`
- Animation: `animate-fade-in`
## Responsive
- Mobile: single column
- `md:`: 2 columns
- `lg:`: 3 columns
## Verification
- Dark mode tested ✅
- Mobile tested ✅