HeroUI

v3.0.0-rc.1

7 new components (Drawer, ToggleButton, ToggleButtonGroup, Meter, ProgressBar, ProgressCircle, Toolbar), Table & ListBox virtualization, ButtonGroup improvements, and bug fixes.

March 14, 2026

Seven new components: Drawer, ToggleButton, ToggleButtonGroup, Meter, ProgressBar, ProgressCircle, and Toolbar. Table and ListBox gain virtualization, ButtonGroup gets a Separator sub-component + vertical orientation, and React Aria Components is bumped to v1.16.0.

HeroUI v3 RC 1

Installation

Update to the latest version:

npm i @heroui/styles@rc @heroui/react@rc
pnpm add @heroui/styles@rc @heroui/react@rc
yarn add @heroui/styles@rc @heroui/react@rc
bun add @heroui/styles@rc @heroui/react@rc

Using AI assistants? Simply prompt "Hey Cursor, update HeroUI to the latest version" and your AI assistant will automatically compare versions and apply the necessary changes. Learn more about the HeroUI MCP Server.

What's New

New Components

  • Drawer: Slide-out panel with drag-to-dismiss, 4 placements, backdrop variants, scrollable body (Docs)
  • ToggleButton: Selected/unselected toggle with all button variants + icon-only mode (Docs)
  • ToggleButtonGroup: Single or multi-select toggle group, attached/detached layouts, orientation (Docs)
  • Meter: Value within a known range — disk usage, password strength, quotas (Docs)
  • ProgressBar: Linear progress, determinate + indeterminate, colors, custom formatting (Docs)
  • ProgressCircle: Circular SVG progress with customizable track + fill circles (Docs)
  • Toolbar: Groups buttons, toggles, and separators with horizontal or vertical orientation (Docs)

Drawer

Slide-out panel overlay with top/bottom/left/right placement, drag-to-dismiss gestures, and backdrop variants. Compound parts: Trigger, Backdrop, Content, Dialog, Header, Heading, Body, Footer, Handle, CloseTrigger.

import {Button, Drawer} from "@heroui/react";

