# Sage Design Engine — Complete Component Reference # Version: 1.1.0 | React 18/19 | Next.js 15+ | Tailwind 3.4+ | framer-motion ^12 # Components: 100 | Themes: 3 (Studio, Terra, Volt) | Blocks: 2 # Last verified: 2026-02-16 # Package: pnpm add @thesage/ui # MCP: npx @thesage/mcp > 100 components | 11 categories | 3 themes | TypeScript strict mode | MIT license --- ## INSTALLATION ```bash pnpm add @thesage/ui # or npm install @thesage/ui ``` ## PROVIDER HIERARCHY (Required) Wrap your app root in this order: ```tsx import { ThemeProvider, TooltipProvider } from '@thesage/ui/providers' import { Toaster } from '@thesage/ui' import '@thesage/ui/globals.css' export default function RootLayout({ children }) { return ( {children} ) } ``` ## IMPORT PATTERNS ```tsx // Main exports (most common) import { Button, Card, Input, Dialog, Badge } from '@thesage/ui' // Subpath exports import { useMotionPreference, useTheme } from '@thesage/ui/hooks' import { ThemeProvider, TooltipProvider } from '@thesage/ui/providers' import { cn } from '@thesage/ui/utils' import { spacing, typography } from '@thesage/ui/tokens' // Heavy/optional features import { Form, FormField, FormItem } from '@thesage/ui/forms' import { Calendar, DatePicker } from '@thesage/ui/dates' import { DataTable } from '@thesage/ui/tables' import { DragDrop } from '@thesage/ui/dnd' ``` ## EJECT (Full Customization) Copy any component's source into your project with imports rewritten: ```bash npx @thesage/ui eject Button # eject to src/components/ui/ npx @thesage/ui eject Dialog --dir my/dir # custom target npx @thesage/ui eject --list # list all components ``` Ejected components keep working with SDE themes and CSS variables. Internal imports (`../../lib/utils`) are rewritten to package-level imports (`@thesage/ui/hooks`, `@thesage/ui/utils`). A `utils.ts` with `cn()` is auto-scaffolded alongside the ejected file. Also available via MCP tool `eject_component` (returns transformed source) and web UI (Eject button on every component page at thesage.dev). ## COMPLETE APP SHELL (copy-paste ready) ### Vite + React ```tsx // src/main.tsx import React from 'react' import ReactDOM from 'react-dom/client' import { ThemeProvider, TooltipProvider, Toaster } from '@thesage/ui' import '@thesage/ui/globals.css' import App from './App' ReactDOM.createRoot(document.getElementById('root')!).render( ) // tailwind.config.js /** @type {import('tailwindcss').Config} */ export default { content: ['./index.html', './src/**/*.{ts,tsx}', './node_modules/@thesage/ui/dist/**/*.{js,mjs}'], darkMode: 'class', theme: { extend: {} }, plugins: [require('tailwindcss-animate')], } // postcss.config.js export default { plugins: { tailwindcss: {}, autoprefixer: {} }, } ``` ### Next.js App Router ```tsx // app/layout.tsx import { ThemeProvider, TooltipProvider, Toaster } from '@thesage/ui' import '@thesage/ui/globals.css' export default function RootLayout({ children }: { children: React.ReactNode }) { return ( {children} ) } ``` ### Manual Setup (any React project) 1. `pnpm add @thesage/ui` 2. Add to tailwind.config.js content array: `'./node_modules/@thesage/ui/dist/**/*.{js,mjs}'` 3. Import globals: `import '@thesage/ui/globals.css'` 4. Wrap app in providers: `{children}` --- ## THEMES Three themes, each with light and dark modes: - **Studio** — Professional, balanced (default). Framer/Vercel/Linear aesthetic. - **Terra** — Calm, organic, warm earth tones. - **Volt** — Bold, electric, cyberpunk neon. Switch at runtime: ```tsx import { useTheme } from '@thesage/ui/hooks' const { theme, setTheme, mode, setMode } = useTheme() setTheme('volt') setMode('dark') ``` ## STYLING RULES - Use CSS variables for colors: `bg-background`, `text-foreground`, `border-border` - Never hardcode colors: no `bg-white`, `text-black`, `bg-neutral-100` - All components are Tailwind-compatible via `className` prop - Use `cn()` utility to merge classNames: `import { cn } from '@thesage/ui/utils'` ## MOTION Every animation MUST respect user preferences: ```tsx import { useMotionPreference } from '@thesage/ui/hooks' const { shouldAnimate, scale } = useMotionPreference() // shouldAnimate = false when intensity is 0 or prefers-reduced-motion // scale = 0-1 multiplier for animation intensity ``` --- # COMPONENT CATEGORIES ## ACTIONS (5 components) Interactive elements that trigger behaviors. ### Button Import: `import { Button } from '@thesage/ui'` Props: - variant: 'default' | 'destructive' | 'outline' | 'secondary' | 'ghost' | 'link' (default: 'default') - size: 'sm' | 'default' | 'lg' | 'icon' (default: 'default') - disabled: boolean (default: false) - asChild: boolean (default: false) — Renders as child element via Radix Slot Built on: @radix-ui/react-slot Example: ```tsx ``` ### Toggle Import: `import { Toggle } from '@thesage/ui'` Props: - pressed: boolean - onPressedChange: (pressed: boolean) => void - variant: 'default' | 'outline' (default: 'default') - size: 'sm' | 'default' | 'lg' (default: 'default') - disabled: boolean (default: false) Built on: @radix-ui/react-toggle Example: ```tsx ``` ### ToggleGroup Import: `import { ToggleGroup, ToggleGroupItem } from '@thesage/ui'` Props: - type: 'single' | 'multiple' (required) - value: string | string[] - onValueChange: (value) => void - variant: 'default' | 'outline' (default: 'default') - size: 'sm' | 'default' | 'lg' (default: 'default') Built on: @radix-ui/react-toggle-group Example: ```tsx Left Center Right ``` ### Link Import: `import { Link } from '@thesage/ui'` Props: - variant: 'default' | 'inline' (default: 'default') - hoverEffect: boolean (default: true) - href: string (required) - All standard attributes Example: ```tsx Learn More ``` ### Magnetic Import: `import { Magnetic } from '@thesage/ui'` Props: - children: ReactNode - strength: number (default: 0.5) Dependency: framer-motion Example: ```tsx ``` --- ## FORMS (19 components) Input controls for data collection. ### Input Import: `import { Input } from '@thesage/ui'` Props: - type: string (default: 'text') — HTML input type - placeholder: string - disabled: boolean (default: false) - All standard attributes Example: ```tsx ``` ### Textarea Import: `import { Textarea } from '@thesage/ui'` Props: - placeholder: string - disabled: boolean (default: false) - All standard