Skip to content

bgunnarsson/react-primitives

Repository files navigation

@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-primitives

Peer dependencies

pnpm add react react-dom

Usage

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 Storybook

Component Reference

95 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, h1h6)
VirtualList Windowed list for large datasets — fixed or variable item sizes, vertical or horizontal

Typography & Media

Component Description
AudioPlayer HTML5 audio wrapper
Badge Inline label for status, counts, or categories
Embed Iframe wrapper with safe defaults plus YouTube / Vimeo URL helpers
Icon SVG icon from sprite or external file
Image DPR-aware responsive <img> (1x/2x/3x srcset) for image-resizing backends
CropImage Responsive <picture> with separate mobile / desktop crops, each DPR-aware
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
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
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
ErrorBoundary Catches descendant render errors and renders a fallback (with resetKeys and render-prop fallback)
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

About

Barebones React parts. No opinions, no bloat—just vibes and components

Resources

License

Stars

Watchers

Forks

Contributors