export function Basic() {
  return (
    <Drawer>

Placements:

import {Button, Drawer} from "@heroui/react";

export function Placements() {
  const placements = ["bottom", "top", "left", "right"] as const;

With Form:

import {Button, Drawer, Input, Label, TextField} from "@heroui/react";

export function WithForm() {
  return (
    <Drawer>

Toggle Button

Stateful toggle between selected and unselected. All button variants and sizes, icon-only mode, controlled or uncontrolled.

import {Heart} from "@gravity-ui/icons";
import {ToggleButton} from "@heroui/react";

export function Basic() {
  return (

Variants:

import {Heart} from "@gravity-ui/icons";
import {ToggleButton} from "@heroui/react";

export function Variants() {
  return (

Toggle Button Group

Single or multi-select toggle group. Attached (connected) and detached layouts, vertical orientation, full-width, and a Separator sub-component.

import {Bold, Italic, Strikethrough, Underline} from "@gravity-ui/icons";
import {ToggleButton, ToggleButtonGroup} from "@heroui/react";

export function Basic() {
  return (

Selection Mode:

Single selection
Multiple selection
import {
  Bold,
  Italic,
  Strikethrough,
  TextAlignCenter,

Attached Mode:

Attached (default)
Detached
import {Bold, Italic, Strikethrough, Underline} from "@gravity-ui/icons";
import {ToggleButton, ToggleButtonGroup} from "@heroui/react";

export function Attached() {
  return (

Meter

Value within a known range — disk usage, password strength, quotas. Compound parts: Root, Output, Track, Fill.

Storage60%
import {Label, Meter} from "@heroui/react";

export function Basic() {
  return (
    <Meter aria-label="Storage" className="w-64" value={60}>

Colors:

Default50%
Accent50%
Success50%
Warning50%
Danger50%
import {Label, Meter} from "@heroui/react";

export function Colors() {
  return (
    <div className="flex w-64 flex-col gap-6">

Progress Bar

Linear progress indicator with determinate + indeterminate states, color variants, sizes, and custom value display. Compound parts: Root, Output, Track, Fill.

Loading60%
import {Label, ProgressBar} from "@heroui/react";

export function Basic() {
  return (
    <ProgressBar aria-label="Loading" className="w-64" value={60}>

Indeterminate:

Loading...
import {Label, ProgressBar} from "@heroui/react";

export function Indeterminate() {
  return (
    <ProgressBar isIndeterminate aria-label="Loading" className="w-64">

Progress Circle

Circular SVG progress with TrackCircle and FillCircle sub-components for direct SVG control. Determinate + indeterminate states.

import {ProgressCircle} from "@heroui/react";

export function Basic() {
  return (
    <ProgressCircle aria-label="Loading" value={60}>

Custom SVG:

import {ProgressCircle} from "@heroui/react";

export function CustomSvg() {
  return (
    <div className="flex items-end gap-6">

Toolbar

Groups buttons, toggle buttons, and separators into an accessible toolbar. Horizontal or vertical orientation, composes with ButtonGroup and ToggleButtonGroup.

import {Bold, Copy, Italic, Scissors, Underline} from "@gravity-ui/icons";
import {
  Button,
  ButtonGroup,
  Separator,

With Button Group:

import {
  ArrowUturnCcwLeft,
  ArrowUturnCwRight,
  Bold,
  Italic,

Component Improvements

ButtonGroup Enhancements

New ButtonGroup.Separator sub-component adds an explicit visual divider between buttons. Works in both horizontal and vertical orientations.

import {
  ChevronDown,
  ChevronLeft,
  ChevronRight,
  CodeFork,

Table & ListBox Virtualization

Table and ListBox now support virtualization via React Aria's Virtualizer for large datasets. Virtualizer, TableLayout, and ListLayout are re-exported from @heroui/react.

Name
Emma Smith
"use client";

import {Table, TableLayout, Virtualizer} from "@heroui/react";

interface User {

ButtonGroup Orientation

ButtonGroup accepts an orientation prop ("horizontal" | "vertical") with correct border-radius handling and separator direction for both axes. The root element was upgraded from <div> to React Aria's Group for proper role="group" semantics.

Horizontal
Vertical
import {TextAlignCenter, TextAlignJustify, TextAlignLeft, TextAlignRight} from "@gravity-ui/icons";
import {Button, ButtonGroup} from "@heroui/react";

export function Orientation() {
  return (

ButtonGroup Focus Ring

Focus rings on grouped buttons now use ring-inset so they stay within button bounds instead of overlapping neighbors.

Granular Component Imports

@heroui/react now supports per-component subpath entrypoints for more explicit imports (#6301):

// Before — root entrypoint
import { Button } from "@heroui/react";

// After — granular subpath import
import { Button } from "@heroui/react/button";

Dependencies

Upgraded react-aria-components from v1.15.1 to v1.16.0 and related packages:

PackageOldNew
react-aria-components1.15.11.16.0
@react-aria/i18n3.12.153.12.16
@react-aria/utils3.33.03.33.1
@react-types/shared3.33.03.33.1
@react-types/color3.1.33.1.4
@internationalized/date3.11.03.12.0
@react-stately/data3.15.13.15.2

Bug Fixes

  • InputGroup: Focus styles now trigger only when the actual input/textarea is focused (:has([data-slot]:focus)) instead of any focusable child via :focus-within (#6274)
  • Avatar: Fallback element inherits border-radius from the parent instead of hardcoding rounded-full, so className overrides apply correctly (#6300)
  • Modal & AlertDialog: Backdrop click events no longer propagate through portals to parent elements (#6297)
  • Table: Fixed header rounding and background color bleeding in Firefox (#6298)

Contributors

Thanks to everyone who contributed to this release!

On this page