@bgunnarsson/react-primitives
v0.1.14
Published
Unstyled, accessible React component primitives built on Radix UI
Downloads
128
Maintainers
Readme
@bgunnarsson/react-primitives
An unstyled, accessible React component library. Built on Radix UI primitives — components ship with zero CSS and are styled entirely via className in the consuming project.
Philosophy
- Unstyled by default — no opinions on colors, spacing, or typography. Apply Tailwind or any CSS solution via
className. - Accessible — Radix UI handles ARIA attributes, keyboard navigation, and focus management out of the box.
- Composable — compound component pattern throughout. Each named part (trigger, content, item, etc.) is a separate export that accepts
className. - Framework-agnostic styling — works with Tailwind CSS v3/v4, CSS Modules, plain CSS, or any other approach.
Installation
pnpm add @bgunnarsson/react-primitivesPeer dependencies
pnpm add react react-domUsage
Import components directly from the package:
import { useState } from 'react'
import { Button, Dialog, DialogContent, DialogTitle } from '@bgunnarsson/react-primitives'
export function MyComponent() {
const [open, setOpen] = useState(false)
return (
<>
<Button className="rounded-md bg-blue-600 px-4 py-2 text-sm text-white" onClick={() => setOpen(true)}>
Open dialog
</Button>
<Dialog open={open} onOpenChange={setOpen}>
<DialogContent className="fixed left-1/2 top-1/2 -translate-x-1/2 -translate-y-1/2 rounded-xl bg-white p-6 shadow-xl">
<DialogTitle className="text-lg font-semibold">Hello</DialogTitle>
</DialogContent>
</Dialog>
</>
)
}Lightbox CSS
If you use the Lightbox component, import its stylesheet once in your app entry or layout:
import 'yet-another-react-lightbox/styles.css'Toaster
Place <Toaster> once in your root layout to enable toast notifications:
import { Toaster } from '@bgunnarsson/react-primitives'
export default function Layout({ children }) {
return <>{children}<Toaster /></>
}Development
pnpm dev # Start Storybook on http://localhost:6006
pnpm build # Build the library (ESM + CJS + types)
pnpm build-storybook # Build static StorybookComponent Reference
92 components across layout, form, navigation, overlay, media, and low-level utility categories.
Layout & Content
| Component | Description |
|---|---|
| AspectRatio | Container that locks children to a fixed width/height ratio |
| Box | Polymorphic block-level wrapper with as prop |
| Card | Flexible container for composing any card layout |
| CodeBlock | Code display with title, copy button, and optional syntax highlighting |
| Container | Generic div wrapper accepting all HTML attributes |
| EmptyState | Zero-data placeholder with icon, title, description, and action |
| Footer | Semantic <footer> wrapper |
| Grid | CSS grid container and item wrapper |
| Header | Semantic <header> wrapper |
| Resizable | Resizable split-pane layouts (IDE sidebars, chat UIs) |
| ScrollArea | Scrollable container with custom scrollbars |
| Separator | Horizontal or vertical dividing line |
| Skeleton | Loading placeholder element |
| Stack / Flex | Flex layout with direction, align, justify, gap, and wrap shortcuts |
| Stat | Metric display with label, value, and help text |
| Table | Semantic table with Header, Body, Footer, Row, Head, Cell, Caption |
| Text | Polymorphic text element (p, span, h1–h6) |
| VirtualList | Windowed list for large datasets — fixed or variable item sizes, vertical or horizontal |
Typography & Media
| Component | Description |
|---|---|
| Badge | Inline label for status, counts, or categories |
| Icon | SVG icon from sprite or external file |
| Lightbox | Full-screen image viewer with navigation |
| Mark | Highlighted text — direct wrap or query-based search highlighting |
| Picture | Responsive <picture> with multiple sources |
| Richtext | CMS HTML string renderer |
| Spinner | Animated loading indicator |
| VideoPlayer | HTML5 video wrapper |
Form
| Component | Description |
|---|---|
| Button | Unstyled button element |
| Calendar | Inline calendar for single, range, or multiple date selection |
| Checkbox | Accessible checkbox with built-in indicator |
| CheckboxGroup | Controlled group of labelled checkboxes |
| ColorPicker | Hex, RGBA, and HSLA color pickers |
| Combobox | Searchable dropdown select |
| DatePicker | Single date picker with calendar popover |
| DateRangePicker | Two-date range picker with calendar popover |
| Editable | Click-to-edit inline text with preview/input swap |
| FileInput | File picker with drag-and-drop support |
| Form | Context-based field wrapper (label, control, error message) |
| Input | Text input field |
| InputOTP | One-time-password / verification-code input |
| Label | Form field label |
| MaskedInput | Pattern-masked input (credit card, SSN, custom formats) |
| Mention | @-style autocomplete primitive (render-prop) for input/textarea |
| NumberInput | Numeric input with increment/decrement buttons |
| PasswordInput | Password input with show/hide toggle |
| PhoneInput | International phone input with country selector, emits E.164 |
| RadioGroup | Radio button group |
| Rating | Star / score rating input with keyboard and screen-reader support |
| SearchInput | Search input with leading icon and clear button |
| Select | Dropdown select with groups and separators |
| Slider | Accessible range slider |
| Switch | Toggle switch |
| TagInput | Multi-value chip/token input |
| Textarea | Multi-line text input |
| TimePicker | Time input with keyboard stepping and 12/24h formats |
Navigation
| Component | Description |
|---|---|
| Breadcrumbs | Navigation trail with current page indicator |
| Link | Anchor element |
| Menubar | Desktop-style application menu bar |
| Nav | Semantic <nav>, <ul>, <li> wrappers |
| NavigationMenu | Site-header navigation with mega-menu support |
| Pagination | Page navigation with prev, next, and ellipsis |
| Stepper | Multi-step progress indicator |
| Tabs | Tabbed panel interface |
| TreeView | Hierarchical tree with expand/collapse and selection |
Overlay & Popover
| Component | Description | |---|---| | AlertDialog | Confirmation dialog for destructive actions | | Command | Command palette (⌘K) — inline or as a modal | | ContextMenu | Right-click menu | | Dialog | Modal dialog | | Drawer | Bottom sheet with drag-to-dismiss | | DropdownMenu | Button-triggered dropdown menu | | HoverCard | Hover-triggered preview popover | | Popover | Click-triggered floating panel | | Sheet | Sliding panel from any screen edge | | Toaster | Toast notification system | | Tooltip | Hover/focus tooltip |
Disclosure & Interaction
| Component | Description | |---|---| | Accordion | Expandable sections (single or multiple) | | Carousel | Touch-friendly slideshow | | Collapsible | Single expandable section | | Progress | Progress bar (0–100) | | Toggle | Pressed/unpressed button | | ToggleGroup | Group of toggles (single or multiple selection) | | Toolbar | Accessible toolbar with roving-focus keyboard navigation |
Display
| Component | Description |
|---|---|
| Alert | Status message with title and description |
| Avatar | Profile image with text fallback |
| Banner | Persistent dismissable site-wide notification |
| Status | Live state indicator (online/busy/away/etc.) with optional label |
| Timeline | Chronological event list (<ol>) with indicators, connectors, and time |
Utilities & Composition
| Component | Description |
|---|---|
| CopyButton | Button that copies text to the clipboard with copied-state feedback |
| DirectionProvider | Declares writing direction (ltr / rtl) for all child Radix primitives |
| FocusScope | Standalone focus trap with auto-focus and focus restoration |
| Portal | Renders children into a different part of the DOM tree |
| Slot | Composition primitive for implementing an asChild prop |
| VisuallyHidden | Hides content visually while keeping it available to screen readers |
