apps/docs/content/docs/react/releases/v3-0-0.mdx
<VideoPlayer src="https://heroui-assets.nyc3.cdn.digitaloceanspaces.com/videos/heroui-v3-release.mp4" height={430} muted />
Every component rewritten. Every animation moved to CSS. Styles decoupled from implementation. A brand-new React Native library. And tooling that treats AI assistants as a primary development interface.
75+ components. React Aria Components for accessibility. Tailwind CSS v4 + CSS variables for theming. Styles in a standalone package you can use with any framework.
37 components with shared design tokens, compound pattern, unified animation API, and adaptive presentation modes. Built native on each platform with Uniwind for Tailwind CSS v4 support.
<VideoPlayer src="https://heroui-assets.nyc3.cdn.digitaloceanspaces.com/videos/heroui-native-v1-release-.mp4" playMode="manual" height={430} muted />
<DocsImage src="https://heroui-assets.nyc3.cdn.digitaloceanspaces.com/docs/[email protected]" darkSrc="https://heroui-assets.nyc3.cdn.digitaloceanspaces.com/docs/[email protected]" alt="HeroUI Pro" href="https://heroui.pro" />
Premium components, templates, and AI tooling for React and React Native. Command palette, Kanban, DataGrid, Dashboard templates, and more. Pre-sale pricing at heroui.pro.
Composition over configuration: v2 components were black boxes. v3 adopts compound components: every internal piece is a real element you can style, move, swap, or remove.
Styles separated from implementation: @heroui/styles is standalone CSS. @heroui/react handles behavior. Use the styles with React, plain HTML + Tailwind, or any framework. BEM class names make every slot customizable globally. Swap themes to change not just variables, but how components look and feel.
Headless when you want it: Remove the @heroui/styles import and you have a headless library. We maintain functionality and accessibility. You focus on your product.
Performance by default: v2 used Framer Motion for every animation. v3 replaced it with native CSS transitions and keyframes. Lighter bundles, GPU-accelerated, no JS animation runtime.
Accessible from the start: Migrated from React Aria hooks to React Aria Components. Keyboard navigation, focus management, screen readers, and ARIA attributes are built in.
Here's what the compound pattern looks like in practice:
<Card>
<Card.Header>
<Card.Title>Product</Card.Title>
<Card.Description>Details about this product.</Card.Description>
</Card.Header>
<Card.Body>
<p>Card content goes here.</p>
</Card.Body>
<Card.Footer>
<Button variant="primary">Buy now</Button>
</Card.Footer>
</Card>
More lines of code. But every piece is a real element you can style, move, or replace. The pattern runs through the entire library, from Accordion to Toast.
<ComponentPreview name="accordion-basic" />
Each compound component shares state through React context. The root component creates a style context, and every child consumes it. You never pass classNames down manually:
<Alert status="success">
<Alert.Indicator />
<Alert.Content>
<Alert.Title>Profile updated</Alert.Title>
<Alert.Description>Your changes have been saved.</Alert.Description>
</Alert.Content>
</Alert>
<ComponentPreview name="alert-basic" />
Components support both simple and compound usage. Start with the one-liner. Add structure when you need it:
// One line
<Button>Submit</Button>
// With icon
<Button>
<Icon icon="gravity-ui:check" />
Submit
</Button>
// Full control
<Button variant="primary" size="lg" isDisabled={isLoading}>
{isLoading ? <Spinner size="sm" /> : <Icon icon="gravity-ui:check" />}
{isLoading ? "Saving..." : "Submit"}
</Button>
<ComponentPreview name="button-variants" />
Theming runs on Tailwind CSS v4's native CSS variable layer with OKLCH colors. Every design token is a CSS variable:
:root {
--background: oklch(0.9702 0 0);
--foreground: oklch(0.2103 0.0059 285.89);
--accent: oklch(0.6204 0.195 253.83);
--surface: oklch(100% 0 0);
--danger: oklch(0.6532 0.2328 25.74);
--radius: 0.5rem;
}
Tailwind's @theme directive maps these tokens to utility classes. bg-accent, text-foreground, rounded-lg all resolve to CSS variables. Light and dark mode switch by swapping the values:
.dark, [data-theme="dark"] {
--background: oklch(12% 0.005 285.823);
--foreground: oklch(0.9911 0 0);
--surface: oklch(0.2103 0.0059 285.89);
}
No provider component. No JavaScript theme object. One CSS import, two lines:
@import "tailwindcss";
@import "@heroui/styles";
Override any component globally through standard CSS:
@layer components {
.button {
@apply font-semibold tracking-wide;
}
.button--primary {
@apply bg-blue-600 hover:bg-blue-700;
}
}
No className threading. No style prop gymnastics. Your design system overrides happen in CSS, where they belong.
Create a theme by defining your own token set. Everything cascades from there:
@layer base {
[data-theme="ocean"] {
--accent: oklch(0.450 0.150 230);
--background: oklch(0.985 0.015 225);
--radius: 0.75rem;
--border: oklch(0.50 0.060 230 / 22%);
}
}
Apply it with a single data attribute:
<html data-theme="ocean">
The Theme Builder generates these variables visually. Pick colors, adjust radius and spacing, export the CSS.
Import the full library or pick individual component styles:
@import "tailwindcss";
@import "@heroui/styles/base" layer(base);
@import "@heroui/styles/themes/default" layer(theme);
@import "@heroui/styles/components/button.css" layer(components);
@import "@heroui/styles/components/card.css" layer(components);
Ship only the CSS you use. No unused component styles in production.
All component animations use CSS transitions and keyframes tied to data attributes. Popovers fade in with [data-entering]. Buttons scale on [data-pressed]. Accordions expand with [aria-hidden="false"].
.popover[data-entering] {
@apply animate-in zoom-in-90 fade-in-0 duration-200;
}
.button:active,
.button[data-pressed="true"] {
transform: scale(0.97);
}
Some users need animations disabled. HeroUI extends Tailwind's motion-reduce: variant to support both the system preference and a data attribute:
.button {
@apply transition-colors motion-reduce:transition-none;
}
This responds to the native prefers-reduced-motion: reduce media query. It also responds to data-reduce-motion="true" on the HTML element, for app-level control:
<html data-reduce-motion="true">
<!-- All HeroUI animations are disabled -->
</html>
The data attribute overrides the system setting. Set data-reduce-motion="false" to force animations on, or remove the attribute to defer to the OS. Every animated component respects this. No opt-in required.
Framer Motion, Motion One, or any CSS animation library works alongside HeroUI's built-in transitions:
import { motion } from "framer-motion";
import { Button } from "@heroui/react";
const MotionButton = motion(Button);
<MotionButton whileHover={{ scale: 1.05 }} whileTap={{ scale: 0.95 }}>
Animated
</MotionButton>
Six components: Calendar, RangeCalendar, DateField, DatePicker, DateRangePicker, and TimeField. Built on React Aria's internationalized date library with Gregorian, Buddhist, Persian, and other calendar systems by default. Keyboard navigation, screen reader labels, and locale-aware formatting come free.
<ComponentPreview name="date-picker-basic" />
<ComponentPreview name="range-calendar-basic" />
Six color components: ColorPicker, ColorArea, ColorSlider, ColorField, ColorSwatch, and ColorSwatchPicker. Pick from a 2D area, adjust hue and alpha sliders, enter hex values, or select from a swatch palette.
<ComponentPreview name="color-picker-basic" />
Need a table with sorting, row selection, column resizing, async loading, and custom cells? Table does all of that. Large datasets get virtualization via React Aria's Virtualizer. ListBox shares the same virtualization support.
<ComponentPreview name="table-virtualization" />
Thirteen form components: TextField, Select, Autocomplete, ComboBox, Checkbox, CheckboxGroup, RadioGroup, Switch, InputOTP, NumberField, SearchField, Slider, and Fieldset. All integrate with React Aria's form validation. isRequired, isInvalid, and custom error messages through FieldError work across every one.
<ComponentPreview name="select-default" />
<ComponentPreview name="input-otp-basic" />
Seven overlay components. Drawer supports four placements with drag-to-dismiss gestures. Toast stacks notifications with auto-dismiss and promise support. Menu composes with submenus and sections. Plus Modal, AlertDialog, Popover, and Tooltip.
<ComponentPreview name="drawer-basic" />
<ComponentPreview name="toast-default" />
Tabs, Accordion, Breadcrumbs, Pagination, and Link. Tabs support horizontal and vertical orientation. Accordion supports single or multiple expanded panels.
<ComponentPreview name="tabs-basic" />
ProgressBar and ProgressCircle handle determinate + indeterminate states. Meter maps values to semantic colors: green for safe, yellow for cautious, red for critical. Skeleton and Spinner round out the set.
<ComponentPreview name="meter-colors" />
<ComponentPreview name="skeleton-basic" />
Button, ButtonGroup, ToggleButton, ToggleButtonGroup, CloseButton, and Toolbar. ButtonGroup connects buttons with shared borders and supports vertical orientation. Toolbar groups buttons, toggles, and separators into an accessible role="toolbar" container.
<ComponentPreview name="toggle-button-group-attached" />
Import from the root or from per-component subpaths. Both work:
// Root import
import { Button, Card, Table } from "@heroui/react";
// Subpath import
import { Button } from "@heroui/react/button";
import { Card } from "@heroui/react/card";
import { Table } from "@heroui/react/table";
More developers build by prompting than by reading API docs. HeroUI v3 accounts for that.
The HeroUI MCP Server connects AI coding assistants (Cursor, Claude Code, VS Code Copilot, Windsurf, Zed) to component docs, props, source code, CSS styles, and theme variables. The AI reads the source of truth directly instead of guessing from training data.
{
"mcpServers": {
"heroui-react": {
"command": "npx",
"args": ["-y", "@heroui/react-mcp@latest"]
}
}
}
Ask your AI assistant "update HeroUI to the latest version" and it will compare versions, review the changelog for breaking changes, and apply the necessary code updates automatically.
Installable knowledge packs for Cursor and Claude Code. Component patterns, variant usage, theming instructions, and upgrade guides. Preloaded context so the AI writes correct HeroUI code on the first attempt.
Structured documentation files optimized for AI context windows. Published at /llms.txt and /llms-components.txt, these give any LLM-powered tool a machine-readable summary of HeroUI's API surface.
MCP server, agent skills, LLMs.txt. Three layers that give AI assistants the same access to HeroUI that human developers get from docs.
<VideoPlayer src="https://heroui-assets.nyc3.cdn.digitaloceanspaces.com/videos/heroui-native-v1-release-.mp4" height={430} muted />
HeroUI Native is a brand-new library shipping alongside v3 for the web. Different rendering engine, same mental model. Where the platforms diverge, the APIs adapt to feel native on each.
Scan the QR code with your device's camera or Expo Go to explore all 37 components live:
<div className="flex justify-center my-6"> </div> <div className="flex justify-center"> **[📱 Open Demo App in Expo Go](https://link.heroui.com/native-demo)** </div> <Callout type="info"> **Android users:** If scanning the QR code redirects to a browser and shows a 404 error, open Expo Go first and use its built-in QR scanner instead. </Callout>Forms, navigation, overlays, feedback, layout. From Button, Input, and Checkbox to Dialog, BottomSheet, Select, Toast, and InputOTP. Components follow the compound pattern:
import { Dialog, Button } from "heroui-native";
<Dialog>
<Dialog.Trigger asChild>
<Button variant="primary">Open</Button>
</Dialog.Trigger>
<Dialog.Portal>
<Dialog.Overlay />
<Dialog.Content>
<Dialog.Close />
<Dialog.Title>Confirm action</Dialog.Title>
<Dialog.Description>This cannot be undone.</Dialog.Description>
</Dialog.Content>
</Dialog.Portal>
</Dialog>
If you know HeroUI on the web, most of that knowledge carries over. Familiar component names, dot notation, and prop patterns wherever possible. Where the platforms diverge (layout primitives, gestures, navigation), the APIs adapt to feel native. The mental model stays the same:
// React (web)
<Alert status="success">
<Alert.Indicator />
<Alert.Content>
<Alert.Title>Profile updated</Alert.Title>
<Alert.Description>Your changes have been saved.</Alert.Description>
</Alert.Content>
</Alert>
// React Native — similar API, native behavior
<Alert status="success">
<Alert.Indicator />
<Alert.Content>
<Alert.Title>Profile updated</Alert.Title>
<Alert.Description>Your changes have been saved.</Alert.Description>
</Alert.Content>
</Alert>
Teams working on both web and mobile share knowledge and patterns. The learning curve between platforms is minimal, even where the components differ.
Both platforms read from the same token set. Colors like accent, surface, danger, and success resolve identically across web and native. Your brand stays consistent without maintaining two separate systems.
import { View, Text } from "react-native";
<View className="bg-surface p-4 rounded-lg">
<Text className="text-foreground text-lg font-semibold">Card Title</Text>
<Text className="text-muted text-sm">Consistent on web and mobile.</Text>
</View>
Tailwind CSS v4 on both platforms. Uniwind on native, standard Tailwind on web.
<VideoPlayer src="https://heroui-assets.nyc3.cdn.digitaloceanspaces.com/videos/native-v1-demo/v-1-demo-2.mp4" height={430} muted />
Every animated native component exposes a single animation prop. Values, timing, spring configs, enter/exit transitions controlled from one place. Reanimated powers the math, but you never touch it directly:
import { Switch } from "heroui-native";
<Switch
animation={{
scale: { value: [1, 0.9] },
backgroundColor: { value: ["#172554", "#eab308"] },
}}
>
<Switch.Thumb />
</Switch>
Disable animations at any level. Per-component, per-tree, or globally:
// Single component
<Switch.Thumb animation={false} />
// Entire subtree
<Card animation="disable-all">...</Card>
// App-wide
<HeroUINativeProvider config={{ animation: "disable-all" }}>
<App />
</HeroUINativeProvider>
Reduce Motion is automatic. When a user enables it in system settings, all animations stop. No extra code.
Popover, Select, and Menu switch between popover, bottom-sheet, and dialog with a single prop. Same component, different presentation depending on context:
<Select presentation="popover">...</Select>
<Select presentation="bottom-sheet">...</Select>
<Select presentation="dialog">...</Select>
No other React Native component library does this.
<VideoPlayer src="https://heroui-assets.nyc3.cdn.digitaloceanspaces.com/videos/native-v1-demo/v-1-demo-3.mp4" height={430} muted />
Each native component has its own entry point. Import only what you use:
import { HeroUINativeProvider } from "heroui-native/provider";
import { Button } from "heroui-native/button";
import { Card } from "heroui-native/card";
HeroUI Native ships with its own MCP Server, agent skills, and LLMs.txt. Same tooling structure as the web library:
{
"mcpServers": {
"heroui-native": {
"command": "npx",
"args": ["-y", "@heroui/native-mcp@latest"]
}
}
}
<DocsImage src="https://heroui-assets.nyc3.cdn.digitaloceanspaces.com/docs/[email protected]" darkSrc="https://heroui-assets.nyc3.cdn.digitaloceanspaces.com/docs/[email protected]" alt="HeroUI Pro" href="https://heroui.pro" />
Alongside v3, the pre-sale of HeroUI Pro is live. Premium components, templates, and AI tooling for both React and React Native.
Components beyond the core library: Command palette, Kanban board, Stats dashboard, Filters, Agenda, DataGrid, and more. Accessibility, animations, and platform edge cases are handled. Will be available for both Web and Native.
Full-page, responsive starter templates: Dashboard, Mail, Chat, and Finances. Real layouts with real structure. Start from something that works and customize from there.
Pro licenses include premium MCP servers and agent skills with Pro component docs, usage patterns, and upgrade paths baked in.
Pre-sale pricing is live. v2 Pro customers get an upgrade discount. Use the same email or contact support.
See plans and pricing at heroui.pro
<Tabs items={["npm", "pnpm", "yarn", "bun"]}>
<Tab value="npm">
bash npm i @heroui/styles @heroui/react
</Tab>
<Tab value="pnpm">
bash pnpm add @heroui/styles @heroui/react
</Tab>
<Tab value="yarn">
bash yarn add @heroui/styles @heroui/react
</Tab>
<Tab value="bun">
bash bun add @heroui/styles @heroui/react
</Tab>
</Tabs>
Add two lines to your CSS:
@import "tailwindcss";
@import "@heroui/styles";
<Tabs items={["npm", "pnpm", "yarn", "bun"]}>
<Tab value="npm">
bash npm install heroui-native
</Tab>
<Tab value="pnpm">
bash pnpm add heroui-native
</Tab>
<Tab value="yarn">
bash yarn add heroui-native
</Tab>
<Tab value="bun">
bash bun add heroui-native
</Tab>
</Tabs>
See the React docs and React Native docs for full setup guides (peer dependencies, Uniwind config, and provider setup).
Coming from HeroUI v2? Follow the Migration Guide for step-by-step upgrade instructions.
Every component in HeroUI v3 has a 1:1 match in Figma. Same variants, same naming, same structure. The kit uses auto layout throughout, Figma variables that map directly to code tokens (--accent, --surface, --radius), and Figma's new slots for flexible component composition. Designers rearrange, swap, and customize parts the same way developers do in code.
<DocsImage src="https://heroui-assets.nyc3.cdn.digitaloceanspaces.com/docs/[email protected]" darkSrc="https://heroui-assets.nyc3.cdn.digitaloceanspaces.com/docs/[email protected]" alt="HeroUI Figma Kit v3" href="https://www.figma.com/community/file/1546526812159103429/heroui-figma-kit-v3" />
React Aria gave us the accessibility layer we couldn't build as well on our own. Tailwind CSS v4's native CSS variable approach shaped the entire theming system. The compound component pattern was refined by studying how Radix, Ark UI, and Base UI solved composition.
Thanks to every community member who filed issues, tested betas, and gave feedback throughout the alpha and RC cycle. The library is better because of you.