Architecture
The component system has two layers:@vertz/ui-primitives— Headless, accessible components with WAI-ARIA patterns. No styling, just behavior.@vertz/theme-shadcn— Wraps every primitive with shadcn-inspired styles, plus adds common components like Button, Input, Card, and Table.
@vertz/theme-shadcn.
Setup
CallconfigureTheme() once and register it with registerTheme():
@vertz/ui/components anywhere in your app:
Direct components (
Button, Card, etc.) are simple styled wrappers. Primitive
components (Dialog, Select, etc.) are themed wrappers around @vertz/ui-primitives with
compound sub-components (e.g., Dialog.Title, Dialog.Footer, Select.Content).Form
Button
Triggers an action or event. Supports intents and sizes.primary, secondary, outline, ghost, destructive, link. Sizes: sm, md, lg.
Input
Text input field for forms.Per-input debounce
Adddebounce={ms} to delay the form-level onChange callback for this input. Useful for search fields where you don’t want to fire on every keystroke:
Textarea
Multi-line text input.debounce={ms} for form-level onChange, same as Input:
Label
Accessible label for form controls.FormGroup
Groups form controls with error display.Select
Dropdown selection control.Layout
AppShell
Sidebar + content layout for SaaS apps. Includes themed navigation links with automatic active state.Sidebar, Brand, Nav, NavItem, Content, User.
NavItem provides SPA navigation with active state detection:
match="prefix"(default) — active when pathname starts withhref(e.g.,/projectsmatches/projects/123)match="exact"— active only on exact pathname matchicon— accepts any@vertz/iconscomponent, rendered at 16px
Card
Container with header, content, and footer.Separator
Visual divider between content.Accordion
Expandable/collapsible content sections.Tabs
Tabbed content organization.variant="line" for an underline tab style.
Data Display
Badge
Small status or count indicator.Avatar
User profile image with fallback.Table
Tabular data display.Skeleton
Loading placeholder with built-in pulse animation. Comes withText and Circle sub-components for common patterns.
EmptyState
Compound component for empty-data placeholders with icon, title, description, and action slots.Overlays
Dialog
All dialogs useuseDialogStack() with native <dialog> + showModal(). Dialog sub-components
(Dialog.Header, Dialog.Title, etc.) are used inside the dialog component.
Confirm Dialog
Quick confirmation viauseDialogStack().confirm():
Sheet
Side panel that slides in from edge.side="left", side="right" (default), side="top", side="bottom".
Popover
Floating content anchored to trigger.Tooltip
Brief info on hover or focus.Navigation
Breadcrumb
Navigation breadcrumb trail.separator prop (defaults to /).
Pagination
Page navigation controls.siblingCount to control how many page numbers show around the current page.
DropdownMenu
Menu triggered by a button click.Feedback
Alert
Inline alert messages.Factory-based primitives
These components use an imperative factory API — they return DOM elements rather than JSX compound components. Import them from@vertz/ui/components.
These primitives haven’t been converted to JSX compound components yet. They work by returning DOM
elements that you embed in your JSX tree. JSX versions are planned.
Checkbox
Toggle control for boolean values.Switch
Toggle between on and off states.size: 'sm' for compact variant.
RadioGroup
Select one option from a set.Slider
Range input with track and thumb.Toggle
Toggle button with pressed state.Progress
Shows task completion percentage.Toast
Temporary notification popup.Additional primitives
These components are available via@vertz/ui/components, but are less commonly used:
| Component | Description |
|---|---|
| Calendar | Date grid with month navigation |
| DatePicker | Date picker composing Calendar + Popover |
| Carousel | Slide navigation with prev/next controls |
| Collapsible | Expandable/collapsible content section |
| Command | Searchable command palette |
| ContextMenu | Right-click context menu |
| Drawer | Bottom/side panel wrapping Dialog |
| HoverCard | Hover-triggered interactive card |
| Menubar | Horizontal menu bar with dropdowns |
| NavigationMenu | Site navigation with hover dropdowns |
| ResizablePanel | Resizable panel layout with drag handles |
| ScrollArea | Custom scrollbars |
| ToggleGroup | Group of toggle buttons |
@vertz/ui/components after registering a theme with registerTheme().
Headless usage
For custom styling, import directly from@vertz/ui-primitives and apply your own classes:
css() and variants().
Theme configuration
configureTheme() accepts palette, radius, and color override options:
colors key deep-merges into the selected palette. Use DEFAULT for light mode and _dark for dark mode. You can also add custom token names.
config.theme— Resolved CSS variablesconfig.globals— Global CSS string to injectconfig.styles— Pre-built style objects for manual stylingconfig.components— Used internally byregisterTheme()— import components from@vertz/ui/componentsinstead