Skip to main content
Vertz ships a full set of ready-to-use UI components with a shadcn-inspired theme. Use them instead of building from scratch.

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.
Most apps only import from @vertz/theme-shadcn.

Setup

Call configureTheme() once and register it with registerTheme():
Then import components from @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.
Intents: primary, secondary, outline, ghost, destructive, link. Sizes: sm, md, lg.

Input

Text input field for forms.

Per-input debounce

Add debounce={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:
See Form-level onChange for full details.

Textarea

Multi-line text input.
Supports 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.
Sub-components: Sidebar, Brand, Nav, NavItem, Content, User. NavItem provides SPA navigation with active state detection:
  • match="prefix" (default) — active when pathname starts with href (e.g., /projects matches /projects/123)
  • match="exact" — active only on exact pathname match
  • icon — accepts any @vertz/icons component, rendered at 16px

Card

Container with header, content, and footer.

Separator

Visual divider between content.

Accordion

Expandable/collapsible content sections.

Tabs

Tabbed content organization.
Supports 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 with Text and Circle sub-components for common patterns.

EmptyState

Compound component for empty-data placeholders with icon, title, description, and action slots.
All slots are optional — use only what you need:

Overlays

Dialog

All dialogs use useDialogStack() with native <dialog> + showModal(). Dialog sub-components (Dialog.Header, Dialog.Title, etc.) are used inside the dialog component.

Confirm Dialog

Quick confirmation via useDialogStack().confirm():

Sheet

Side panel that slides in from edge.
Supports side="left", side="right" (default), side="top", side="bottom".

Popover

Floating content anchored to trigger.

Tooltip

Brief info on hover or focus.

Navigation breadcrumb trail.
The last item renders as the current page (no link). Supports a custom separator prop (defaults to /).

Pagination

Page navigation controls.
Supports siblingCount to control how many page numbers show around the current page. 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.
Supports 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:
ComponentDescription
CalendarDate grid with month navigation
DatePickerDate picker composing Calendar + Popover
CarouselSlide navigation with prev/next controls
CollapsibleExpandable/collapsible content section
CommandSearchable command palette
ContextMenuRight-click context menu
DrawerBottom/side panel wrapping Dialog
HoverCardHover-triggered interactive card
MenubarHorizontal menu bar with dropdowns
NavigationMenuSite navigation with hover dropdowns
ResizablePanelResizable panel layout with drag handles
ScrollAreaCustom scrollbars
ToggleGroupGroup of toggle buttons
All are importable from @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:
See Styling for details on css() and variants().

Theme configuration

configureTheme() accepts palette, radius, and color override options:
The 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 variables
  • config.globals — Global CSS string to inject
  • config.styles — Pre-built style objects for manual styling
  • config.components — Used internally by registerTheme() — import components from @vertz/ui/components instead