docs: document architecture and usage
Explain installation, styles, exports, and validation. Record the component wrapper design and implementation plan.
This commit is contained in:
@@ -0,0 +1,203 @@
|
||||
# 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"
|
||||
|
||||
<Dialog.Root>
|
||||
<Dialog.Trigger>Open</Dialog.Trigger>
|
||||
<Dialog.Portal>
|
||||
<Dialog.Backdrop />
|
||||
<Dialog.Popup />
|
||||
</Dialog.Portal>
|
||||
</Dialog.Root>
|
||||
```
|
||||
|
||||
Named exports are the shadcn-style flattened API:
|
||||
|
||||
```tsx
|
||||
import {
|
||||
Dialog,
|
||||
DialogTrigger,
|
||||
DialogContent,
|
||||
DialogTitle,
|
||||
} from "@/components/ui/dialog"
|
||||
|
||||
<Dialog>
|
||||
<DialogTrigger>Open</DialogTrigger>
|
||||
<DialogContent>
|
||||
<DialogTitle>Title</DialogTitle>
|
||||
</DialogContent>
|
||||
</Dialog>
|
||||
```
|
||||
|
||||
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.
|
||||
Reference in New Issue
Block a user