README.md
# heroui
> HeroUI v3 component library expertise for React (web) and React Native (mobile). Covers 75+ web components and 40+ native components built on Tailwind CSS v4 and React Aria Components.
## What it does
`heroui` turns your agent into a HeroUI v3 specialist. It knows:
- **Setup for both platforms** — React web (`@heroui/react` + `@heroui/styles`) and React Native (`heroui-native` + Uniwind + Reanimated 4.1+)
- **The full component catalog** — 75+ web components and 40+ native components with their anatomy, props, and composition patterns
- **Theming and styling** — CSS variables, dark mode, custom themes, semantic colors, BEM classes, variant functions, data attributes
- **Compound component patterns** — how HeroUI composes (e.g., `<Modal>` + `<ModalHeader>` + `<ModalBody>` + `<ModalFooter>`)
- **Framework integration** — Next.js App Router, React Router, Vue, Svelte, Expo Router
- **Migration paths** — from NextUI or HeroUI v2
It triggers automatically when code imports `@heroui/react`, `@heroui/styles`, or `heroui-native`.
## When to use it
Invoke this skill when you hear:
- *"Build a dashboard page with HeroUI."*
- *"How do I theme HeroUI to match our brand colors?"*
- *"Compose a multi-step form with HeroUI inputs and a modal confirmation."*
- *"I'm on HeroUI v2 — how do I upgrade to v3?"*
- *"Set up HeroUI in my React Native + Expo app."*
- *"Why isn't dark mode switching in my HeroUI app?"*
## Example walkthrough
**Prompt**
> Set up HeroUI in my Next.js App Router app with a dark-mode toggle and our brand primary color (#0066FF).
**What the skill produces**
**1. Install**
```bash
npm i @heroui/react @heroui/styles
```
**2. `app/globals.css`** (order matters)
```css
@import "tailwindcss";
@import "@heroui/styles";
@theme {
--color-primary: #0066ff;
--color-primary-foreground: #ffffff;
}
```
**3. `app/providers.tsx`**
```tsx
"use client";
import { HeroUIProvider } from "@heroui/react";
import { ThemeProvider } from "next-themes";
export function Providers({ children }: { children: React.ReactNode }) {
return (
<HeroUIProvider>
<ThemeProvider attribute="class" defaultTheme="system">
{children}
</ThemeProvider>
</HeroUIProvider>
);
}
```
**4. `app/layout.tsx`**
```tsx
import { Providers } from "./providers";
import "./globals.css";
export default function RootLayout({ children }: { children: React.ReactNode }) {
return (
<html lang="en" suppressHydrationWarning>
<body><Providers>{children}</Providers></body>
</html>
);
}
```
**5. Theme toggle component**
```tsx
"use client";
import { Button } from "@heroui/react";
import { useTheme } from "next-themes";
export function ThemeToggle() {
const { theme, setTheme } = useTheme();
return (
<Button isIconOnly variant="flat" onPress={() => setTheme(theme === "dark" ? "light" : "dark")}>
{theme === "dark" ? "☾" : "☀"}
</Button>
);
}
```
The skill also explains the **order-matters** pitfall (Tailwind import must come before HeroUI styles) and why `suppressHydrationWarning` is needed with `next-themes`.
## Installation
```bash
npx skills add thatjuan/agent-skills --skill heroui
```
## Bundled resources
| File | Purpose |
|------|---------|
| `SKILL.md` | Quick setup, component architecture, component index, styling system, common patterns |
| `references/react-setup.md` | React web installation, CSS configuration, selective imports, framework integration (Next.js, React Router, Vue, Svelte) |
| `references/native-setup.md` | React Native installation, peer dependencies, Uniwind setup, provider configuration, granular imports |
| `references/react-components.md` | Complete reference — anatomy, props, and usage for all 75+ web components |
| `references/native-components.md` | Complete reference for all 40+ native components |
| `references/theming-and-styling.md` | CSS variables, dark mode, custom themes, semantic colors, BEM classes, variant functions, data attributes |
## Tips
- **Watch the CSS import order.** `@import "tailwindcss"` must come before `@import "@heroui/styles"`. Reversed order silently breaks theming.
- **Use compound components as designed.** HeroUI's `<Modal>` expects `<ModalContent>` + `<ModalHeader>` etc. — don't try to flatten them, accessibility hooks depend on the composition.
- **Theme via CSS variables, not prop overrides.** Changing `--color-primary` in your theme block cascades to every component. Overriding per-component is a smell.
- **React Native setup is heavier.** The native package needs several peer deps at specific versions (Reanimated 4.1+, Gesture Handler 2.28+). Follow the skill's install list exactly — mismatched versions are the #1 setup failure.
## Related skills
- [`stitch-design`](https://github.com/thatjuan/agent-skills) — for high-fidelity screen generation before component implementation
- [`react-components`](https://github.com/thatjuan/agent-skills) — for converting Stitch designs into modular React components
references/native-components.md
# React Native Components Reference
## Table of Contents
- [Provider](#provider)
- [Buttons](#buttons)
- [Collections](#collections)
- [Controls](#controls)
- [Data Display](#data-display)
- [Feedback](#feedback)
- [Forms](#forms)
- [Layout](#layout)
- [Navigation](#navigation)
- [Overlays](#overlays)
- [Utilities](#utilities)
- [Common Patterns](#common-patterns)
All components import from `heroui-native` or granular paths like `heroui-native/button`.
## Provider
The app root requires `HeroUINativeProvider` wrapped in `GestureHandlerRootView`:
```tsx
import { HeroUINativeProvider } from "heroui-native";
import { GestureHandlerRootView } from "react-native-gesture-handler";
<GestureHandlerRootView style={{ flex: 1 }}>
<HeroUINativeProvider>
{/* App */}
</HeroUINativeProvider>
</GestureHandlerRootView>
```
## Buttons
### Button
Interactive pressable component.
```tsx
import { Button } from "heroui-native";
<Button onPress={() => console.log("pressed")}>Label</Button>
```
### CloseButton
Button for closing dialogs, modals, or dismissing content.
### LinkButton
Ghost-variant button with no highlight feedback for inline link-style interactions.
## Collections
### Menu
Floating context menu with positioning, selection groups, and multiple presentation modes.
### TagGroup
Compound component for displaying and managing selectable tags with optional removal.
## Controls
### Slider
Draggable input for selecting a value or range within a bounded interval. Supports `Slider.Output` composition.
### Switch
Toggle control for on/off states.
### Checkbox
Selectable control toggling between checked and unchecked.
## Data Display
### Chip
Compact capsule-shaped element.
### Avatar
User avatar with support for images, text initials, or fallback icons.
## Feedback
### Alert
Important messages with status indicators.
### Spinner
Animated loading indicator.
### Skeleton / SkeletonGroup
Loading placeholders with shimmer or pulse animation. `SkeletonGroup` coordinates multiple skeletons with centralized animation control.
### Toast
Temporary notifications at top or bottom of screen.
## Forms
### TextField
Text input with label, description, and error handling.
```tsx
import { TextField } from "heroui-native";
<TextField label="Name" placeholder="Enter name" />
```
### Input
Styled single-line text input with border and background.
### TextArea
Multiline text input with styled border and background.
### InputGroup
Groups input with optional prefix and suffix decorators.
### InputOTP
One-time password input with individual character slots, animations, and validation.
### SearchField
Compound search input for filtering and querying.
### Select
Option list triggered by a button. Supports single and multi-selection modes.
### NumberField
Not available in native — use Input with numeric keyboard.
### RadioGroup
Radio buttons where only one option can be selected.
### Checkbox
(See Controls section)
### ControlField
Combines label, description, and control (Switch or Checkbox) into a single pressable area.
### Label
Text component for labeling form fields with required indicators and validation states.
### Description
Text for providing accessible descriptions and helper text.
### FieldError
Validation error message with smooth animations.
## Layout
### Card
Card container with flexible layout sections.
```tsx
import { Card } from "heroui-native";
<Card>
<Card.Header>
<Card.Title>Title</Card.Title>
</Card.Header>
<Card.Body>Content</Card.Body>
</Card>
```
### Surface
Container providing elevation and background styling.
### Separator
Simple visual divider.
### Accordion
Collapsible content panels.
### ListGroup
Surface-based container grouping related list items with consistent layout.
### Tabs
Tabbed views with animated transitions and indicators.
## Overlays
### Dialog
Modal overlay with animated transitions and gesture-based dismissal.
### BottomSheet
Slides up from bottom with animated transitions and swipe-to-dismiss. Requires `react-native-screens` (optional `@gorhom/bottom-sheet`).
### Popover
Floating content panel anchored to a trigger element with placement options.
### Toast
Temporary notifications at top or bottom of screen.
## Utilities
### PressableFeedback
Container providing visual feedback for press interactions with automatic scale animation.
### ScrollShadow
Dynamic gradient shadows on scrollable content based on scroll position and overflow.
## Common Patterns
### Granular Imports
```tsx
import { Button } from "heroui-native/button";
import { Card } from "heroui-native/card";
```
### Tailwind Styling via Uniwind
```tsx
<View className="flex-1 justify-center items-center bg-background">
<Button>Styled</Button>
</View>
```
### Full Component Docs
Each component has detailed documentation at:
`https://www.heroui.com/docs/native/components/{component-name}`
references/native-setup.md
# React Native Setup
## Table of Contents
- [Requirements](#requirements)
- [Installation](#installation)
- [CSS Configuration](#css-configuration)
- [Provider Setup](#provider-setup)
- [Granular Imports](#granular-imports)
- [Optional Dependencies](#optional-dependencies)
- [Platform Support](#platform-support)
## Requirements
- React Native
- Uniwind (Tailwind CSS for React Native)
- Mandatory peer dependencies (see Installation)
## Installation
### Step 1: Install HeroUI Native
```bash
npm install heroui-native
```
### Step 2: Install Mandatory Peer Dependencies
```bash
npm install react-native-reanimated@^4.1.1 react-native-gesture-handler@^2.28.0 react-native-worklets@^0.5.1 react-native-safe-area-context@^5.6.0 react-native-svg@^15.12.1 tailwind-variants@^3.2.2 tailwind-merge@^3.4.0
```
### Step 3: Set Up Uniwind
Follow the [Uniwind installation docs](https://uniwind.dev) for Tailwind CSS React Native integration.
### Step 4: Configure global.css
```css
@import "tailwindcss";
@import "uniwind";
@import "heroui-native/styles";
@source "./node_modules/heroui-native/lib";
```
## Provider Setup
Wrap the app with `HeroUINativeProvider` and `GestureHandlerRootView`:
```tsx
import { HeroUINativeProvider } from "heroui-native";
import { GestureHandlerRootView } from "react-native-gesture-handler";
export default function App() {
return (
<GestureHandlerRootView style={{ flex: 1 }}>
<HeroUINativeProvider>
{/* App content */}
</HeroUINativeProvider>
</GestureHandlerRootView>
);
}
```
## Granular Imports
Granular imports reduce bundle size:
```tsx
import { HeroUINativeProvider } from "heroui-native/provider";
import { Button } from "heroui-native/button";
import { Card } from "heroui-native/card";
```
General imports also work:
```tsx
import { Button, Card } from "heroui-native";
```
Available granular export paths: `provider`, `provider-raw`, individual component names, `portal`, `toast`, `utils`, `hooks`.
## Optional Dependencies
| Package | Version | Required For |
|---------|---------|--------------|
| `react-native-screens` | ^4.16.0 | BottomSheet, Dialog, Menu, Popover, Select, Toast |
| `@gorhom/bottom-sheet` | ^5.2.8 | BottomSheet, Menu/Popover/Select with bottom-sheet presentation |
## Platform Support
HeroUI Native targets **iOS and Android only**. For web development, use `@heroui/react` instead.
references/react-components.md
# React Web Components Reference
## Table of Contents
- [Buttons](#buttons)
- [Collections](#collections)
- [Colors](#colors)
- [Controls](#controls)
- [Data Display](#data-display)
- [Date and Time](#date-and-time)
- [Feedback](#feedback)
- [Forms](#forms)
- [Layout](#layout)
- [Media](#media)
- [Navigation](#navigation)
- [Overlays](#overlays)
- [Pickers](#pickers)
- [Typography](#typography)
- [Utilities](#utilities)
- [Common Patterns](#common-patterns)
All components import from `@heroui/react`. All support `className` and standard HTML attributes.
## Buttons
### Button
Clickable element with multiple variants and states.
```tsx
<Button variant="primary" size="md" onPress={handlePress}>
Label
</Button>
```
| Prop | Type | Default |
|------|------|---------|
| `variant` | `"primary" \| "secondary" \| "tertiary" \| "outline" \| "ghost" \| "danger"` | `"primary"` |
| `size` | `"sm" \| "md" \| "lg"` | `"md"` |
| `fullWidth` | `boolean` | `false` |
| `isDisabled` | `boolean` | `false` |
| `isPending` | `boolean` | `false` |
| `isIconOnly` | `boolean` | `false` |
| `onPress` | `(e: PressEvent) => void` | — |
| `render` | `DOMRenderFunction` | — |
CSS: `.button`, `.button--primary`, `.button--sm`, `.button--icon-only`
### ButtonGroup
Groups related buttons with consistent styling and spacing.
```tsx
<ButtonGroup>
<Button>One</Button>
<Button>Two</Button>
</ButtonGroup>
```
### CloseButton
Specialized button for closing dialogs, modals, or dismissing content.
### ToggleButton
Interactive toggle control for on/off or selected/unselected states.
### ToggleButtonGroup
Groups multiple ToggleButtons; supports single or multiple selection.
## Collections
### Dropdown
Displays a list of actions or options.
```tsx
<Dropdown>
<Button>Actions</Button>
<Dropdown.Popover>
<Dropdown.Menu>
<Dropdown.Item id="edit">Edit</Dropdown.Item>
<Dropdown.Item id="delete">Delete</Dropdown.Item>
</Dropdown.Menu>
</Dropdown.Popover>
</Dropdown>
```
### ListBox
Displays a list of selectable options.
```tsx
<ListBox selectionMode="single" aria-label="Options">
<ListBox.Item id="1">Option 1</ListBox.Item>
<ListBox.Item id="2">Option 2</ListBox.Item>
<ListBox.Section>
<ListBox.Header>Group</ListBox.Header>
<ListBox.Item id="3">Option 3</ListBox.Item>
</ListBox.Section>
</ListBox>
```
### TagGroup
Focusable list of tags with keyboard navigation, selection, and removal.
## Colors
### ColorPicker
Composable picker synchronizing color value between multiple color components.
### ColorArea
2D gradient area for selecting colors.
### ColorSlider
Slider for adjusting an individual color channel.
### ColorField
Input field for color values with labels, descriptions, and validation.
### ColorSwatch
Visual preview of a color value with accessibility support.
### ColorSwatchPicker
List of color swatches for selecting from a predefined palette.
## Controls
### Slider
Select one or more values within a range.
### Switch
Toggle between boolean states.
```tsx
<Switch>Dark mode</Switch>
```
| Prop | Type |
|------|------|
| `isSelected` | `boolean` |
| `onChange` | `(isSelected: boolean) => void` |
| `isDisabled` | `boolean` |
## Data Display
### Badge
Small indicator for notification counts, status dots, labels. Positioned relative to another element.
### Chip
Small informational badges for labels, statuses, categories.
### Table
Structured data in rows and columns with sorting, selection, column resizing, infinite scrolling, and virtualization.
```tsx
<Table>
<Table.ScrollContainer>
<Table.Content aria-label="Users" selectionMode="multiple">
<Table.Header>
<Table.Column id="name" isRowHeader>Name</Table.Column>
<Table.Column id="role">Role</Table.Column>
</Table.Header>
<Table.Body>
<Table.Row id="1">
<Table.Cell>Alice</Table.Cell>
<Table.Cell>Admin</Table.Cell>
</Table.Row>
</Table.Body>
</Table.Content>
</Table.ScrollContainer>
<Table.Footer>
<Pagination total={10} />
</Table.Footer>
</Table>
```
Sub-components: `Table`, `Table.ScrollContainer`, `Table.Content`, `Table.Header`, `Table.Column`, `Table.Body`, `Table.Row`, `Table.Cell`, `Table.Footer`, `Table.ColumnResizer`, `Table.ResizableContainer`, `Table.LoadMore`, `Table.LoadMoreContent`, `Table.Collection`.
| Table.Content Prop | Type |
|--------------------|------|
| `selectionMode` | `"none" \| "single" \| "multiple"` |
| `sortDescriptor` | `SortDescriptor` |
| `onSortChange` | `(descriptor: SortDescriptor) => void` |
| `selectedKeys` | `Selection` |
| `onSelectionChange` | `(keys: Selection) => void` |
| Table.Column Prop | Type |
|-------------------|------|
| `allowsSorting` | `boolean` |
| `isRowHeader` | `boolean` |
| `defaultWidth` | `string \| number` |
| Table Prop | Type | Default |
|------------|------|---------|
| `variant` | `"primary" \| "secondary"` | `"primary"` |
CSS: `.table-root`, `.table__scroll-container`, `.table__content`, `.table__header`, `.table__column`, `.table__body`, `.table__row`, `.table__cell`, `.table__footer`
## Date and Time
### Calendar
Composable date picker with month grid, navigation, and year picker. Built on React Aria Calendar.
### RangeCalendar
Date range picker with month grid. Built on React Aria RangeCalendar.
### DateField
Date input field with labels, descriptions, and validation. Built on React Aria DateField.
### DatePicker
Composable date picker combining DateField and Calendar.
### DateRangePicker
Composable date range picker combining DateField and RangeCalendar.
### TimeField
Time input with labels, descriptions, and validation. Built on React Aria TimeField.
## Feedback
### Alert
Important messages and notifications with status indicators.
```tsx
<Alert>
<Alert.Icon />
<Alert.Content>
<Alert.Title>Success</Alert.Title>
<Alert.Description>Changes saved.</Alert.Description>
</Alert.Content>
<Alert.Close />
</Alert>
```
### Meter
Quantity within a known range or fractional value.
### ProgressBar
Determinate or indeterminate linear progress.
### ProgressCircle
Circular progress indicator.
### Skeleton
Loading placeholder showing expected shape of a component.
### Spinner
Animated loading indicator.
### Toast
Temporary notifications with automatic dismissal and customizable placement.
```tsx
import { ToastQueue } from "@heroui/react";
ToastQueue.add({ title: "Saved", description: "Changes saved." });
```
## Forms
### Form
Wrapper for form validation and submission.
```tsx
<Form validationBehavior="aria" onSubmit={handleSubmit}>
<TextField name="email" isRequired>
<Label>Email</Label>
<Input />
<FieldError />
</TextField>
<Button type="submit">Submit</Button>
</Form>
```
| Prop | Type | Default |
|------|------|---------|
| `validationBehavior` | `"native" \| "aria"` | `"native"` |
| `validationErrors` | `ValidationErrors` | — |
| `onSubmit` | `FormEventHandler` | — |
| `onInvalid` | `FormEventHandler` | — |
### TextField
Composition-friendly text field with label, description, and validation.
```tsx
<TextField name="name" isRequired>
<Label>Name</Label>
<Input />
<Description>Enter your full name</Description>
<FieldError />
</TextField>
```
### Input
Primitive single-line text input. Accepts standard HTML input attributes.
### TextArea
Primitive multiline text input.
### InputGroup
Groups input with prefix and suffix elements.
```tsx
<InputGroup>
<InputGroup.Prefix>$</InputGroup.Prefix>
<Input />
<InputGroup.Suffix>.00</InputGroup.Suffix>
</InputGroup>
```
### InputOTP
One-time password input for verification codes.
### NumberField
Number input with increment/decrement buttons, validation, and internationalized formatting.
### SearchField
Search input with clear button and search icon.
### Checkbox / CheckboxGroup
```tsx
<CheckboxGroup>
<Label>Options</Label>
<Checkbox value="a">Option A</Checkbox>
<Checkbox value="b">Option B</Checkbox>
</CheckboxGroup>
```
### RadioGroup
```tsx
<RadioGroup name="color">
<Label>Color</Label>
<RadioGroup.Radio value="red">Red</RadioGroup.Radio>
<RadioGroup.Radio value="blue">Blue</RadioGroup.Radio>
</RadioGroup>
```
### Fieldset
Groups related form controls with legends, descriptions, and actions.
### Label
Accessible label associated with form controls.
### Description
Supplementary text for form fields.
### ErrorMessage / FieldError
Display validation error messages.
## Layout
### Card
Flexible container for grouping related content.
```tsx
<Card>
<Card.Header>
<Card.Title>Title</Card.Title>
</Card.Header>
<Card.Body>Content</Card.Body>
<Card.Footer>Footer</Card.Footer>
</Card>
```
### Surface
Container providing surface-level styling and context.
### Separator
Visual divider between content sections.
### Toolbar
Container for interactive controls with arrow key navigation.
## Media
### Avatar
User profile images with customizable fallback content.
```tsx
<Avatar src="/photo.jpg" alt="User" />
```
## Navigation
### Tabs
Organize content into multiple sections.
```tsx
<Tabs>
<Tabs.List>
<Tabs.Tab id="1">Tab 1</Tabs.Tab>
<Tabs.Tab id="2">Tab 2</Tabs.Tab>
</Tabs.List>
<Tabs.Panel id="1">Content 1</Tabs.Panel>
<Tabs.Panel id="2">Content 2</Tabs.Panel>
</Tabs>
```
### Accordion
Collapsible content panels.
```tsx
<Accordion>
<Accordion.Item id="1">
<Accordion.Trigger>Section 1</Accordion.Trigger>
<Accordion.Panel>Content 1</Accordion.Panel>
</Accordion.Item>
</Accordion>
```
### Breadcrumbs
Navigation breadcrumbs showing location within a hierarchy.
### Disclosure / DisclosureGroup
Collapsible sections with header and content.
### Link
Styled anchor with built-in icon support.
### Pagination
Page navigation with composable page links, previous/next buttons, and ellipsis.
## Overlays
### Modal
Dialog overlay for focused interactions.
```tsx
<Modal>
<Button>Open Modal</Button>
<Modal.Backdrop>
<Modal.Container size="md" placement="center">
<Modal.Dialog>
<Modal.CloseTrigger />
<Modal.Header>
<Modal.Heading>Title</Modal.Heading>
</Modal.Header>
<Modal.Body>Content</Modal.Body>
<Modal.Footer>
<Button slot="close">Close</Button>
</Modal.Footer>
</Modal.Dialog>
</Modal.Container>
</Modal.Backdrop>
</Modal>
```
| Sub-component | Key Props |
|---------------|-----------|
| `Modal.Backdrop` | `variant: "opaque" \| "blur" \| "transparent"`, `isDismissable`, `isOpen`, `onOpenChange` |
| `Modal.Container` | `size: "xs" \| "sm" \| "md" \| "lg" \| "cover" \| "full"`, `placement: "auto" \| "center" \| "top" \| "bottom"`, `scroll: "inside" \| "outside"` |
### AlertDialog
Modal dialog for critical confirmations requiring explicit user action.
### Drawer
Slide-out panel for supplementary content.
### Popover
Rich content in a portal triggered by a button or custom element.
### Tooltip
Informative text on hover or focus.
```tsx
<Tooltip>
<Button>Hover me</Button>
<Tooltip.Content>Tooltip text</Tooltip.Content>
</Tooltip>
```
## Pickers
### Select
Collapsible option list for single or multiple selection.
```tsx
<Select>
<Label>Country</Label>
<Select.Trigger>
<Select.Value placeholder="Pick a country" />
<Select.Indicator />
</Select.Trigger>
<Select.Popover>
<ListBox>
<ListBox.Item id="us">United States</ListBox.Item>
<ListBox.Item id="uk">United Kingdom</ListBox.Item>
</ListBox>
</Select.Popover>
<Description>Select your country</Description>
</Select>
```
| Prop | Type | Default |
|------|------|---------|
| `selectionMode` | `"single" \| "multiple"` | `"single"` |
| `variant` | `"primary" \| "secondary"` | `"primary"` |
| `isDisabled` | `boolean` | — |
| `isRequired` | `boolean` | — |
| `isInvalid` | `boolean` | — |
| `fullWidth` | `boolean` | `false` |
### ComboBox
Text input combined with a listbox for filtering options.
### Autocomplete
Select with filtering, searching, and selecting from a list.
## Typography
### Kbd
Display keyboard shortcuts and key combinations.
```tsx
<Kbd>Ctrl+S</Kbd>
```
## Utilities
### ScrollShadow
Visual shadows indicating scrollable content overflow.
## Common Patterns
### Dynamic Collections
```tsx
<Table.Body items={users}>
{(user) => (
<Table.Row id={user.id}>
<Table.Cell>{user.name}</Table.Cell>
</Table.Row>
)}
</Table.Body>
```
### Controlled State
```tsx
const [value, setValue] = useState<Key | null>(null);
<Select value={value} onChange={setValue}>
{/* ... */}
</Select>
```
### Overlay State Hook
```tsx
const state = useOverlayState({ defaultOpen: false });
// state.isOpen, state.open(), state.close(), state.toggle()
```
### Slot-Based Closing
```tsx
<Button slot="close">Close</Button>
```
Any button with `slot="close"` inside an overlay automatically closes it.
### Full Component Docs
Each component has detailed documentation at:
`https://www.heroui.com/docs/react/components/{component-name}`
references/react-setup.md
# React (Web) Setup
## Table of Contents
- [Requirements](#requirements)
- [Installation](#installation)
- [CSS Configuration](#css-configuration)
- [Selective Imports](#selective-imports)
- [Framework Integration](#framework-integration)
## Requirements
- React 19+
- Tailwind CSS v4
## Installation
```bash
# npm
npm i @heroui/styles @heroui/react
# pnpm
pnpm add @heroui/styles @heroui/react
# yarn
yarn add @heroui/styles @heroui/react
# bun
bun add @heroui/styles @heroui/react
```
## CSS Configuration
Add to `globals.css` (import order matters):
```css
@import "tailwindcss";
@import "@heroui/styles";
```
### Selective Import with Layer Control
```css
@layer theme, base, components, utilities;
@import "tailwindcss";
@import "@heroui/styles/base" layer(base);
@import "@heroui/styles/themes/default" layer(theme);
@import "@heroui/styles/components" layer(components);
```
### Component-Specific Imports
```css
@import "@heroui/styles/components/button.css" layer(components);
@import "@heroui/styles/components/accordion.css" layer(components);
```
### Headless Mode (Custom Styles Only)
```css
@import "tailwindcss";
@import "@heroui/styles/base/base.css";
.button {
/* custom button styles */
}
```
## Selective Imports
Components are importable from the main package:
```tsx
import { Button, Modal, Table } from "@heroui/react";
```
Variant functions are available from either package:
```tsx
import { buttonVariants } from "@heroui/styles";
// or
import { buttonVariants } from "@heroui/react";
```
Use `@heroui/styles` to avoid React dependencies (for Vue, Svelte, etc.).
## Framework Integration
### Next.js
```tsx
import Link from "next/link";
import { buttonVariants } from "@heroui/styles";
<Link className={buttonVariants({ variant: "primary" })} href="/dashboard">
Dashboard
</Link>
```
### React Router
```tsx
import { Link } from "react-router-dom";
import { buttonVariants } from "@heroui/styles";
<Link className={buttonVariants({ variant: "primary" })} to="/dashboard">
Dashboard
</Link>
```
### Vue / Svelte / Other Frameworks
```ts
import { buttonVariants } from "@heroui/styles";
const primaryButton = buttonVariants({ variant: "primary" });
// Apply in template
```
### HTML Setup
```html
<html class="light" data-theme="light">
<body class="bg-background text-foreground">
<!-- App content -->
</body>
</html>
```
references/theming-and-styling.md
# Theming and Styling
## Table of Contents
- [Theming System](#theming-system)
- [Color Variables](#color-variables)
- [Dark Mode](#dark-mode)
- [Custom Themes](#custom-themes)
- [Custom Semantic Colors](#custom-semantic-colors)
- [Component-Level Overrides](#component-level-overrides)
- [Styling Methods](#styling-methods)
- [Variant Functions](#variant-functions)
- [Custom Variants](#custom-variants)
- [BEM Class Reference](#bem-class-reference)
- [Data Attributes for Interactive States](#data-attributes-for-interactive-states)
## Theming System
HeroUI v3 uses CSS variables and BEM classes for theming. Built on Tailwind CSS v4's theme system with automatic light/dark switching and CSS layers.
### Naming Convention
- **Background colors**: Variables without suffix (e.g., `--accent`)
- **Foreground colors**: Variables with `-foreground` suffix (e.g., `--accent-foreground`)
## Color Variables
Override in `:root` or theme selectors:
```css
@import "tailwindcss";
@import "@heroui/styles";
:root {
--accent: oklch(0.7 0.25 260);
--success: oklch(0.65 0.15 155);
}
```
### Variable Categories
| Type | Description | Examples |
|------|-------------|---------|
| Base | Non-changing values | `--white`, `--black`, spacing, typography |
| Theme | Shift between light/dark | `--accent`, `--background`, `--foreground` |
| Calculated | Auto-generated states | Hover, focus variants via `@theme` |
### Field Control Variables
Form controls (inputs, checkboxes, radios, OTP slots) use `--field-*` variables. Update these to restyle form components independently from buttons or cards.
## Dark Mode
Toggle via HTML class and data attribute:
```html
<!-- Light -->
<html class="light" data-theme="light">
<!-- Dark -->
<html class="dark" data-theme="dark">
```
## Custom Themes
Define in separate CSS files with light/dark variants:
```css
@layer base {
[data-theme="ocean"] {
color-scheme: light;
--accent: oklch(0.6 0.2 240);
--background: oklch(0.97 0.01 240);
--foreground: oklch(0.2 0.02 240);
}
[data-theme="ocean-dark"] {
color-scheme: dark;
--accent: oklch(0.7 0.18 240);
--background: oklch(0.15 0.02 240);
--foreground: oklch(0.95 0.01 240);
}
}
```
Apply in globals with layer prioritization:
```css
@layer theme, base, components, utilities;
@import "tailwindcss";
@import "@heroui/styles";
@import "./src/themes/ocean.css" layer(theme);
```
## Custom Semantic Colors
Add colors for both light and dark themes, then register with Tailwind:
```css
:root,
[data-theme="light"] {
--info: oklch(0.6 0.15 210);
--info-foreground: oklch(0.98 0 0);
}
.dark,
[data-theme="dark"] {
--info: oklch(0.7 0.12 210);
--info-foreground: oklch(0.15 0 0);
}
@theme inline {
--color-info: var(--info);
--color-info-foreground: var(--info-foreground);
}
```
Usage:
```tsx
<div className="bg-info text-info-foreground">Info message</div>
```
## Component-Level Overrides
Override component styles globally using BEM classes in `@layer components`:
```css
@layer components {
.button {
@apply font-semibold tracking-wide;
}
.button--primary {
@apply bg-blue-600 hover:bg-blue-700;
}
.accordion__trigger {
@apply text-lg font-bold;
}
.select__trigger {
@apply rounded-lg border border-border bg-surface p-2;
}
}
```
## Styling Methods
### 1. className Prop
```tsx
<Button className="rounded-full shadow-lg font-bold">Styled</Button>
```
### 2. Inline Styles
```tsx
<Button style={{ borderRadius: "9999px" }}>Rounded</Button>
```
### 3. CSS Modules
```tsx
import styles from "./MyComponent.module.css";
<Button className={styles.customButton}>Styled</Button>
```
### 4. CSS-in-JS (Styled Components / Emotion)
```tsx
const StyledButton = styled(Button)`
border-radius: 9999px;
`;
```
### 5. Global Stylesheet
```css
@layer components {
.table-root {
@apply relative grid w-full overflow-clip;
}
.table__header {
@apply bg-gray-100;
}
.table__row {
@apply bg-white border-b border-gray-200;
}
}
```
### 6. Render Props for State-Based Styling
```tsx
<Button>
{({ isPressed }) => (
<span className={isPressed ? "text-white" : "text-gray-800"}>
Press me
</span>
)}
</Button>
```
## Variant Functions
Type-safe styling available from `@heroui/styles` or `@heroui/react`:
```tsx
import { buttonVariants } from "@heroui/styles";
// Apply to any element
<a className={buttonVariants({ variant: "primary", size: "lg" })} href="/about">
About
</a>
```
Available functions: `buttonVariants`, `chipVariants`, `linkVariants`, `spinnerVariants`, and component-specific functions.
### Slot-Based Variant Functions
Some components expose slot functions:
```tsx
const slots = linkVariants();
<a className={slots.base()} href="/about">
About
<span className={slots.icon()} />
</a>
```
## Custom Variants
Extend base variant functions with `tv()`:
```tsx
import { buttonVariants, tv } from "@heroui/styles";
const myButton = tv({
extend: buttonVariants,
base: "text-md font-semibold shadow-md",
variants: {
radius: {
lg: "rounded-lg",
md: "rounded-md",
},
},
});
<button className={myButton({ variant: "primary", radius: "lg" })}>
Custom
</button>
```
## BEM Class Reference
### Pattern
- Block: `.button`, `.modal`, `.table-root`
- Element: `.modal__header`, `.table__cell`
- Modifier: `.button--primary`, `.button--lg`, `.modal__backdrop--blur`
### Common Component Classes
| Component | Base | Elements | Modifiers |
|-----------|------|----------|-----------|
| Button | `.button` | — | `--primary`, `--secondary`, `--tertiary`, `--outline`, `--ghost`, `--danger`, `--sm`, `--md`, `--lg`, `--icon-only` |
| Modal | `.modal` | `__trigger`, `__backdrop`, `__container`, `__dialog`, `__header`, `__body`, `__footer`, `__close-trigger` | `__backdrop--opaque`, `__backdrop--blur`, `__backdrop--transparent` |
| Table | `.table-root` | `__scroll-container`, `__content`, `__header`, `__column`, `__body`, `__row`, `__cell`, `__footer` | `--primary`, `--secondary` |
| Select | `.select` | `__trigger`, `__value`, `__indicator`, `__popover` | `--primary`, `--secondary` |
| Card | `.card` | `__header`, `__body`, `__footer`, `__title` | — |
| Accordion | `.accordion` | `__item`, `__trigger`, `__panel` | — |
| Alert | `.alert` | `__icon`, `__content`, `__title`, `__description`, `__close` | — |
## Data Attributes for Interactive States
| State | Data Attribute | CSS Pseudo |
|-------|---------------|------------|
| Hovered | `[data-hovered="true"]` | `:hover` |
| Pressed | `[data-pressed="true"]` | `:active` |
| Focused | `[data-focus-visible="true"]` | `:focus-visible` |
| Disabled | `[aria-disabled="true"]` | `:disabled` |
| Selected | `[data-selected="true"]` | — |
| Open | `[data-open="true"]` | — |
| Entering | `[data-entering]` | — |
| Exiting | `[data-exiting]` | — |
| Invalid | `[data-invalid="true"]` | — |
| Pending | `[data-pending]` | — |
| Placeholder | `[data-placeholder="true"]` | — |
| Allows Sorting | `[data-allows-sorting="true"]` | — |
| Dragging | `[data-dragging="true"]` | — |
| Drop Target | `[data-drop-target="true"]` | — |
### Targeting States in CSS
```css
.button[data-hovered="true"] {
transform: translateY(-1px);
}
.table__row[data-selected="true"] {
background-color: var(--accent);
}
```
### Targeting States with Tailwind
```tsx
<Button className="data-[hovered=true]:scale-105 data-[pressed=true]:scale-95">
Interactive
</Button>
```
### Color Format
OKLCH is the recommended format for color variables:
```css
--accent: oklch(0.7 0.25 260);
```
### Theme Builder
Visual tool at https://www.heroui.com/themes for customizing colors, radius, fonts.
SKILL.md
---
name: heroui
description: HeroUI v3 component library expertise for React (web) and React Native (mobile). Use when code imports @heroui/react, @heroui/styles, or heroui-native, user asks to build UI with HeroUI, or references HeroUI components, theming, or migration from NextUI/HeroUI v2.
---
# HeroUI v3
An open-source UI component library for React (web) and React Native (mobile). Built on Tailwind CSS v4 and React Aria Components. Provides 75+ accessible, customizable web components and 40+ native components.
## Technology Stack
| Platform | Package | Requires |
|----------|---------|----------|
| React (Web) | `@heroui/react`, `@heroui/styles` | React 19+, Tailwind CSS v4 |
| React Native | `heroui-native` | React Native, Uniwind, react-native-reanimated 4.1+, react-native-gesture-handler 2.28+ |
## Quick Setup
### React (Web)
```bash
npm i @heroui/react @heroui/styles
```
```css
/* globals.css — order matters */
@import "tailwindcss";
@import "@heroui/styles";
```
```tsx
import { Button } from "@heroui/react";
function App() {
return <Button>Click me</Button>;
}
```
### React Native
```bash
npm install heroui-native react-native-reanimated@^4.1.1 react-native-gesture-handler@^2.28.0 react-native-worklets@^0.5.1 react-native-safe-area-context@^5.6.0 react-native-svg@^15.12.1 tailwind-variants@^3.2.2 tailwind-merge@^3.4.0
```
```css
/* global.css */
@import "tailwindcss";
@import "uniwind";
@import "heroui-native/styles";
@source "./node_modules/heroui-native/lib";
```
```tsx
import { HeroUINativeProvider } from "heroui-native";
import { GestureHandlerRootView } from "react-native-gesture-handler";
import { Button } from "heroui-native";
export default function App() {
return (
<GestureHandlerRootView style={{ flex: 1 }}>
<HeroUINativeProvider>
<Button onPress={() => console.log("Pressed!")}>Get Started</Button>
</HeroUINativeProvider>
</GestureHandlerRootView>
);
}
```
For detailed setup instructions, see [react-setup.md](references/react-setup.md) and [native-setup.md](references/native-setup.md).
## Component Architecture
HeroUI v3 uses **compound component composition** with dot notation:
```tsx
<Modal>
<Button>Open</Button>
<Modal.Backdrop>
<Modal.Container>
<Modal.Dialog>
<Modal.Header>
<Modal.Heading>Title</Modal.Heading>
</Modal.Header>
<Modal.Body>Content</Modal.Body>
<Modal.Footer>
<Button slot="close">Close</Button>
</Modal.Footer>
</Modal.Dialog>
</Modal.Container>
</Modal.Backdrop>
</Modal>
```
### Three Import Patterns
```tsx
// 1. Compound (recommended)
<Alert>
<Alert.Icon />
<Alert.Content>
<Alert.Title>Success</Alert.Title>
</Alert.Content>
</Alert>
// 2. With .Root suffix
<Alert.Root>
<Alert.Icon />
</Alert.Root>
// 3. Named exports
import { AlertRoot, AlertIcon, AlertContent, AlertTitle } from "@heroui/react";
```
### Type Imports
```tsx
import type { ButtonRootProps, AvatarRootProps } from "@heroui/react";
```
## React Web Components (75+)
| Category | Components |
|----------|------------|
| Buttons | Button, ButtonGroup, CloseButton, ToggleButton, ToggleButtonGroup |
| Collections | Dropdown, ListBox, TagGroup |
| Colors | ColorArea, ColorField, ColorPicker, ColorSlider, ColorSwatch, ColorSwatchPicker |
| Controls | Slider, Switch |
| Data Display | Badge, Chip, Table |
| Date & Time | Calendar, DateField, DatePicker, DateRangePicker, RangeCalendar, TimeField |
| Feedback | Alert, Meter, ProgressBar, ProgressCircle, Skeleton, Spinner, Toast |
| Forms | Checkbox, CheckboxGroup, Description, ErrorMessage, FieldError, Fieldset, Form, Input, InputGroup, InputOTP, Label, NumberField, RadioGroup, SearchField, TextField, TextArea |
| Layout | Card, Separator, Surface, Toolbar |
| Media | Avatar |
| Navigation | Accordion, Breadcrumbs, Disclosure, DisclosureGroup, Link, Pagination, Tabs |
| Overlays | AlertDialog, Drawer, Modal, Popover, Tooltip |
| Pickers | Autocomplete, ComboBox, Select |
| Typography | Kbd |
| Utilities | ScrollShadow |
For component anatomy, props, and usage patterns, see [react-components.md](references/react-components.md).
## React Native Components (40+)
| Category | Components |
|----------|------------|
| Buttons | Button, CloseButton, LinkButton |
| Collections | Menu, TagGroup |
| Controls | Slider, Switch, Checkbox |
| Data Display | Chip, Avatar |
| Feedback | Alert, Spinner, Skeleton, SkeletonGroup, Toast |
| Forms | ControlField, Description, FieldError, Input, InputGroup, InputOTP, Label, RadioGroup, SearchField, Select, TextArea, TextField |
| Layout | Card, Separator, Surface, Accordion, ListGroup, Tabs |
| Overlays | BottomSheet, Dialog, Popover |
| Utilities | PressableFeedback, ScrollShadow |
For native component details, see [native-components.md](references/native-components.md).
## Styling System
HeroUI v3 provides three styling approaches:
### 1. BEM Classes
```tsx
<button className="button button--primary button--lg">Click</button>
```
Class pattern: `.{block}`, `.{block}__{element}`, `.{block}--{modifier}`
### 2. Variant Functions (Type-Safe)
```tsx
import { buttonVariants } from "@heroui/styles";
<a className={buttonVariants({ variant: "primary", size: "lg" })} href="/about">
About
</a>
```
Variant functions are framework-agnostic — usable with Vue, Svelte, vanilla HTML.
### 3. Tailwind CSS Classes + className Prop
```tsx
<Button className="rounded-full shadow-lg">Styled</Button>
```
### Custom Variants
```tsx
import { buttonVariants, tv } from "@heroui/styles";
const myButton = tv({
extend: buttonVariants,
base: "font-semibold shadow-md",
variants: {
radius: { lg: "rounded-lg", md: "rounded-md" },
},
});
```
### render Prop for Custom Elements
```tsx
<Button
render={(domProps, { isPressed }) => (
<motion.button {...domProps} animate={{ scale: isPressed ? 0.9 : 1 }} />
)}
>
Animated
</Button>
```
For theming, CSS variables, dark mode, custom themes, and component-level overrides, see [theming-and-styling.md](references/theming-and-styling.md).
## Common Prop Patterns
### Interactive States (Data Attributes)
| State | Attribute | CSS Pseudo |
|-------|-----------|------------|
| Hover | `[data-hovered="true"]` | `:hover` |
| Pressed | `[data-pressed="true"]` | `:active` |
| Focus | `[data-focus-visible="true"]` | `:focus-visible` |
| Disabled | `[aria-disabled="true"]` | `:disabled` |
| Selected | `[data-selected="true"]` | — |
| Open | `[data-open="true"]` | — |
| Entering | `[data-entering]` | — |
| Exiting | `[data-exiting]` | — |
### Event Handlers
HeroUI uses React Aria's press events, not native click events:
```tsx
<Button onPress={(e) => console.log("pressed")} />
```
### Overlay State Management
```tsx
import { useOverlayState } from "@heroui/react";
const state = useOverlayState({ defaultOpen: false });
// state.isOpen, state.open(), state.close(), state.toggle(), state.setOpen()
```
## Form Validation
```tsx
import { Form, TextField, Button } from "@heroui/react";
<Form validationBehavior="aria" onSubmit={handleSubmit}>
<TextField name="email" isRequired>
<Label>Email</Label>
<Input />
<FieldError />
</TextField>
<Button type="submit">Submit</Button>
</Form>
```
Two validation modes: `"native"` (blocks submission) and `"aria"` (realtime errors).
## Documentation Resources
| Resource | URL |
|----------|-----|
| React Docs | https://www.heroui.com/docs/react/getting-started |
| Native Docs | https://www.heroui.com/docs/native/getting-started |
| All React Components | https://www.heroui.com/docs/react/components |
| All Native Components | https://www.heroui.com/docs/native/components |
| Theme Builder | https://www.heroui.com/themes |
| Migration (v2 to v3) | https://www.heroui.com/docs/react/migration |