Adding Components

Step-by-step workflows for extending the design system

Ejecting Components

When to Eject

Ejecting copies a component's source code into your project so you can modify it freely. The ejected component still works with Sage themes and CSS variables — you just own the code. Only eject when you need deep customization beyond what props and CSS variables offer.

Three Ways to Eject

1CLI (Recommended)

The fastest way to eject. Run from your project root:

# Eject a single component
npx @thesage/ui eject Button

# Eject to a custom directory
npx @thesage/ui eject Dialog --dir components/sage

# List all available components
npx @thesage/ui eject --list

The CLI automatically transforms internal imports, scaffolds a utils.ts file with the cn() utility, and lists any npm dependencies you need to install.

2Eject Button (This Site)

Every component page on this site has an Eject button. Click it to view the transformed source code, then copy or download it directly into your project.

3AI Assistant (MCP)

If you have the @thesage/mcp server configured, ask your AI assistant to eject a component. It will return the full transformed source code ready to save.

// Example prompts for your AI assistant:
"Eject the Button component so I can customize it"
"I need the Dialog source code in my project"

What Happens When You Eject

Import Transformation

Internal relative imports are automatically rewritten to use package-level imports:

// Before (internal source):
import { cn } from '../../lib/utils'
import { useMotionPreference } from '../../hooks/use-motion-preference'
import { Button } from '../actions/Button'

// After (ejected):
import { cn } from './utils'
import { useMotionPreference } from '@thesage/ui/hooks'
import { Button } from '@thesage/ui'

cn() Utility

A utils.ts file is scaffolded alongside your ejected component containing the cn() utility (clsx + tailwind-merge). If the file already exists, it won't be overwritten.

Theme Compatibility

Ejected components continue to use CSS variables (var(--color-primary), etc.) and work with all three Sage themes (Studio, Terra, Volt) and light/dark modes — no additional configuration needed.

Dependencies

External dependencies (Radix UI primitives, lucide-react, etc.) are listed after ejecting. Install them with the provided pnpm add command. You still need @thesage/ui installed for hooks, utilities, and any non-ejected sibling components.

Example: Ejecting the Button

$ npx @thesage/ui eject Button

  Ejected Button successfully!

  src/components/ui/Button.tsx
  src/components/ui/utils.ts (cn utility)

  Required dependencies:
  pnpm add @radix-ui/react-slot class-variance-authority

  Update your imports:
  import { Button } from './src/components/ui/Button'

  The ejected component still works with @thesage/ui themes and CSS variables.
  You now own it — modify freely.