Flat Design, No Outlines
We avoid heavy borders and outlines in favor of more subtle, modern techniques:- Subtle backgrounds — Differentiate elements with slight background color changes
- Elevation through shadows — Use soft, layered shadows for depth
- Negative space — Let elements breathe; whitespace is your friend
- Color fills — Solid, muted colors with proper opacity
Flat design doesn’t mean lifeless. Use shadows, opacity, and subtle color changes to create depth without heavy borders.
Visual Hierarchy
Guide the eye naturally through your component by establishing clear visual hierarchy:1. Size Matters
Important elements should be larger. This is the most fundamental way to establish hierarchy.2. Weight for Emphasis
- Headings — Use font-weight 500-600 (medium to semibold)
- Body text — Use font-weight 400 (regular)
- Labels — Use font-weight 500 for slight emphasis
3. Color for Attention
- Primary actions — Get the accent color
- Secondary actions — Stay muted
- Destructive actions — Use semantic red
4. Spacing for Grouping
Related items stay close, separate concerns stay apart. Spacing is one of the most powerful tools for creating visual hierarchy.Spacing & Padding
Be generous but intentional with space. Proper spacing makes interfaces feel premium and easy to use.Touch Targets
Minimum 44x44px for interactive elements, following Apple’s accessibility recommendations.Padding Scale
Stick to the Tailwind scale for consistency:p-3— Compact spacing (12px)p-4— Standard spacing (16px)p-6— Comfortable spacing (24px)p-8— Generous spacing (32px)
Gap Patterns
gap-3orgap-4— For most layoutsgap-6orgap-8— For section separation
Card Padding
Cards need at leastp-4, ideally p-6 for a comfortable feel:
Typography
Typography creates rhythm and hierarchy in your interfaces.Scale Guidelines
- Headings — Use the default font stack, weights 500-700
- Body text — 14-16px, weight 400, good line-height (1.5-1.6)
- Labels — 12-14px, weight 500, slightly muted color
Size Discipline
Don’t mix too many sizes. Stick to 2-3 text sizes per component maximum.Color Usage
Color should be used purposefully, not decoratively.Primary/Accent Colors
Use sparingly for CTAs and important actions. If everything is highlighted, nothing is.Muted Tones
- Background fills
- Secondary text
- Dividers and separators
Semantic Colors
- Red — Destructive actions and errors
- Green — Success states
- Yellow — Warnings and caution
- Blue — Information and neutral actions
Dark Mode Support
Always design for both modes from the start. Use CSS variables instead of hardcoded colors.Animation Guidelines
Motion should feel natural and purposeful, never gratuitous.Timing
- Micro-interactions — 150-200ms (hover states, toggles)
- Small transitions — 200-300ms (dropdowns, tooltips)
- Large transitions — 300-500ms (modals, page transitions)
- Never longer than 500ms for UI animations
Easing Functions
- ease-out — For elements entering (start fast, end slow)
- ease-in — For elements leaving (start slow, end fast)
- ease-in-out — For elements that stay on screen while moving
What to Animate
- ✅ Opacity changes
- ✅ Transform (scale, translate, rotate)
- ✅ Background color
- ❌ Width/height (causes layout thrashing)
- ❌ Box shadows (can be expensive)
Always respect
prefers-reduced-motion. Users who enable this preference should see no or minimal animation.Iconography
We use Hugeicons through theicons component for consistent, beautiful icons.
Icon Guidelines
- Size consistency — Use
size-4(16px),size-5(20px), orsize-6(24px) - Match visual weight — Icons should feel balanced with adjacent text
- Stroke width — Keep consistent at 1.5-2px
- Provide fallbacks — Not all icons exist; handle gracefully
Component Architecture
Built on shadcn/ui
Gaia UI is built on shadcn/ui, which uses Radix primitives for accessible, composable components.Class Merging with cn()
Always use thecn utility for conditional classes:
Props Pattern
Export clear, well-typed interfaces:Performance Considerations
Bundle Size
- Import only what you need from libraries
- Avoid importing entire icon sets
- Use dynamic imports for heavy components
Rendering Performance
- Use
React.memo()for expensive components - Avoid inline function definitions in JSX when possible
- Keep state as local as possible