# Base UI Shadcn Wrapper Design ## Goal Build an internal source-template component library that wraps Base UI React with Tailwind CSS styles. The library should feel like shadcn/ui for application developers while preserving a Base UI-style part API for people who prefer Base UI's composition model. The first version is source-only. It will not publish to npm, provide a CLI, or maintain registry metadata. ## Inputs - Base library: `@base-ui/react` - Styling: Tailwind CSS utility classes - Default visual style: Base UI React documentation examples - Consumer model: copy source files into internal React projects - Framework target: framework-neutral React source templates ## Component Scope The first version covers every component listed in the Base UI React component documentation: - Accordion - Alert Dialog - Autocomplete - Avatar - Button - Checkbox - Checkbox Group - Collapsible - Combobox - Context Menu - Dialog - Drawer - Field - Fieldset - Form - Input - Menu - Menubar - Meter - Navigation Menu - Number Field - OTP Field - Popover - Preview Card - Progress - Radio - Scroll Area - Select - Separator - Slider - Switch - Tabs - Toast - Toggle - Toggle Group - Toolbar - Tooltip ## Directory Shape Each component is a folder under `components/ui`. Composite components split every Base UI part into its own file. Example: ```txt components/ui/dialog/ index.ts root.tsx trigger.tsx portal.tsx backdrop.tsx popup.tsx content.tsx title.tsx description.tsx close.tsx ``` Single-part components also use folders for consistency: ```txt components/ui/button/ index.ts root.tsx ``` Shared helpers live in: ```txt lib/utils.ts ``` ## Export Model Every component module supports two API styles from the same implementation. Default export is the styled Base UI namespace: ```tsx import Dialog from "@/components/ui/dialog" Open ``` Named exports are the shadcn-style flattened API: ```tsx import { Dialog, DialogTrigger, DialogContent, DialogTitle, } from "@/components/ui/dialog" Open Title ``` For single-part components: ```tsx import Button from "@/components/ui/button" import { Button as UIButton } from "@/components/ui/button" ``` `Button` as the default export is the styled primitive for Base UI-style import habits. `Button` as a named export is the shadcn-style import. For single-part components these can reference the same underlying styled component. Part file names should mirror Base UI part names where possible. Additional shadcn-style convenience components, such as `DialogContent`, can live beside the primitive part files when they compose multiple parts. ## Implementation Rules - Styled parts wrap Base UI parts directly. - Each part owns its own Tailwind classes. - Shadcn-style convenience components compose styled parts instead of duplicating styles. - The internal library does not re-export unstyled Base UI primitives. Consumers who need unstyled primitives can import from `@base-ui/react` directly. - Every styled part accepts `className` and merges it after the default classes using `cn`. - Forward refs where the underlying Base UI part supports refs. - Use Base UI data attributes and CSS variables for stateful styling. - Add `"use client"` to interactive component files so copied source works in Next.js projects while remaining harmless in ordinary React projects. ## Styling Rules Default styles should mirror Base UI documentation examples: - Neutral black/white visual language - Clear borders - Compact control sizing - `focus-visible` outlines - `data-*` selectors for open, highlighted, checked, disabled, selected, and similar states - Dark mode classes where Base UI examples provide them - Tailwind classes in source files, not CSS Modules Components should not add shadcn-style variant systems unless Base UI's official examples require that abstraction. The default implementation should stay close to the official Base UI Tailwind demos, and local variation should happen through `className` overrides. ## TypeScript Rules - Component props extend the corresponding Base UI part props. - Variant props are added only where the component defines variants. - Export prop types for public components where useful. - Avoid hiding Base UI capabilities such as `render`, `nativeButton`, `focusableWhenDisabled`, positioning props, and controlled-state props. ## Documentation Add a README that explains: - Required dependencies - Tailwind requirements - The default namespace export - The named shadcn-style export - The source-copy workflow - How to customize classes safely The README should include a short example for a single-part component and a composite component. ## Verification The first implementation should verify: - TypeScript compiles. - Every component folder exports a default namespace or default primitive. - Every component folder provides shadcn-style named exports where appropriate. - Tailwind class strings are static enough for Tailwind scanning. - Representative examples compile for both a single-part component and a composite component. Visual verification can be added after the component set exists, using a local demo page or Storybook-like fixture. ## Non-Goals - No npm package publishing. - No CLI. - No registry metadata. - No attempt to create a separate design language. - No unstyled primitive re-export layer.