Instruction file imported from sadmann7/diceui (
.cursor/rules/component-setup.mdc). Copyright stays with the author.
Dice UI Component Setup Rule
You are an expert in TypeScript, React, and Dice UI component architecture. When a user asks you to create a new component using the pattern "@setup-component [component-name]", follow this comprehensive pipeline:
Base Selection
Dice UI supports multiple UI base libraries. When creating a component, specify which base to use:
- Base UI (default):
@docs/registry/bases/base/ - Radix UI:
@docs/registry/bases/radix/
Steps
1. Create Component Types (@docs/types/[base]/[component-name].ts)
- Create TypeScript interfaces for all component parts based on the base library
- For Radix UI: Use
@docs/types/radix/[component-name].tswithCompositionPropsandEmptyProps - For Base UI: Use
@docs/types/base/[component-name].tswithuseRender.ComponentPropsandEmptyProps - Follow the pattern from existing files like
action-bar.ts - Include proper JSDoc comments with examples
- Import necessary types from UI libraries and internal types
- Define interfaces for Root, Content, Trigger, and any specific component parts
- Include composition props and controlled/uncontrolled patterns
Finalize the API design first. Once it's been iterated on and completed, proceed to the other steps. This will minimize refactoring.
2. Create Examples (@docs/registry/bases/[base]/examples/)
Create these example files in the appropriate base folder:
[component-name]-demo.tsx- Basic usage example[component-name]-controlled-demo.tsx- Controlled state example (if applicable)[component-name]-form-demo.tsx- Form integration example (if applicable)- Additional variant demos as needed
3. Update Registry Files
Update the registry files in @docs/registry/bases/[base]/:
UI Registry (@docs/registry/bases/[base]/ui/_registry.ts)
Add UI component entry with:
- Component name
- Dependencies (only the main UI library:
radix-uior@base-ui/react)- Do NOT include
class-variance-authority,lucide-react, orreact-dom- these are already part of the project setup
- Do NOT include
- Registry dependencies (internal UI components, hooks, libs)
- File paths for UI component
Examples Registry (@docs/registry/bases/[base]/examples/_registry.ts)
Add example entries for each demo file created:
- Component name + "-demo" suffix
- Dependencies and registry dependencies
- File paths
Hooks/Libs Registry (if needed)
- Update
@docs/registry/bases/[base]/hooks/_registry.tsfor custom hooks - Update
@docs/registry/bases/[base]/lib/_registry.tsfor utility functions
4. Create Documentation (@docs/content/docs/components/[base]/[component-name].mdx)
Create comprehensive documentation including:
- Title, description, and metadata with
basefield set to "radix" or "base" - ComponentTabs for demo preview
- Installation instructions (CLI and manual)
- Layout/composition examples
- Multiple example sections
- Complete API reference with AutoTypeTable for each interface using
./types/[base]/[component-name].ts - Accessibility section with keyboard interactions
- Any specific notes about browser support or limitations
5. Update Navigation Meta (@docs/content/docs/components/[base]/meta.json)
Add the component name to the pages array in alphabetical order:
{
"pages": [
"action-bar",
"angle-slider",
"[component-name]", // Insert alphabetically
...
]
}
Implementation Guidelines
Type Definitions
- Use consistent naming:
RootProps,TriggerProps,ContentProps, etc. - Extend from appropriate base components (Button, Input, etc.)
- Use
EmptyPropsfirst to filter out standard HTML attributes - For Radix UI: Include
CompositionPropsforasChildsupport - For Base UI: Include
useRender.ComponentPropsforrenderprop support - Add proper JSDoc with
@defaultvalues and@exampleusage - Support both controlled and uncontrolled patterns where applicable
Example Components
- Import from
@/registry/bases/[base]/ui/[component-name] - For Radix UI: Use
asChildprop pattern with Slot primitive - For Base UI: Use
renderprop pattern withuseRenderhook - Use default export with descriptive function name
- Show realistic usage scenarios
- Include proper TypeScript typing
- Follow Dice UI component composition patterns
Registry Entries
- Maintain alphabetical order in all registry files
- Include all necessary dependencies
- Use proper file paths relative to registry
- Match naming conventions exactly
Documentation Structure
- Follow the established MDX pattern from existing component docs
- Set the
basefrontmatter to either "radix" or "base" - Use ComponentTabs for interactive previews
- Update AutoTypeTable paths to use
./types/[base]/[component-name].ts - Include comprehensive API documentation
- Add accessibility considerations
- Provide installation and setup instructions with correct dependencies
Example Usage
When user types: @setup-component [component-name] --base=[radix|base]
You should:
- Create
docs/registry/bases/[base]/ui/[component-name].tsxwith the component - Create
docs/types/[base]/[component-name].tswith proper interfaces - Create example files like
[component-name]-demo.tsxindocs/registry/bases/[base]/examples/ - Update
docs/registry/bases/[base]/ui/_registry.tswith the component entry - Update
docs/registry/bases/[base]/examples/_registry.tswith example entries - Create
docs/content/docs/components/[base]/[component-name].mdxdocumentation - Update
docs/content/docs/components/[base]/meta.jsonto add the component to navigation
And when user types: @setup-only [component-name] --base=[radix|base]
- Create
docs/registry/bases/[base]/ui/[component-name].tsxwith the component - Create
docs/registry/bases/[base]/examples/[component-name]-demo.tsxwith the demo
Note: If no --base flag is provided, default to Radix UI.
Code Style
- Use functional components with TypeScript
- Follow existing patterns for imports and exports
- Use descriptive variable names
- Maintain consistent formatting and structure
- Add proper error handling and accessibility features
- Use flex and gap instead of space-x-n and space-y-n
- Style a component with
cn-*markers like shadcn/ui:className={cn("cn-faceted-trigger group/faceted-trigger", className)}, with its classes indocs/registry/styles/style-new-york.cssas.cn-faceted-trigger { @apply ...; }, written in shadcn's New York classes (h-9 rounded-md shadow-xsinputs,rounded-smitems). Keepgroup/*,peer/*anddarknext to the marker, since@applycan't take them. - Where a part is a shadcn primitive (an input, a popup, a menu item), use shadcn's own marker instead of a copy, like
cn-command-input-group, so it gets shadcn's exact classes in every style. - Put markers where
transformStylecompiles them:cva()base andvariants,classNameattributes,className: cn(...)properties andmergeProps.pnpm build:registrycompiles them per style, andpnpm devregenerates the style maps when a style file changes. After changingstyle-new-york.css, runpnpm --filter docs styles:syncto generate all eightstyle-*.cssfiles. Don't edit those by hand: the generator restyles each marker like the shadcn part it copies (shadcn/roles.json, refreshed byshadcn:sync), and a test fails when they're out of date. If the generator picks the wrong shadcn part for a rule, pin it with a comment right above the rule instyle-new-york.css, like/* @role cn-dropdown-menu-content */, so it takes that part's classes in every style. When a style needs a hand-tuned rule, put it indocs/registry/styles/overrides/style-[style].css(same.style-[style] { .cn-x { @apply ...; } }format) and rerunstyles:sync; an override wins over the generated rule for that style. - shadcn/ui components in
docs/registry/bases/[base]/uicome from shadcn's marker source, not the CLI. Update them withpnpm --filter docs shadcn:sync, which pins a commit, re-applies our patches and vendors their style rules intodocs/registry/styles/shadcn. - Docs UI (not examples) imports primitives from
@/styles/[base]-nova/ui/*, compiled copies that ignore the style switcher. Examples keep importing@/registry/bases/[base]/ui/*so previews follow the selected style. - Write physical classes (
ml-*,pl-*,left-*,border-l,text-left) like shadcn/ui, and addcn-rtl-flipto directional icons. The shadcn CLI converts them to logical classes for projects withrtl: true. - The CLI skips
compoundVariants, so use logical classes (ms-*,start-*,rounded-s-*) there. - When something must stay physical in RTL (an inline
leftstyle, aside="left"prop), use arbitrary properties like[left:--spacing(2)]or[translate:-50%_0], which the CLI won't flip. - RTL demos (
*-rtl-demo.tsx) import from@/registry/bases/[base]/ui-rtl/, whichpnpm build:registrygenerates fromui/. Rerun it after changing a component an RTL demo uses. - In the layout portion of the docs don't pass any props, can reference the @file-upload.mdx.
- Make sure not to update any `[component-name].json files, these will be autogenerated with the shadcn cli.
File Organization
- Keep consistent file naming (kebab-case)
- Follow existing directory structure
- Maintain import path consistency
- Use proper TypeScript module organization
When implementing, create all files in the correct locations and ensure they follow the established patterns from existing components like action-bar, editable, color-picker, etc.
