Subframe is the single source of truth for your design system. Components you build in Subframe sync directly to your codebase — same code, same behavior.Documentation Index
Fetch the complete documentation index at: https://subframe-59800133-apg-component-directories.mintlify.app/llms.txt
Use this file to discover all available pages before exploring further.
Using the CLI
Sync all components to your codebase with the CLI:Adding business logic
Subframe components are presentational — they handle layout, styling, and UI interactions like accordion open/close, but avoid adding product-specific application logic like API calls or state management. Under the hood, we use Radix for interactive behavior, which gives you accessible, well-tested interactions out of the box.Adding handlers and attributes
All components pass through props to the top-level element. This means you can adddata-* attributes, tabIndex, onClick, or any other standard HTML attribute directly to any component.
Using slots to access nested props
It’s common for components to contain interactive elements within them—like a card with a button. Slots let you access these nested elements’ props:Wrapping components
For logic not supported by Radix or slots, wrap the Subframe component. Each component syncs as a directory:components/Button/Button.tsx is the source Subframe generates, and components/Button/index.tsx is a wrapper that re-exports it. The wrapper is yours to edit — add your logic there and mark it with @subframe/sync-disable so the CLI won’t overwrite it:
components/Button/index.tsx
Button.tsx keeps syncing, so Subframe stays the source of truth for the visual layer — while index.tsx gives you the flexibility of code to add any business logic. Anything importing @/ui/components/Button gets your wrapped version, with no import changes.
See Component directories for the full layout and migration details.
In the future, we’ll let you add component logic directly in Subframe.
Disabling sync
Add the@subframe/sync-disable comment anywhere in a file to tell the CLI to skip it on the next sync:
- The wrapper
index.tsx— the usual choice once you’ve added wrapping logic. Your wrapper is preserved, whileButton.tsxkeeps receiving Subframe’s updates. - The main
Button.tsx— a last resort that fully freezes the file Subframe generates, so the component stops receiving updates. Prefer wrapping inindex.tsxinstead.

