# All Components
**Category**: native
**URL**: https://v3.heroui.com/docs/native/components
**Source**: https://raw.githubusercontent.com/heroui-inc/heroui/refs/heads/v3/apps/docs/content/docs/native/components/index.mdx
> Explore the full list of components available in HeroUI Native. More are on the way.
## Buttons
## Collections
## Controls
## Forms
## Navigation
## Overlays
## Feedback
## Layout
## Media
## Data Display
## Utilities
# Introduction
**Category**: native
**URL**: https://v3.heroui.com/docs/native/getting-started
**Source**: https://raw.githubusercontent.com/heroui-inc/heroui/refs/heads/v3/apps/docs/content/docs/native/getting-started/index.mdx
> An open-source UI component library for building beautiful and accessible user interfaces.
HeroUI Native is a component library built on [Tailwind v4](https://tailwindcss.com/blog/tailwindcss-v4) via [Uniwind](https://uniwind.dev/) and modern mobile development technologies. Every component comes with smooth animations, polished details, and built-in accessibility—ready to use, fully customizable.
## Why HeroUI Native?
**Beautiful by default** — Professional look out of the box, no extra styling needed.
**Accessible** — Accessibility is managed following mobile development best practices, with proper focus management, touch accessibility, and screen reader support built into every component.
**Flexible** — Each component is made of customizable parts. Change what you need, leave the rest.
**Developer-friendly** — Fully typed APIs, predictable patterns, and excellent autocompletion.
**Maintained** — We handle updates, bug fixes, and new features. Just update the package.
**Lightweight** — Tree-shaken. Only what you use goes into your app.
**Future-proof** — Compatible with the latest [Expo](https://expo.dev/) and on [Tailwind v4](https://tailwindcss.com/blog/tailwindcss-v4) via [Uniwind](https://uniwind.dev/), designed for AI-assisted development.
## A Living Library, Not Copy-Paste
Copy-paste code works until it breaks. You're left maintaining outdated dependencies that stop evolving.
HeroUI Native is different. It's a living library that grows with you:
* Automatic updates and fixes
* New features without extra work
* Components stay current with React Native, Tailwind, and mobile platforms
* Deep customization, not shallow theme tweaks
* AI-friendly APIs for code generation
HeroUI Native is not a snapshot—it's a garden that keeps growing. 🌱
## HeroUI Ecosystem
* **🌐 HeroUI v3** (web) — React components with Tailwind CSS v4
* **📱 HeroUI Native (mobile)** — Beautiful components for React Native
* **🤖 [HeroUI Chat](https://heroui.chat?ref=heroui-v3)** (text-to-app) — Create apps with natural language
* **🧠 UI for LLMs** — New platform & MCPs coming soon
## FAQ
**Is HeroUI Native free?**
Yes, completely free and open source under the MIT license.
**Is it production-ready?**
Currently in **beta**. We're actively working towards a stable release with community feedback.
**Can I customize the components?**
Yes! Update default styles, animations or compose component parts differently. Every slot is customizable.
**Does it work with TypeScript?**
Fully typed with excellent IDE support and autocompletion.
**What about accessibility?**
Accessibility follows mobile development best practices with proper focus management, touch accessibility, and screen reader support built into every component.
**Is there a Figma file?**
Yes! Access our design system at [HeroUI Figma Kit V3](https://www.figma.com/community/file/1546526812159103429).
## Get Involved
Join the community, share feedback, or contribute:
* [GitHub Discussions](https://github.com/heroui-inc/heroui-native/discussions)
* [Discord](https://discord.gg/9b6yyZKmH4)
* [X/Twitter](https://x.com/hero_ui)
* [Contributing Guidelines](https://github.com/heroui-inc/heroui-native/blob/main/CONTRIBUTING.md)
HeroUI Native is released under the [MIT License](https://github.com/heroui-inc/heroui-native/blob/main/LICENSE).
# Beta 10
**Category**: native
**URL**: https://v3.heroui.com/docs/native/releases/beta-10
**Source**: https://raw.githubusercontent.com/heroui-inc/heroui/refs/heads/v3/apps/docs/content/docs/native/releases/beta-10.mdx
> Bottom Sheet component, PressableFeedback refactor, Animation API State Prop extension, use-theme-color multiple colors selection, and bug fixes.
December 30, 2025
This release introduces the new [Bottom Sheet](/docs/native/components/bottom-sheet) component, refactors [PressableFeedback](/docs/native/components/pressable-feedback) with improved API, extends the Animation API with State Prop support, enhances the `use-theme-color` hook to handle multiple colors selection, and includes various bug fixes and documentation improvements.
## Installation
Update to the latest version:
```bash
npm i heroui-native@beta
```
```bash
pnpm add heroui-native@beta
```
```bash
yarn add heroui-native@beta
```
```bash
bun add heroui-native@beta
```
**Using AI assistants?** Simply prompt "Hey Cursor, update HeroUI Native to the latest version" and your AI assistant will automatically compare versions and apply the necessary changes. Learn more about the [HeroUI Native MCP Server](/docs/native/getting-started/mcp-server).
## What's New
### New Components
#### Bottom Sheet
This release introduces the **Bottom Sheet** component, a versatile overlay component that slides up from the bottom of the screen with animated transitions and swipe-to-dismiss gestures.
**Features:**
* Smooth animated transitions with gesture support
* Multiple snap points for flexible sizing
* Detached mode for custom positioning
* Customizable overlay with blur effects
* Full accessibility support
* Built on [@gorhom/bottom-sheet](https://gorhom.dev/react-native-bottom-sheet)
**Usage:**
```tsx
import { BottomSheet, Button } from 'heroui-native';
TitleDescription
```
For complete documentation and examples, see the [Bottom Sheet component page](/docs/native/components/bottom-sheet).
**Related PR:** [#174](https://github.com/heroui-inc/heroui-native/pull/174)
## Component Improvements
### PressableFeedback Refactor
The [PressableFeedback](/docs/native/components/pressable-feedback) component has been refactored with an improved API and better animation control.
**Improvements:**
* Enhanced animation configuration API
* Better support for custom animation states
* Improved performance and smoother animations
* More flexible feedback positioning options
The component maintains backward compatibility while providing more control over press feedback animations.
**Related PR:** [#182](https://github.com/heroui-inc/heroui-native/pull/182)
## API Enhancements
### Animation API State Prop Extension
The Animation API has been extended with a new `state` prop that allows you to disable animations while customizing properties. This provides more granular control over animation behavior.
**New Capability:**
```tsx
```
The `state` prop can be:
* `'disabled'`: Disable animations while still allowing property customization
* `'disable-all'`: Disable all animations including children
* `boolean`: Simple enable/disable control
This enhancement makes it easier to customize animation properties without enabling animations, useful for fine-tuning component behavior.
**Related PR:** [#176](https://github.com/heroui-inc/heroui-native/pull/176)
### use-theme-color Multiple Colors Selection
The `use-theme-color` hook has been refactored to handle multiple colors selection, making it more flexible and powerful for theme customization.
**Enhancement:**
* Support for selecting multiple colors at once
* Improved color selection logic
* Better performance when working with multiple color values
This improvement makes it easier to work with complex theming scenarios where multiple colors need to be selected and applied together.
**Related PR:** [#170](https://github.com/heroui-inc/heroui-native/pull/170)
## Documentation
### Animated Styles Guide Comments
Added comprehensive comments and documentation to the Animated Styles Guide, making it easier for developers to understand and use animation features effectively.
**Improvements:**
* Enhanced code examples with detailed comments
* Better explanation of animation patterns
* Clearer guidance on when to use different animation approaches
**Related PR:** [#179](https://github.com/heroui-inc/heroui-native/pull/179)
## Bug Fixes
This release includes fixes for the following issues:
* **[Issue #173](https://github.com/heroui-inc/heroui-native/issues/173)**: Fixed issue where `classNames={{container:"bg-x"}}` was not working for styling the backgroundColor of TextField.Input container
* **[Issue #177](https://github.com/heroui-inc/heroui-native/issues/177)**: Fixed button scale animation issue where the scale would sometimes stay at 0.9x and not bounce back after being pressed
* **[Issue #178](https://github.com/heroui-inc/heroui-native/issues/178)**: Fixed bug affecting component functionality
## Updated Documentation
The following documentation pages have been updated to reflect the changes in this release:
* [Animation Guide](/docs/native/getting-started/animation) - Updated with Animation API State Prop documentation
* [Colors Guide](/docs/native/getting-started/colors) - Updated with use-theme-color multiple colors selection information
* [PressableFeedback Component](/docs/native/components/pressable-feedback) - Updated with refactored API documentation
## Links
* [Component Documentation](../components)
* [GitHub Repository](https://github.com/heroui-inc/heroui-native)
## Contributors
Thanks to everyone who contributed to this release!
# Beta 11
**Category**: native
**URL**: https://v3.heroui.com/docs/native/releases/beta-11
**Source**: https://raw.githubusercontent.com/heroui-inc/heroui/refs/heads/v3/apps/docs/content/docs/native/releases/beta-11.mdx
> Enhanced Bottom Sheet close coordination, Dialog swipe-to-dismiss fixes, TextField improvements, and PortalHost export for advanced use cases
January 6, 2026
Beta 11 focuses on improving component reliability and developer experience across several key areas. This release enhances Bottom Sheet close coordination to ensure consistent behavior across all close mechanisms, fixes Dialog swipe-to-dismiss gesture handling issues, resolves TextField styling and functionality problems, and introduces a new PortalHost export for advanced portal mounting scenarios. These improvements make interactions smoother and provide developers with more control over component behavior.
## Installation
Update to the latest version:
```bash
npm i heroui-native@beta
```
```bash
pnpm add heroui-native@beta
```
```bash
yarn add heroui-native@beta
```
```bash
bun add heroui-native@beta
```
**Using AI assistants?** Simply prompt "Hey Cursor, update HeroUI Native to the latest version" and your AI assistant will automatically compare versions and apply the necessary changes. Learn more about the [HeroUI Native MCP Server](/docs/native/getting-started/mcp-server).
## Try It Out
Experience all the Beta 11 improvements in action with our preview app! You can explore the enhanced Bottom Sheet, Dialog, TextField, and PortalHost components directly on your device.
### Prerequisites
Make sure you have the latest version of [Expo Go](https://expo.dev/go) installed on your mobile device.
### How to Access
**Option 1: Scan the QR Code**
Use your device's camera or Expo Go app to scan:
> **Note for Android users:** If scanning the QR code with your device's camera or other scanner apps redirects to a browser and shows a 404 error, open Expo Go first and use its built-in QR scanner instead.
**Option 2: Click the Link**
**[📱 Open Demo App in Expo Go](https://link.heroui.com/native-demo)**
This will automatically open the app in Expo Go if it's installed on your device.
## Component Improvements
### Bottom Sheet Close Coordination Enhancement
The [Bottom Sheet](/docs/native/components/bottom-sheet) component has been enhanced with improved close coordination across all close mechanisms.
**Improvements:**
* Enhanced synchronization between swipe-to-dismiss, overlay press, close button, and programmatic close actions
* Improved state management to prevent race conditions during close operations
* More reliable `onOpenChange` callback firing across all close scenarios
* Better coordination between animation progress and close state transitions
The Bottom Sheet component supports multiple ways to close: swiping down, pressing the overlay, clicking the close button, or programmatically calling close. Previously, these mechanisms could sometimes conflict or produce inconsistent behavior. This update ensures all close mechanisms work harmoniously together, providing a smoother and more predictable user experience.
**Related PR:** [#201](https://github.com/heroui-inc/heroui-native/pull/201)
### Dialog Swipe-to-Dismiss Gesture Handling Fix
The [Dialog](/docs/native/components/dialog) component has been fixed to properly handle swipe-to-dismiss gestures.
**Improvements:**
* Fixed gesture detection and handling for swipe-to-dismiss functionality
* Improved gesture state management during swipe interactions
* Enhanced animation coordination during gesture release
* More reliable dismissal when swiping beyond the threshold
The Dialog component supports swipe-to-dismiss functionality, allowing users to dismiss dialogs by swiping down. This fix resolves issues where gesture handling could become unresponsive or produce unexpected behavior during swipe interactions.
**Related PR:** [#193](https://github.com/heroui-inc/heroui-native/pull/193)
### TextField Styling and Functionality Fixes
The [TextField](/docs/native/components/text-field) component has been fixed to resolve styling and functionality issues.
**Improvements:**
* Fixed input styling inconsistencies
* Resolved animation state management issues
* Improved focus and blur state handling
* Enhanced error state visual feedback
* Fixed placeholder and selection color application
These fixes ensure the TextField component displays correctly across all states (focused, blurred, invalid) and provides consistent visual feedback to users.
**Related PR:** [#202](https://github.com/heroui-inc/heroui-native/pull/202)
## API Enhancements
### PortalHost Export for Advanced Use Cases
The `PortalHost` component is now exported from the main provider module, enabling advanced portal host mounting scenarios.
**New Capability:**
```tsx
import { HeroUINativeProvider, PortalHost } from "@heroui/native";
export function CustomLayout() {
return (
<>
{/* Your app content */}
{/* Manually mount PortalHost in a custom location */}
>
);
}
```
This enhancement allows developers to manually mount portal hosts in custom layouts, which is particularly useful for scenarios where you need portals to render in specific locations (e.g., within BottomSheet, Modal, or other overlay components). By default, `HeroUINativeProvider` includes a `PortalHost` for standard use cases, but now you can create additional hosts with custom names for advanced scenarios.
**Use Cases:**
* Mounting portals within BottomSheet components
* Creating portal hosts in Modal components
* Custom overlay rendering scenarios
* Multi-host portal architectures
**Related PR:** [#185](https://github.com/heroui-inc/heroui-native/pull/185)
## Bug Fixes
This release includes fixes for the following issues:
* **[Issue #187](https://github.com/heroui-inc/heroui-native/issues/187)**: Fixed an issue where multiple presses were required to re-open a bottom sheet or dialog after it was dismissed via swipe gesture. The internal state now properly synchronizes with the close animation, allowing immediate reopening regardless of how the component was closed.
* **[Issue #189](https://github.com/heroui-inc/heroui-native/issues/189)**: Fixed app freezing when swiping to dismiss dialogs containing text inputs.
* **[Issue #196](https://github.com/heroui-inc/heroui-native/issues/196)**: Fixed TextField multiline input behavior to match React Native's TextInput multiline functionality.
* **[Issue #199](https://github.com/heroui-inc/heroui-native/issues/199)**: Fixed placeholder text positioning within TextField Input component.
**Related PRs:**
* [#201](https://github.com/heroui-inc/heroui-native/pull/201)
* [#202](https://github.com/heroui-inc/heroui-native/pull/202)
* [#193](https://github.com/heroui-inc/heroui-native/pull/193)
## Links
* [Component Documentation](../components)
* [GitHub Repository](https://github.com/heroui-inc/heroui-native)
## Contributors
Thanks to everyone who contributed to this release!
# Beta 12
**Category**: native
**URL**: https://v3.heroui.com/docs/native/releases/beta-12
**Source**: https://raw.githubusercontent.com/heroui-inc/heroui/refs/heads/v3/apps/docs/content/docs/native/releases/beta-12.mdx
> InputOTP, Label, and Description components, Popover close fixes, controlled state improvements, border radius fixes, and variant style prop support
January 13, 2026
Beta 12 introduces three essential form components—InputOTP, Label, and Description—that enhance form building capabilities in React Native applications. This release also includes critical fixes for Popover close behavior, popup controlled state management, border radius configuration, and adds variant style prop support across multiple form components. These improvements provide developers with more robust form components and better control over component styling and behavior.
## Installation
Update to the latest version:
```bash
npm i heroui-native@beta
```
```bash
pnpm add heroui-native@beta
```
```bash
yarn add heroui-native@beta
```
```bash
bun add heroui-native@beta
```
**Using AI assistants?** Simply prompt "Hey Cursor, update HeroUI Native to the latest version" and your AI assistant will automatically compare versions and apply the necessary changes. Learn more about the [HeroUI Native MCP Server](/docs/native/getting-started/mcp-server).
## Try It Out
Experience all the Beta 12 improvements in action with our preview app! You can explore the new InputOTP, Label, and Description components, along with the Popover fixes, controlled state improvements, border radius fixes, and variant style prop support directly on your device.
### Prerequisites
Make sure you have the latest version of [Expo Go](https://expo.dev/go) installed on your mobile device.
### How to Access
**Option 1: Scan the QR Code**
Use your device's camera or Expo Go app to scan:
> **Note for Android users:** If scanning the QR code with your device's camera or other scanner apps redirects to a browser and shows a 404 error, open Expo Go first and use its built-in QR scanner instead.
**Option 2: Click the Link**
**[📱 Open Demo App in Expo Go](https://link.heroui.com/native-demo)**
This will automatically open the app in Expo Go if it's installed on your device.
## What's New
### New Components
This release introduces **3 new** essential form components:
* **[InputOTP](/docs/native/components/input-otp)**: Input component for entering one-time passwords (OTP) with individual character slots, animations, and validation support.
* **[Label](/docs/native/components/label)**: Text component for labeling form fields and other UI elements with support for required indicators and validation states.
* **[Description](/docs/native/components/description)**: Text component for providing accessible descriptions and helper text for form fields and other UI elements.
#### InputOTP
The InputOTP component provides a complete solution for one-time password input scenarios, such as two-factor authentication, verification codes, and PIN entry. It features individual character slots with smooth animations, customizable grouping, separators, and comprehensive validation support.
**Features:**
* Individual character slots with smooth animations and caret indicators
* Flexible grouping with separators for visual organization
* Pattern-based input restriction (digits, characters, or custom regex)
* Controlled and uncontrolled value management
* Validation state support with visual feedback
* Customizable placeholder characters per slot position
* Paste support with transformer function
* Complete accessibility support
**Usage:**
```tsx
import { InputOTP, Label, Description } from "heroui-native";
export function Example() {
return (
<>
console.log(code)}>
We've sent a code to your email
>
);
}
```
For complete documentation and examples, see the [InputOTP component page](/docs/native/components/input-otp).
**Related PR:** [#214](https://github.com/heroui-inc/heroui-native/pull/214)
#### Label
The Label component provides accessible labeling for form fields with built-in support for required indicators, validation states, and disabled states. It automatically displays an asterisk for required fields and adapts its styling based on the field's validation state.
**Features:**
* Automatic required field indicator (asterisk)
* Invalid state styling for validation errors
* Disabled state support
* Compound component architecture for custom layouts
* Full accessibility support with nativeID linking
* Customizable styling via className, classNames, and styles props
**Usage:**
```tsx
import { Label, TextField } from "heroui-native";
export function Example() {
return (
);
}
```
For complete documentation and examples, see the [Label component page](/docs/native/components/label).
**Related PR:** [#214](https://github.com/heroui-inc/heroui-native/pull/214)
#### Description
The Description component provides accessible helper text and descriptions for form fields. It features muted styling by default and supports linking to form fields via nativeID for screen reader support.
**Features:**
* Muted text styling optimized for helper text
* Accessibility linking via nativeID and aria-describedby
* Seamless integration with form components
* Customizable styling support
**Usage:**
```tsx
import { Description, TextField } from "heroui-native";
export function Example() {
return (
Email address
We'll never share your email with anyone else.
);
}
```
For complete documentation and examples, see the [Description component page](/docs/native/components/description).
**Related PR:** [#214](https://github.com/heroui-inc/heroui-native/pull/214)
## Component Improvements
### Popover Close via Ref Fix
The [Popover](/docs/native/components/popover) component has been fixed to properly handle programmatic close operations via ref.
**Improvements:**
* Fixed ref-based close method to properly trigger close animations
* Improved state synchronization between ref calls and component state
* Enhanced reliability of programmatic close operations
This fix ensures that when developers call `popoverRef.current?.close()`, the popover closes reliably with proper animation and state management.
**Related PR:** [#207](https://github.com/heroui-inc/heroui-native/pull/207)
### Popup Controlled State Fix
Popup components (including Dialog, Bottom Sheet, and Popover) have been fixed to properly handle controlled state via the `isOpen` prop.
**Improvements:**
* Fixed controlled state synchronization for popup components
* Improved handling of external state changes
* Enhanced reliability when using controlled mode
This fix ensures that popup components correctly respond to external state changes when using controlled mode, providing developers with more predictable behavior when managing popup state externally.
**Related PR:** [#215](https://github.com/heroui-inc/heroui-native/pull/215)
### Button, Chip, and Tabs Border Radius Fix
The [Button](/docs/native/components/button), [Chip](/docs/native/components/chip), and [Tabs](/docs/native/components/tabs) components have been fixed to properly respect global border radius configuration.
**Improvements:**
* Fixed border radius configuration application for Button component
* Fixed border radius configuration application for Chip component
* Fixed border radius configuration application for Tabs component
* Improved consistency across components using global theme configuration
These fixes ensure that global border radius settings defined in the theme configuration are properly applied to Button, Chip, and Tabs components, providing consistent styling across the application.
**Related PR:** [#218](https://github.com/heroui-inc/heroui-native/pull/218)
### TextField.Input Props Cleanup
The [TextField](/docs/native/components/text-field) component's Input subcomponent has been cleaned up by removing the `animation` and `isAnimatedStyleActive` props.
**Changes:**
* Removed `animation` prop from TextField.Input
* Removed `isAnimatedStyleActive` prop from TextField.Input
* Simplified component API for better maintainability
These props were removed to streamline the TextField.Input API and reduce complexity. Animation behavior is now handled internally by the component, providing a more consistent and predictable experience without requiring manual animation configuration.
**Related PR:** [#220](https://github.com/heroui-inc/heroui-native/pull/220)
## API Enhancements
### HeroUINativeProvider devInfo Configuration
The `HeroUINativeProvider` component now supports `devInfo` configuration options for enhanced development experience.
**New Capability:**
```tsx
import { HeroUINativeProvider } from "heroui-native";
export function App() {
return (
{/* Your app content */}
);
}
```
This enhancement provides developers with additional configuration options for development and debugging scenarios, making it easier to troubleshoot and optimize applications during development.
**Related PR:** [#217](https://github.com/heroui-inc/heroui-native/pull/217)
### Variant Style Prop Support
The [Checkbox](/docs/native/components/checkbox), [Radio](/docs/native/components/radio), [TextField](/docs/native/components/text-field), and [InputOTP](/docs/native/components/input-otp) components now support the `variant` style prop for easier variant customization.
**New Capability:**
```tsx
import { Checkbox, Radio, TextField, InputOTP } from "heroui-native";
// Apply variant styles directly via style prop
Option 1
Option 2
```
This enhancement provides developers with more flexibility when customizing component variants, allowing variant changes to be applied via the style prop in addition to the component's variant prop.
**Related PR:** [#220](https://github.com/heroui-inc/heroui-native/pull/220)
## Style Fixes
### Border Radius Configuration
Fixed global border radius configuration not applying correctly to certain components.
**Fixes:**
* Fixed Button component not respecting global border radius configuration
* Fixed Chip component border radius application
* Fixed Tabs component border radius application
### Style Optimizations
* **Border Radius Consistency**: Improved consistency of border radius application across Button, Chip, and Tabs components
* **Theme Configuration**: Enhanced theme configuration propagation to ensure all components respect global settings
## Bug Fixes
This release includes fixes for the following issues:
* **[Issue #93](https://github.com/heroui-inc/heroui-native/issues/93)**: Fixed global border radius configuration not applying to Button component in hero-ui-native using Unwind. The Button component now properly respects border radius settings defined in the global theme configuration, ensuring consistent styling across the application.
* **[Issue #213](https://github.com/heroui-inc/heroui-native/issues/213)**: Fixed Select controlled mode (`isOpen`) not working. The Select component now properly handles controlled state when the `isOpen` prop is provided, allowing developers to manage Select open/close state externally with predictable behavior.
**Related PRs:**
* [#218](https://github.com/heroui-inc/heroui-native/pull/218)
* [#215](https://github.com/heroui-inc/heroui-native/pull/215)
## Links
* [Component Documentation](../components)
* [GitHub Repository](https://github.com/heroui-inc/heroui-native)
## Contributors
Thanks to everyone who contributed to this release!
# Beta 13
**Category**: native
**URL**: https://v3.heroui.com/docs/native/releases/beta-13
**Source**: https://raw.githubusercontent.com/heroui-inc/heroui/refs/heads/v3/apps/docs/content/docs/native/releases/beta-13.mdx
> TextArea component, Button outline variant, Tabs improvements, form component decomposition, popup animation refactor, style class exports, and critical bug fixes
February 3, 2026
Beta 13 introduces the TextArea component for multiline text input, adds Button outline variant, and exports style class names for all components. This release also includes significant improvements to Tabs with better animations and clearer variant naming, decomposes form components into standalone primitives for better flexibility, refactors popup animation system for improved consistency and Android compatibility, and fixes critical issues including Chinese character input handling, theme color calculations, Uniwind Pro compatibility, BottomSheet opening issues, and tree-shaking support. These updates enhance developer experience and component reliability across the library.
## Installation
Update to the latest version:
```bash
npm i heroui-native@beta
```
```bash
pnpm add heroui-native@beta
```
```bash
yarn add heroui-native@beta
```
```bash
bun add heroui-native@beta
```
**Using AI assistants?** Simply prompt "Hey Cursor, update HeroUI Native to the latest version" and your AI assistant will automatically compare versions and apply the necessary changes. Learn more about the [HeroUI Native MCP Server](/docs/native/getting-started/mcp-server).
## Try It Out
Experience all the Beta 13 improvements in action with our preview app! You can explore the new TextArea and CloseButton components, along with Button outline variant, Tabs improvements, granular exports, and all the bug fixes directly on your device.
### Prerequisites
Make sure you have the latest version of [Expo Go](https://expo.dev/go) installed on your mobile device.
### How to Access
**Option 1: Scan the QR Code**
Use your device's camera or Expo Go app to scan:
> **Note for Android users:** If scanning the QR code with your device's camera or other scanner apps redirects to a browser and shows a 404 error, open Expo Go first and use its built-in QR scanner instead.
**Option 2: Click the Link**
**[📱 Open Demo App in Expo Go](https://link.heroui.com/native-demo)**
This will automatically open the app in Expo Go if it's installed on your device.
## What's New
### New Components
This release introduces **3 new** essential components:
* **[TextArea](/docs/native/components/text-area)**: Multiline text input component with styled border and background for collecting longer user input.
* **[Input](/docs/native/components/input)**: Single-line text input component with styled border and background, now available as a standalone component separate from TextField.
* **[CloseButton](/docs/native/components/close-button)**: Reusable button component for closing dialogs, modals, or dismissing content with consistent styling across overlay components.
#### TextArea
The TextArea component provides a complete solution for multiline text input scenarios, such as comments, messages, descriptions, and longer form fields. It features seamless integration with TextField for complete form structure, validation state support, and customizable variants for different visual contexts.
**Features:**
* Multiline text input with customizable rows
* Seamless integration with TextField component
* Validation state support with visual feedback
* Primary and secondary variants for different contexts
* Disabled and read-only states
* Customizable styling via className and styles props
* Complete accessibility support
**Usage:**
```tsx
import { Description, Label, TextArea, TextField } from "heroui-native";
export function Example() {
return (
Please provide as much detail as possible.
);
}
```
For complete documentation and examples, see the [TextArea component page](/docs/native/components/text-area).
**Related PR:** [#254](https://github.com/heroui-inc/heroui-native/pull/254)
#### Input
The Input component is now available as a standalone component, providing single-line text input functionality with styled border and background. Previously available only as `TextField.Input`, Input can now be used independently or integrated with form components like TextField and ControlField.
**Features:**
* Single-line text input with styled border and background
* Standalone usage or integration with form components
* Validation state support with visual feedback
* Primary and secondary variants for different contexts
* Disabled and read-only states
* Customizable styling via className and styles props
* Complete accessibility support
**Usage:**
```tsx
import { Description, Input, Label, TextField } from "heroui-native";
export function Example() {
return (
We'll never share your email.
);
}
```
For complete documentation and examples, see the [Input component page](/docs/native/components/input).
**Related PR:** [#247](https://github.com/heroui-inc/heroui-native/pull/247)
#### CloseButton
The CloseButton component provides a reusable solution for closing dialogs, modals, popovers, and other overlay components. It features consistent styling across all overlay components, customizable icon properties, and seamless integration with Dialog, Popover, Select, and Bottom Sheet components.
**Features:**
* Consistent close button styling across overlay components
* Customizable icon size and color
* Support for custom children to replace default icon
* Disabled state support
* Seamless integration with Dialog, Popover, Select, and Bottom Sheet
* Default styling optimized for overlay contexts
**Usage:**
```tsx
import { CloseButton } from "heroui-native";
// Standalone usage
// As part of Dialog, Popover, Select, Bottom Sheet
```
For complete documentation and examples, see the [CloseButton component page](/docs/native/components/close-button).
**Related PR:** [#237](https://github.com/heroui-inc/heroui-native/pull/237)
### New Subcomponents
#### Tabs.Separator
The Tabs component now includes a new `Separator` subcomponent that provides animated visibility control between tab triggers. This allows developers to create visual separators that automatically show or hide based on the active tab state.
**Features:**
* Animated visibility transitions based on active tab
* Configurable visibility via `betweenValues` prop
* Customizable animation timing and opacity
* Always visible option for static separators
**Usage:**
```tsx
import { Tabs } from "heroui-native";
GeneralNotifications
```
**Related PR:** [#228](https://github.com/heroui-inc/heroui-native/pull/228)
## Component Improvements
### Button Outline Variant
The [Button](/docs/native/components/button) component now includes an `outline` variant that provides a bordered style with transparent background, offering more visual variety for button designs.
**Improvements:**
* New `outline` variant for bordered button style
* Consistent styling with other Button variants
* Proper hover and focus states for outline variant
* Seamless integration with existing Button API
**Usage:**
```tsx
import { Button } from "heroui-native";
```
**Related PR:** [#235](https://github.com/heroui-inc/heroui-native/pull/235)
### Tabs Indicator Animation Refactor
The [Tabs](/docs/native/components/tabs) component's indicator animation has been refactored to use `translateX` transforms instead of width/height animations, resulting in smoother and more performant tab indicator transitions.
**Improvements:**
* Migrated indicator animation to `translateX` transforms
* Improved animation performance and smoothness
* Better visual consistency during tab transitions
* Reduced layout recalculations during animations
**Related PR:** [#227](https://github.com/heroui-inc/heroui-native/pull/227)
### Popover Arrow Sizing and Visual Connection
The [Popover](/docs/native/components/popover) component has been improved with better arrow sizing and visual connection to the popover content, creating a more cohesive visual appearance.
**Improvements:**
* Improved arrow sizing relative to popover content
* Enhanced visual connection between arrow and popover
* Better alignment and spacing
* More polished overall appearance
**Related PR:** [#243](https://github.com/heroui-inc/heroui-native/pull/243)
### Form Components Decomposition
Form components have been decomposed into standalone primitives, providing developers with more flexibility and better control over component composition.
**Improvements:**
* Decomposed form components into standalone primitives
* Improved component reusability and composition
* Better separation of concerns
* Enhanced flexibility for custom form layouts
**Related PR:** [#247](https://github.com/heroui-inc/heroui-native/pull/247)
### Input Android Shadow Fix
The [Input](/docs/native/components/input) component now includes platform-specific shadow styling for Android, ensuring consistent visual appearance across platforms.
**Improvements:**
* Added platform-specific shadow for Android
* Improved visual consistency across iOS and Android
* Better elevation appearance on Android devices
* Enhanced component appearance on Android platform
**Related PR:** [#248](https://github.com/heroui-inc/heroui-native/pull/248)
### Popup Animation System Refactor
The animation system for popup components (Popover, Select, Dialog, BottomSheet) has been refactored to improve entering/exiting animation logic, overlay composition, and content animation handling. This change standardizes animation behavior across all popup components and fixes Android pointer events issues.
**Improvements:**
* Standardized entering/exiting animations using FadeInDown/FadeOutDown for dialog presentations
* Refactored overlay animation hooks to support both progress-based and entering/exiting animations
* Improved overlay composition using Dialog.Overlay and Popover.Overlay components instead of Pressable wrappers
* Fixed Android pointer events issue affecting popup interactions
* Made presentation prop explicit in examples (popover, dialog, bottom-sheet)
* Simplified animation API for better maintainability and consistency
**Related PR:** [#263](https://github.com/heroui-inc/heroui-native/pull/263)
## API Enhancements
### Granular Exports for Bundle Optimization
The library now provides granular exports for each component, allowing developers to reduce bundle size by importing only the components they need.
**New Capability:**
```tsx
// Granular imports - use when you need only a few components
import { HeroUINativeProvider } from "heroui-native/provider";
import { Button } from "heroui-native/button";
import { Card } from "heroui-native/card";
// General import - imports the whole library, use when you're using many components
import { Button, Card } from "heroui-native";
```
Granular imports are ideal when you only need a few components, as they help keep your bundle size smaller. General imports from `heroui-native` will include the entire library, which is convenient when you're using many components throughout your app.
**Available granular exports:**
* `heroui-native/provider` - Provider component
* `heroui-native/[component-name]` - Individual components
* `heroui-native/portal` - Portal utilities
* `heroui-native/utils` - Utility functions
* `heroui-native/hooks` - Custom hooks
**Important**: To keep the bundle size under control, you must follow the pattern with granular imports consistently. Even one general import from `heroui-native` will break this optimization strategy.
**Related PR:** [#233](https://github.com/heroui-inc/heroui-native/pull/233)
### Style Class Names Export
All components now export their style class names, enabling developers to reference component styles programmatically and create custom styling solutions.
**New Capability:**
```tsx
import { buttonClassNames } from "heroui-native";
// Access component class names programmatically
const customStyles = {
base: buttonClassNames.base,
variant: buttonClassNames.variant,
};
```
This enhancement provides developers with programmatic access to component class names, enabling advanced styling scenarios and custom theme implementations.
**Related PR:** [#252](https://github.com/heroui-inc/heroui-native/pull/252)
## Style Fixes
### Style Optimizations
* **Quaternary Variant Removal**: Removed quaternary variant and polished component styles for better consistency
* **Component Style Polish**: Enhanced styling across multiple components for improved visual consistency
* **Shadow and Border Radius Updates**: Improved shadow and border radius consistency across components
* **Theme Variable Cleanup**: Simplified theme variables and removed redundant color-mix calculations
**Related PR:** [#246](https://github.com/heroui-inc/heroui-native/pull/246)
## ⚠️ Breaking Changes
### Tabs Variant Prop Rename
The Tabs component's `variant` prop has been renamed from `pill`/`line` to `primary`/`secondary` for better clarity and consistency with other components.
**Migration:**
Update all instances of Tabs variant prop:
```tsx
// Before
{/* content */}
{/* content */}
// After
{/* content */}
{/* content */}
```
**Available options:**
* `"primary"` - Primary variant (previously `"pill"`)
* `"secondary"` - Secondary variant (previously `"line"`)
**Related PR:** [#236](https://github.com/heroui-inc/heroui-native/pull/236)
### Tabs Indicator Animation Refactor
The [Tabs](/docs/native/components/tabs) component's indicator animation has been refactored to use `translateX` transforms instead of `left` positioning for GPU-accelerated performance. This change improves animation performance but requires updates to custom animation configurations.
**Migration:**
If you have customized the Tabs indicator animation, update your animation configuration:
```tsx
// Before
{/* content */}
// After
{/* content */}
```
**What Changed:**
* Animation API changed from `left` to `translateX` in `TabsIndicatorAnimation` configuration
* Indicator positioning now uses `translateX` transform for GPU-accelerated animations
* Added `left-0` base class to indicator styles to maintain initial positioning
* Visual behavior remains identical, only the underlying implementation has changed
**Related PR:** [#227](https://github.com/heroui-inc/heroui-native/pull/227)
### Divider Component Rename
The `Divider` component has been renamed to `Separator` for better consistency with naming conventions and to avoid confusion with other divider implementations.
**Migration:**
Update all imports and usages:
```tsx
// Before
import { Divider } from "heroui-native";
// After
import { Separator } from "heroui-native";
```
**Related PR:** [#238](https://github.com/heroui-inc/heroui-native/pull/238)
### Quaternary Variant Removal
The `quaternary` variant has been removed from [Surface](/docs/native/components/surface) and [Card](/docs/native/components/card) components to simplify the design system and improve consistency.
**Migration:**
Update any components using the `quaternary` variant:
```tsx
// Before
{/* content */}
{/* content */}
// After
// Use default, secondary, or tertiary variants, or apply custom styling
{/* content */}
{/* content */}
// Or use custom styling for specific needs
{/* content */}
```
**Available variants:**
* `"default"` - Default surface styling
* `"secondary"` - Secondary surface styling
* `"tertiary"` - Tertiary surface styling
**Related PR:** [#246](https://github.com/heroui-inc/heroui-native/pull/246)
### Form Component Decomposition
As part of the form component decomposition, several components have been renamed and restructured to provide better flexibility and composition patterns.
**Component Renames:**
* `FormField` has been renamed to `ControlField`
* `ErrorView` has been renamed to `FieldError`
**Migration:**
Update all imports and usages:
```tsx
// Before
import { FormField, ErrorView, TextField } from "heroui-native";
Error message
// After
import { ControlField, FieldError, Input, TextField } from "heroui-native";
Error message
```
**TextField.Input Removal:**
The `TextField.Input` subcomponent has been removed. Use the standalone `Input` component instead:
```tsx
// Before
import { TextField } from "heroui-native";
// After
import { Input, TextField } from "heroui-native";
```
**Component Composition Changes:**
`RadioGroup`, `TextField`, and `ControlField` now use `Label`, `Description`, and `FieldError` components directly, providing more flexible composition:
```tsx
import { ControlField, Description, FieldError, Input, Label, RadioGroup, TextField } from "heroui-native";
// TextField with Label, Description, and FieldError
We'll never share your email.Invalid email address
// RadioGroup with Label, Description, and FieldError
Option 1Choose one optionPlease select an option
// ControlField with Label, Description, and FieldError
Additional informationValidation error
```
**Related PR:** [#247](https://github.com/heroui-inc/heroui-native/pull/247)
### CloseButton Component and asChild Removal
A new reusable `CloseButton` component has been introduced, and all close button implementations across Dialog, Popover, Select, and BottomSheet components have been refactored to use this shared component. The `asChild` prop has been removed from all Close components.
**Migration:**
Update any usage of `asChild` prop on Close components:
```tsx
// Before
import { Button, Dialog } from "heroui-native";
// After
import { Button, Dialog } from "heroui-native";
const [isOpen, setIsOpen] = useState(false);
```
**What Changed:**
* New `CloseButton` component added with default `variant="tertiary"`, `size="sm"`, and `isIconOnly={true}`
* `Dialog.Close`, `Popover.Close`, `Select.Close`, and `BottomSheet.Close` now extend `CloseButton` internally
* The `asChild` prop has been removed from all Close components
* Close components still support all Button props including `variant`, `size`, `iconProps`, and custom `children`
* You must now handle close logic manually when using custom buttons instead of Close components
**Related PR:** [#237](https://github.com/heroui-inc/heroui-native/pull/237)
### Popup Animation System Refactor
The animation system for popup components has been refactored, resulting in several API changes that require code updates.
**Migration:**
* Remove `closeDelay` and `isDismissKeyboardOnClose` props from `Dialog.Root`
* Remove custom `entering`/`exiting` animation configs from `Dialog.Root` animation prop (now only supports disable flags). Custom animations should be configured using Keyframe animations directly on `Dialog.Content` component
* Remove `isAnimatedStyleActive` and `onLayout` props from `Dialog.Content`
* Remove `isDismissKeyboardOnClose` prop from `BottomSheet.Root`
* Update `BottomSheet.Overlay` animation prop to remove `entering`/`exiting` properties (no longer supported)
* Make `presentation` prop explicit on all `Popover.Content` and `Select.Content` components (changed from optional to required)
* Update animation hooks usage: `useBottomSheetAnimation()` no longer returns `bottomSheetState`, `useDialogAnimation()` no longer returns `dialogState`
**What Changed:**
* `Dialog.Root`: Removed `closeDelay` and `isDismissKeyboardOnClose` props
* `Dialog.Root`: Animation prop type changed from `DialogRootAnimation` (supported custom entering/exiting) to `AnimationRootDisableAll` (disable flags only)
* `Dialog.Content`: Removed `isAnimatedStyleActive` and `onLayout` props
* `BottomSheet.Root`: Removed `isDismissKeyboardOnClose` prop
* `BottomSheet.Overlay`: Animation prop no longer supports `entering`/`exiting` properties
* `Popover.Content`: `presentation` prop is now required (was optional, defaulted to `"popover"`)
* `Select.Content`: `presentation` prop is now required (was optional, defaulted to `"popover"`)
* Animation hooks: `useBottomSheetAnimation()` no longer returns `bottomSheetState`, `useDialogAnimation()` no longer returns `dialogState`
**Related PR:** [#263](https://github.com/heroui-inc/heroui-native/pull/263)
## Bug Fixes
This release includes fixes for the following issues:
* **[Issue #181](https://github.com/heroui-inc/heroui-native/issues/181)**: Fixed TextField error when inputting Chinese characters. The TextField component now properly handles multibyte characters and international input, ensuring smooth text entry for all languages including Chinese, Japanese, and Korean.
* **[Issue #219](https://github.com/heroui-inc/heroui-native/issues/219)**: Fixed Button `childrenToString()` returning `"[object Object]"` for multiple children. The function now properly handles React elements and complex children structures, preventing stringification issues when rendering button content.
* **[Issue #232](https://github.com/heroui-inc/heroui-native/issues/232)**: Fixed HeroUINativeProvider breaking with the recently released Uniwind Pro. The provider now properly handles Uniwind Pro compatibility, ensuring smooth integration with the latest Uniwind version.
* **[Issue #259](https://github.com/heroui-inc/heroui-native/issues/259)**: Fixed BottomSheet issue where opening quickly and starting a meeting would prevent it from opening again. The refactored animation system resolves this issue by improving the entering/exiting animation logic.
* **[Issue #261](https://github.com/heroui-inc/heroui-native/issues/261)**: Fixed `@gorhom/bottom-sheet` not being tree-shaken. The library now properly supports tree-shaking for unused dependencies.
**Additional Fixes:**
* Fixed theme calculated colors issue that was causing incorrect color values in certain scenarios
* Fixed `childrenToString` function to prevent React elements from being stringified incorrectly
**Related PRs:**
* [#226](https://github.com/heroui-inc/heroui-native/pull/226)
* [#239](https://github.com/heroui-inc/heroui-native/pull/239)
## Links
* [Component Documentation](../components)
* [GitHub Repository](https://github.com/heroui-inc/heroui-native)
## Contributors
Thanks to everyone who contributed to this release!
# All Releases
**Category**: native
**URL**: https://v3.heroui.com/docs/native/releases
**Source**: https://raw.githubusercontent.com/heroui-inc/heroui/refs/heads/v3/apps/docs/content/docs/native/releases/index.mdx
> All updates and changes to HeroUI Native, including new features, fixes, and breaking changes.
**Using AI assistants?** Simply prompt "Hey Cursor, update HeroUI Native to the latest version" and your AI assistant will automatically compare versions and apply the necessary changes. Learn more about the [HeroUI Native MCP Server](/docs/native/getting-started/mcp-server).
## Latest Release
### RC 4
**March 2026**
This release introduces the SubMenu compound component for nested expandable menus with animated expand/collapse, refactors Slider Output composition with slot-based styling and `textProps` forwarding, and fixes PressableFeedback ripple animation blink on rapid presses.
[Read full release notes →](/docs/native/releases/rc-4)
### RC 3
**February 2026**
This release introduces three new components—TagGroup, Menu, and InputGroup—adds Android hardware back button support for all bottom-sheet-based overlays, and achieves Expo 55 compatibility with a critical `combineStyles` fix that preserves Reanimated animated style bindings.
[Read full release notes →](/docs/native/releases/rc-3)
### RC 2
**February 2026**
This release introduces three new components—SearchField, ListGroup, and Slider—adds multi-selection mode to Select with type-safe generics, and refactors the Button feedback API into a unified `feedbackVariant` + `animation` prop pattern. Peer dependency constraints are relaxed for broader Expo SDK 55 compatibility, and several Select and Avatar bugs are fixed.
[Read full release notes →](/docs/native/releases/rc-2)
### RC 1
**February 2026**
This release introduces the Alert compound component with five status variants and accessibility primitives, extracts Radio into a standalone component with dual-mode operation, and adds the animated Select.TriggerIndicator subcomponent. It also delivers HeroUINativeProviderRaw for bundle optimization, a `disableFullWindowOverlay` prop for iOS debugging, unified `styles` prop support across six components, and theme surface variable refactoring with explicit per-theme definitions.
[Read full release notes →](/docs/native/releases/rc-1)
### Beta 13
**February 2026**
This release introduces the TextArea component for multiline text input, adds Button outline variant, exports style class names for all components, and includes a reusable CloseButton component. The release also refactors Tabs with improved animations and variant naming, decomposes form components into standalone primitives, and adds granular exports for bundle optimization. Critical bug fixes for theme colors and component stringification are also included.
[Read full release notes →](/docs/native/releases/beta-13)
### Beta 12
**January 2026**
This release introduces three essential form components—InputOTP, Label, and Description—that enhance form building capabilities in React Native applications. The release also includes critical fixes for Popover close behavior, popup controlled state management, border radius configuration, and adds variant style prop support across multiple form components.
[Read full release notes →](/docs/native/releases/beta-12)
### Beta 11
**January 2026**
This release enhances component reliability and developer experience with improved close coordination for Bottom Sheet, fixes for Dialog swipe-to-dismiss gestures, TextField styling improvements, and a new PortalHost export for advanced portal mounting scenarios. These updates ensure smoother interactions and provide more flexibility for custom layouts.
[Read full release notes →](/docs/native/releases/beta-11)
### Beta 10
**December 2025**
This release introduces the new [Bottom Sheet](/docs/native/components/bottom-sheet) component, refactors [PressableFeedback](/docs/native/components/pressable-feedback) with improved API, extends the Animation API with State Prop support, enhances the `use-theme-color` hook to handle multiple colors selection, and includes various bug fixes and documentation improvements.
[Read full release notes →](/docs/native/releases/beta-10)
## Release Schedule
HeroUI Native follows a regular release cycle:
* **Release candidates**: Final stabilization before stable release - In progress
* **Stable releases**: Quarterly major versions (Q1 2026 target)
## Contributing
Found an issue or want to contribute? Check out our [GitHub repository](https://github.com/heroui-inc/heroui-native).
# RC 1
**Category**: native
**URL**: https://v3.heroui.com/docs/native/releases/rc-1
**Source**: https://raw.githubusercontent.com/heroui-inc/heroui/refs/heads/v3/apps/docs/content/docs/native/releases/rc-1.mdx
> Alert component, standalone Radio component, Select TriggerIndicator, HeroUINativeProviderRaw, disableFullWindowOverlay prop, styles prop expansion, theme surface refactor
February 12, 2026
RC 1 marks the first Release Candidate for HeroUI Native, signaling that the library is approaching production readiness. This release introduces the Alert compound component with accessibility-first design and status variants, extracts Radio into a standalone component with dual-mode operation, and adds the animated Select.TriggerIndicator subcomponent. It also delivers a lightweight HeroUINativeProviderRaw for bundle optimization, a new `disableFullWindowOverlay` prop for iOS debugging, unified `styles` prop support across six components, and a theme refactor that replaces calculated surface colors with explicit theme-defined variables. Several critical bug fixes—including InputOTP in BottomSheet, toast text clipping, and element inspector compatibility—round out the release.
## Installation
Update to the latest version:
```bash
npm i heroui-native
```
```bash
pnpm add heroui-native
```
```bash
yarn add heroui-native
```
```bash
bun add heroui-native
```
**Using AI assistants?** Simply prompt "Hey Cursor, update HeroUI Native to the latest version" and your AI assistant will automatically compare versions and apply the necessary changes. Learn more about the [HeroUI Native MCP Server](/docs/native/getting-started/mcp-server).
## Try It Out
Experience all the RC 1 improvements in action with our preview app! You can explore the new Alert and Radio components, Select TriggerIndicator and all the bug fixes directly on your device.
### Prerequisites
Make sure you have the latest version of [Expo Go](https://expo.dev/go) installed on your mobile device.
### How to Access
**Option 1: Scan the QR Code**
Use your device's camera or Expo Go app to scan:
> **Note for Android users:** If scanning the QR code with your device's camera or other scanner apps redirects to a browser and shows a 404 error, open Expo Go first and use its built-in QR scanner instead.
**Option 2: Click the Link**
**[📱 Open Demo App in Expo Go](https://link.heroui.com/native-demo)**
This will automatically open the app in Expo Go if it's installed on your device.
## What's New
### New Components
This release introduces **1 new** component:
* **[Alert](/docs/native/components/alert)**: Accessible alert component with five status variants and compound sub-components for flexible content composition.
#### Alert
The Alert component provides accessible alert messaging with built-in support for five status variants: default, accent, success, warning, and danger. It follows the compound component pattern with `Alert.Indicator`, `Alert.Content`, `Alert.Title`, and `Alert.Description` sub-components, giving developers full control over layout and customization. The primitive layer provides `role="alert"`, `aria-labelledby`, and `aria-describedby` accessibility associations automatically.
**Features:**
* Five status variants: default, accent, success, warning, and danger
* Default SVG status icons with theme-aware colors via `useStatusColor` hook
* Compound component architecture with Indicator, Content, Title, and Description sub-components
* Custom indicator support (e.g., replace default icon with a Spinner)
* Accessibility primitives with `role="alert"`, `aria-labelledby`, and `aria-describedby`
* `asChild` slot support on all sub-components
* Ref forwarding and `className` prop support on all parts
**Usage:**
```tsx
import { Alert } from "heroui-native";
export function Example() {
return (
Payment successful
Your payment has been processed successfully.
);
}
```
For complete documentation and examples, see the [Alert component page](/docs/native/components/alert).
**Related PR:** [#284](https://github.com/heroui-inc/heroui-native/pull/284)
### New Subcomponents
#### Select.TriggerIndicator
The [Select](/docs/native/components/select) component now includes a `TriggerIndicator` subcomponent that displays an animated chevron icon to visually indicate the open/close state. The indicator rotates smoothly when the select opens or closes, using React Native Reanimated spring physics.
**Features:**
* Animated chevron icon that rotates on open/close transitions
* Customizable animation configuration via `animation` prop with rotation values and spring config
* Icon customization through `iconProps` (size, color)
* Support for custom children to replace the default chevron
* Automatic state synchronization with Select open/close state
**Usage:**
```tsx
import { Select } from "heroui-native";
```
**Related PR:** [#274](https://github.com/heroui-inc/heroui-native/pull/274)
## Component Improvements
### Toast Styling and Stacking Refactor
The [Toast](/docs/native/components/toast) component styling has been refactored to replace the border-based padding approach with proper padding and vertical placeholder views, improving content visibility when toasts stack.
**Improvements:**
* Replaced `border-[16px]` padding workaround with proper `p-4` padding
* Added `useVerticalPlaceholderStyles` hook for placeholder view styling
* Added absolute positioned placeholder Views at top and bottom to prevent content visibility when toasts stack
* Updated shadow system to use `shadow-overlay` token
* Standardized overlay shadow values across all themes (alpha, mint, sky) with lighter opacity
This refactor ensures content remains properly hidden when toasts of different heights stack together, while providing a more maintainable and predictable styling approach.
**Related PR:** [#229](https://github.com/heroui-inc/heroui-native/pull/229)
### Dialog Overlay Animation Fix
The [Dialog](/docs/native/components/dialog) component's popup animation timing has been fixed when closing via gesture. The progress value is now properly sequenced with delays to ensure the closing animation completes before resetting.
**Improvements:**
* Progress value now transitions to 2 after a 300ms delay when closing via gesture
* Progress resets to 0 after 350ms to ensure animation completion
* Removed immediate `progress.set(2)` call when `isOpen` becomes false
* Smooth closing animations now play correctly when dismissing popups via swipe gestures
**Related PR:** [#277](https://github.com/heroui-inc/heroui-native/pull/277)
### Theme Surface Variables Refactor
The theme system has been refactored to replace calculated surface colors with explicit theme-defined variables, providing more control and consistency across themes.
**Improvements:**
* `surface-secondary` and `surface-tertiary` (with foregrounds) are now defined explicitly in each theme (alpha, lavender, mint, sky, variables.css)
* Base theme uses `var(--surface-secondary)` and `var(--surface-tertiary)` instead of `color-mix` calculations
* Removed `on-surface`, `on-surface-secondary`, and `on-surface-tertiary` palettes from theme.css
* Updated theming documentation with the new variable structure and examples
This change gives theme authors direct control over surface color values rather than relying on `color-mix` calculations, resulting in more predictable and consistent surface styling across all themes.
**Related PR:** [#281](https://github.com/heroui-inc/heroui-native/pull/281)
## API Enhancements
### Unified `styles` Prop for Multiple Components
Six components now support the unified `styles` prop for slot-based styling, providing a consistent pattern for applying styles to component internals.
**Supported components:**
* **Accordion**: `container` and `separator` slots
* **AvatarFallback**: `container` and `text` slots
* **FieldError**: `container` and `text` slots
* **Label**: `text` and `asterisk` slots (also fixed `style` prop handling)
* **PressableFeedback Ripple**: `container` and `ripple` slots (replaces `containerStyle` and `rippleStyle`)
* **SelectContentDialog**: `wrapper` and `content` slots
**New Capability:**
```tsx
import { Accordion, Label } from "heroui-native";
// Apply styles to specific slots
{/* Accordion items */}
```
All changes maintain backward compatibility with existing `style` props and properly merge styles when both are provided.
**Related PR:** [#271](https://github.com/heroui-inc/heroui-native/pull/271)
### `disableFullWindowOverlay` Prop
Portal-based components now support a `disableFullWindowOverlay` prop that enables React Native element inspector support on iOS during development.
**Supported components:**
* `BottomSheet.Portal`
* `Dialog.Portal`
* `Popover.Portal`
* `Select.Portal`
* `ToastProvider`
**New Capability:**
```tsx
import { Dialog } from "heroui-native";
// Enable element inspector support on iOS
```
On iOS, `FullWindowOverlay` uses a separate native window that blocks the React Native element inspector. Setting `disableFullWindowOverlay` to `true` renders content in the main window instead, enabling the inspector during development. The tradeoff is that overlays will no longer appear above native modals or the keyboard. This prop has no effect on Android.
For Toast, the prop is passed via `config.toast` when using `HeroUINativeProvider`.
**Related PR:** [#283](https://github.com/heroui-inc/heroui-native/pull/283)
### HeroUINativeProviderRaw
A new lightweight provider variant, `HeroUINativeProviderRaw`, excludes `ToastProvider` and `PortalHost` to give consumers full control over which dependencies are bundled.
**New Capability:**
```tsx
import { HeroUINativeProviderRaw } from "heroui-native/provider-raw";
// Lightweight provider without Toast and Portal dependencies
export function App() {
return (
{/* Your app content */}
);
}
```
This makes `react-native-screens`, `@gorhom/bottom-sheet`, and `react-native-svg` fully optional dependencies. The raw provider includes only `SafeAreaListener`, `GlobalAnimationSettingsProvider`, and `TextComponentProvider`. Consumers who need toast or portal features can compose them manually.
**Related PR:** [#285](https://github.com/heroui-inc/heroui-native/pull/285)
### Select.Trigger `variant` Prop
The `Select.Trigger` component now supports a `variant` prop with `"default"` and `"unstyled"` options, enabling better composition with custom trigger components like Button.
**New Capability:**
```tsx
import { Button, Select } from "heroui-native";
// Default variant (pre-styled trigger)
// Unstyled variant for custom compositions
```
**Related PR:** [#274](https://github.com/heroui-inc/heroui-native/pull/274)
### ControlField Radio Variant
The [ControlField](/docs/native/components/control-field) component now supports a `"radio"` variant in `ControlField.Indicator`, rendering a standalone Radio component alongside the existing `"switch"` and `"checkbox"` variants.
**New Capability:**
```tsx
import { ControlField } from "heroui-native";
Radio option
```
**Related PR:** [#286](https://github.com/heroui-inc/heroui-native/pull/286)
## ⚠️ Breaking Changes
### PressableFeedback Ripple: Unified `styles` Prop
The PressableFeedback Ripple component's individual style props (`containerStyle` and `rippleStyle`) have been replaced with a unified `styles` prop.
**Migration:**
Update all instances of individual style props to the unified `styles` prop:
```tsx
// Before
// After
```
**Related PR:** [#271](https://github.com/heroui-inc/heroui-native/pull/271)
### Select.Trigger Default Styles
`Select.Trigger` now defaults to `variant="default"`, which applies default container styles (`flex-row items-center justify-between h-12 px-4 rounded-2xl bg-surface shadow-surface`). Users with custom styled triggers need to add `variant="unstyled"` to prevent default styles from being applied.
**Migration:**
```tsx
// Before (custom styled trigger)
{/* content */}
// After (add variant="unstyled" to preserve custom styling)
{/* content */}
```
**Related PR:** [#274](https://github.com/heroui-inc/heroui-native/pull/274)
### Surface Theme Variables Restructured
The `on-surface`, `on-surface-secondary`, and `on-surface-tertiary` CSS variables and their hover/focus variants have been removed from the base theme. Surface secondary and tertiary colors are now defined explicitly in each theme file.
**Migration:**
If you reference `on-surface`, `on-surface-secondary`, or `on-surface-tertiary` variables in custom styles, replace them with the appropriate surface foreground variables defined in your theme.
```css
/* Before */
color: var(--on-surface);
color: var(--on-surface-secondary);
/* After */
color: var(--surface-foreground);
color: var(--surface-secondary-foreground);
```
**Related PR:** [#281](https://github.com/heroui-inc/heroui-native/pull/281)
### RadioGroup Indicator Removed
`RadioGroup.Indicator` and `RadioGroup.IndicatorThumb` have been removed in favor of the new standalone `Radio` component. The related types `RadioGroupIndicatorProps`, `RadioGroupIndicatorThumbProps`, and `RadioGroupIndicatorThumbAnimation` are also removed from exports.
**Migration:**
Replace all `RadioGroup.Indicator` and `RadioGroup.IndicatorThumb` usages with the `Radio` component:
```tsx
// Before
import { RadioGroup } from "heroui-native";
Option 1
// After
import { Radio, RadioGroup } from "heroui-native";
Option 1
```
**Related PR:** [#286](https://github.com/heroui-inc/heroui-native/pull/286)
## Bug Fixes
This release includes fixes for the following issues:
* **[Issue #229](https://github.com/heroui-inc/heroui-native/issues/229)**: Fixed InputOTP not working inside BottomSheet. The InputOTP component now functions correctly when rendered within a BottomSheet overlay, resolving input focus and interaction issues that previously prevented OTP entry in bottom sheet contexts.
* **[Issue #265](https://github.com/heroui-inc/heroui-native/issues/265)**: Fixed the first letter of Toast description text being clipped. The toast styling refactor replaces the border-based padding approach with proper padding and placeholder views, ensuring all text content is fully visible regardless of toast stacking configuration.
* **[Issue #272](https://github.com/heroui-inc/heroui-native/issues/272)**: Fixed FullWindowOverlay blocking the React Native element inspector on iOS. The new `disableFullWindowOverlay` prop on portal components allows developers to render overlay content in the main window during development, restoring element inspector functionality.
**Related PRs:**
* [#229](https://github.com/heroui-inc/heroui-native/pull/229)
* [#283](https://github.com/heroui-inc/heroui-native/pull/283)
## Updated Documentation
The following documentation pages have been updated to reflect the changes in this release:
* [Alert](/docs/native/components/alert) - New component documentation with usage examples and API reference
* [Radio](/docs/native/components/radio) - New standalone Radio component documentation
* [Radio Group](/docs/native/components/radio-group) - Updated to reflect RadioGroup.Indicator removal and Radio integration
* [Control Field](/docs/native/components/control-field) - Updated with new radio variant documentation
* [Select](/docs/native/components/select) - TriggerIndicator subcomponent and Trigger variant documentation
* [Toast](/docs/native/components/toast) - Updated styling approach documentation
* [Bottom Sheet](/docs/native/components/bottom-sheet) - Added disableFullWindowOverlay documentation
* [Dialog](/docs/native/components/dialog) - Added disableFullWindowOverlay documentation
* [Popover](/docs/native/components/popover) - Added disableFullWindowOverlay documentation
* [Provider](/docs/native/getting-started/provider) - HeroUINativeProviderRaw documentation and provider hierarchy
* [Theming](/docs/native/getting-started/theming) - Updated surface variable structure and examples
* [Accordion](/docs/native/components/accordion) - Added styles prop documentation
* [Avatar](/docs/native/components/avatar) - Added styles prop documentation
* [Label](/docs/native/components/label) - Added styles prop documentation
* [Field Error](/docs/native/components/field-error) - Added styles prop documentation
## Links
* [Component Documentation](../components)
* [GitHub Repository](https://github.com/heroui-inc/heroui-native)
## Contributors
Thanks to everyone who contributed to this release!
# RC 2
**Category**: native
**URL**: https://v3.heroui.com/docs/native/releases/rc-2
**Source**: https://raw.githubusercontent.com/heroui-inc/heroui/refs/heads/v3/apps/docs/content/docs/native/releases/rc-2.mdx
> SearchField, ListGroup, and Slider components, Select multi-selection mode, Button feedback API refactor, peer dependency relaxation
February 20, 2026
RC 2 continues the march toward production readiness with three new components—SearchField, ListGroup, and Slider—and a powerful multi-selection mode for Select backed by type-safe generics. The Button feedback API has been refactored into a cleaner unified `feedbackVariant` + `animation` prop pattern, and peer dependency constraints are relaxed for broader compatibility with Expo SDK 55. Several Select and Avatar bug fixes round out the release.
## Installation
Update to the latest version:
```bash
npm i heroui-native
```
```bash
pnpm add heroui-native
```
```bash
yarn add heroui-native
```
```bash
bun add heroui-native
```
**Using AI assistants?** Simply prompt "Hey Cursor, update HeroUI Native to the latest version" and your AI assistant will automatically compare versions and apply the necessary changes. Learn more about the [HeroUI Native MCP Server](/docs/native/getting-started/mcp-server).
## Try It Out
Experience all the RC 2 improvements in action with our preview app! You can explore the new SearchField, ListGroup, and Slider components, Select multi-selection mode, the updated Button feedback API, and all the bug fixes directly on your device.
### Prerequisites
Make sure you have the latest version of [Expo Go](https://expo.dev/go) installed on your mobile device.
### How to Access
**Option 1: Scan the QR Code**
Use your device's camera or Expo Go app to scan:
> **Note for Android users:** If scanning the QR code with your device's camera or other scanner apps redirects to a browser and shows a 404 error, open Expo Go first and use its built-in QR scanner instead.
**Option 2: Click the Link**
**[📱 Open Demo App in Expo Go](https://link.heroui.com/native-demo)**
This will automatically open the app in Expo Go if it's installed on your device.
## What's New
### New Components
This release introduces **3 new** components:
* **[Slider](/docs/native/components/slider)**: Slider component with single-value and range modes, horizontal/vertical orientation, custom number formatting, and spring-animated thumb feedback.
* **[ListGroup](/docs/native/components/list-group)**: Surface-based grouped list component with pressable items, prefix/suffix slots, and default chevron navigation indicator.
* **[SearchField](/docs/native/components/search-field)**: Compound component for filtering and querying content with built-in search icon, clearable input, and auto-hide clear button.
#### Slider
The Slider component supports single-value and range (multi-thumb) modes, horizontal and vertical orientation, custom number formatting via `Intl.NumberFormat`, and spring-animated thumb feedback. The primitive layer handles all gesture and value logic independently, making it reusable for alternative styled implementations.
**Features:**
* Compound sub-components: `Slider.Output`, `Slider.Track`, `Slider.Fill`, `Slider.Thumb`
* Range slider: pass an array as `defaultValue`/`value` and use a render-function on `Slider.Track` to render multiple thumbs
* Vertical orientation via `orientation="vertical"`
* Custom formatting with `formatOptions` accepting `Intl.NumberFormatOptions` (currency, percent, unit, etc.)
* Gesture-handler-based drag and tap-to-position on track
* Value clamping, stepping, and multi-thumb support
* Spring-animated thumb scale via configurable `animation` prop
* Accessibility: each thumb receives `role="slider"` with full `accessibilityValue` (min, max, now, text)
* `useSlider` hook exposes slider context for advanced use cases
**Usage:**
```tsx
import { Slider } from "heroui-native";
export function BasicSlider() {
return (
);
}
export function RangeSlider() {
return (
{({ thumbs }) => (
<>
{thumbs.map((_, i) => (
))}
>
)}
);
}
```
For complete documentation and examples, see the [Slider component page](/docs/native/components/slider).
**Related PR:** [#305](https://github.com/heroui-inc/heroui-native/pull/305)
#### ListGroup
The ListGroup component renders grouped list items inside a Surface container, providing a polished navigation-list pattern commonly used in settings screens, menus, and content browsers. Each item supports prefix, content (title + description), and suffix slots with a default chevron-right navigation indicator.
**Features:**
* Surface-based container with rounded corners and consistent spacing
* Compound sub-components: `ListGroup.Item`, `ListGroup.ItemPrefix`, `ListGroup.ItemContent`, `ListGroup.ItemTitle`, `ListGroup.ItemDescription`, `ListGroup.ItemSuffix`
* Default chevron-right icon in `ItemSuffix` via internal `ChevronRightIcon`
* Pressable items with PressableFeedback integration
* Fully customizable slots for icons, badges, and other content
**Usage:**
```tsx
import { ListGroup } from "heroui-native";
export function Example() {
return (
console.log("Profile")}>
ProfileManage your account console.log("Settings")}>
SettingsApp preferences
);
}
```
For complete documentation and examples, see the [ListGroup component page](/docs/native/components/list-group).
**Related PR:** [#302](https://github.com/heroui-inc/heroui-native/pull/302)
#### SearchField
The SearchField component provides a dedicated input for search and filtering scenarios, built with the same compound-component pattern used by TextField. It includes a search icon, clearable input, and an auto-hiding clear button that disappears when the input is empty.
**Features:**
* Compound sub-components: `SearchField.Group`, `SearchField.SearchIcon`, `SearchField.Input`, `SearchField.ClearButton`
* `ClearButton` auto-hides when value is empty and clears search text on press
* `SearchIcon` supports custom children to replace the default magnifying glass SVG
* Validation state support with visual feedback
* Disabled state support
* Seamless integration with Label, Description, and FieldError
**Usage:**
```tsx
import { Label, SearchField } from "heroui-native";
export function Example() {
return (
);
}
```
For complete documentation and examples, see the [SearchField component page](/docs/native/components/search-field).
**Related PR:** [#299](https://github.com/heroui-inc/heroui-native/pull/299)
### Select Multi-Selection Mode
The [Select](/docs/native/components/select) component now supports multi-item selection via a new `selectionMode` prop. The `RootProps` type is now generic on `SelectionMode`, so TypeScript correctly resolves `value` and `onValueChange` types per mode—`SelectOption` for single, `SelectOption[]` for multiple.
**Features:**
* `selectionMode="multiple"` enables toggling multiple items; `closeOnPress` defaults to `false` in multiple mode
* Type-safe generics: `RootProps` resolves `value` and `onValueChange` types via `SelectValueType`
* `Select.Value` formats multiple labels as "Apple, Banana and Cherry" using `formatSelectedLabels`
* Single mode remains fully backward-compatible (default)
**Usage:**
```tsx
import { Select } from "heroui-native";
export function MultiSelect() {
return (
);
}
```
**Related PR:** [#298](https://github.com/heroui-inc/heroui-native/pull/298)
### New Subcomponents
#### PressableFeedback.Scale
A new compound sub-component for opt-in scale animation composability. `PressableFeedback.Scale` lets you add scale press animations to any pressable element—such as `ListGroup.Item`—without needing the root `PressableFeedback` to manage scale.
**Usage:**
```tsx
import { PressableFeedback } from "heroui-native";
{/* item content */}
```
**Related PR:** [#302](https://github.com/heroui-inc/heroui-native/pull/302)
## Component Improvements
### Select Trigger and State Fixes
The [Select](/docs/native/components/select) component has been improved with several targeted fixes to the trigger and controllable state system.
**Improvements:**
* Custom `className` is now correctly forwarded to the trigger's style computation, resolving cases where user-provided classes were silently dropped
* `useControllableState` now resets internal state when transitioning from controlled to uncontrolled, preventing stale selections from persisting
* Trigger measures position via `onLayout` to properly support `isDefaultOpen`
* Updated trigger styles to use `gap-3`, `py-3.5` padding, and `flex-1` on the value text for improved layout
**Related PR:** [#298](https://github.com/heroui-inc/heroui-native/pull/298)
### Avatar asChild Image Fix
The [Avatar](/docs/native/components/avatar) component's `AvatarImage` now correctly separates `source`, `style`, and `asChild` from rest props when forwarding to the underlying primitive, fixing an issue where all props were incorrectly spread to the image component when using `asChild`.
**Related PR:** [#298](https://github.com/heroui-inc/heroui-native/pull/298)
## API Enhancements
### Button Feedback API Refactor
The [Button](/docs/native/components/button) component's pressable feedback API has been refactored into a unified, type-safe `feedbackVariant` + `animation` prop pattern, replacing the previous multi-prop approach.
**New Capability:**
```tsx
import { Button } from "heroui-native";
// Scale + highlight (default)
// Scale + ripple
// Scale only
// Custom animation configuration
```
The `animation` prop is a discriminated union typed per variant, providing full type-safety for each feedback configuration.
New utility helpers `resolveAnimationObject` and `isAnimationDisabled` in `button.utils.ts` centralise animation prop resolution.
**Related PR:** [#302](https://github.com/heroui-inc/heroui-native/pull/302)
## Dependencies
### Relaxed Peer Dependency Constraints
Peer dependency version constraints have been relaxed to use caret (`^`) and range (`>=`) specifiers instead of restrictive tilde (`~`) or pinned versions. This improves compatibility for consumers on newer dependency versions, particularly those using Expo SDK 55.
**Changes:**
* `react-native-reanimated`: `~4.1.1` → `^4.1.1` (allows minor updates)
* `react-native-safe-area-context`: `~5.6.0` → `^5.6.0` (allows minor updates)
* `react-native-svg`: `15.12.1` → `^15.12.1` (allows patch/minor updates)
* `react-native-worklets`: `0.5.1` → `>=0.5.1` (allows any version 0.5.1+)
No runtime code changes are included—existing projects with previously valid versions continue to work without modification.
**Related PR:** [#306](https://github.com/heroui-inc/heroui-native/pull/306)
## ⚠️ Breaking Changes
### Button Feedback API
The `pressableFeedbackVariant`, `pressableFeedbackHighlightProps`, and `pressableFeedbackRippleProps` props on Button have been removed. Consumers must migrate to `feedbackVariant` and the unified `animation` prop.
**Migration:**
Update all Button feedback prop usages:
```tsx
// Before
// After
```
**Variant mapping:**
* `"highlight"` → `"scale-highlight"` (default)
* `"ripple"` → `"scale-ripple"`
* `"none"` → `"scale"` or `"none"`
**Available options:**
* `"scale-highlight"` - Scale down with highlight overlay (default)
* `"scale-ripple"` - Scale down with ripple effect
* `"scale"` - Scale down only
* `"none"` - No feedback animation
**Related PR:** [#302](https://github.com/heroui-inc/heroui-native/pull/302)
## Bug Fixes
This release includes fixes for the following issues:
* **[Issue #291](https://github.com/heroui-inc/heroui-native/issues/291)**: Fixed `Select.Trigger` variant prop being overwritten by `className`. Custom class names passed to the trigger are now correctly forwarded to the style computation instead of being silently dropped.
* **[Issue #294](https://github.com/heroui-inc/heroui-native/issues/294)**: Resolved compatibility with `react-native-worklets` 0.7.x and `react-native-reanimated` 4.2.x (Expo SDK 55). Peer dependency constraints have been relaxed to accept these newer versions without producing resolution warnings.
**Related PRs:**
* [#298](https://github.com/heroui-inc/heroui-native/pull/298)
* [#306](https://github.com/heroui-inc/heroui-native/pull/306)
## Updated Documentation
The following documentation pages have been updated to reflect the changes in this release:
* [SearchField](/docs/native/components/search-field) - New component documentation with usage examples and API reference
* [ListGroup](/docs/native/components/list-group) - New component documentation with usage examples and API reference
* [Slider](/docs/native/components/slider) - New component documentation with usage examples and API reference
* [Select](/docs/native/components/select) - Multi-selection mode, trigger className fix, and controllable state improvements
* [Button](/docs/native/components/button) - Updated feedback API documentation with new `feedbackVariant` and `animation` props
* [Avatar](/docs/native/components/avatar) - Fixed `asChild` image prop spreading documentation
* [PressableFeedback](/docs/native/components/pressable-feedback) - New `PressableFeedback.Scale` subcomponent documentation
## Links
* [Component Documentation](../components)
* [GitHub Repository](https://github.com/heroui-inc/heroui-native)
## Contributors
Thanks to everyone who contributed to this release!
# RC 3
**Category**: native
**URL**: https://v3.heroui.com/docs/native/releases/rc-3
**Source**: https://raw.githubusercontent.com/heroui-inc/heroui/refs/heads/v3/apps/docs/content/docs/native/releases/rc-3.mdx
> TagGroup, Menu, and InputGroup components, Bottom Sheet Android back press fix, Expo 55 compatibility
February 26, 2026
RC 3 delivers three new components—TagGroup for selectable tag management, Menu for popover/bottom-sheet-based dropdown menus, and InputGroup for decorated text inputs with auto-measuring prefix/suffix slots. This release also brings Android hardware back button support for all bottom-sheet-based overlays, Expo 55 compatibility with a critical `combineStyles` fix that preserves Reanimated animated style bindings, and several dependency upgrades.
## Installation
Update to the latest version:
```bash
npm i heroui-native
```
```bash
pnpm add heroui-native
```
```bash
yarn add heroui-native
```
```bash
bun add heroui-native
```
**Using AI assistants?** Simply prompt "Hey Cursor, update HeroUI Native to the latest version" and your AI assistant will automatically compare versions and apply the necessary changes. Learn more about the [HeroUI Native MCP Server](/docs/native/getting-started/mcp-server).
## Try It Out
Experience all the RC 3 improvements in action with our preview app! You can explore the new TagGroup, Menu, and InputGroup components, Android back press support for bottom sheets, and all the bug fixes directly on your device.
### Prerequisites
Make sure you have the latest version of [Expo Go](https://expo.dev/go) installed on your mobile device.
### How to Access
**Option 1: Scan the QR Code**
Use your device's camera or Expo Go app to scan:
> **Note for Android users:** If scanning the QR code with your device's camera or other scanner apps redirects to a browser and shows a 404 error, open Expo Go first and use its built-in QR scanner instead.
**Option 2: Click the Link**
**[📱 Open Demo App in Expo Go](https://link.heroui.com/native-demo)**
This will automatically open the app in Expo Go if it's installed on your device.
## What's New
### New Components
This release introduces **3 new** components:
* **[TagGroup](/docs/native/components/tag-group)**: Compound component for displaying and managing selectable tags with optional removal, single/multiple selection, and form field integration.
* **[Menu](/docs/native/components/menu)**: Dropdown menu system with popover and bottom-sheet presentation modes, single/multiple selection, item variants, and animated press feedback.
* **[InputGroup](/docs/native/components/input-group)**: Decorated text input with absolutely-positioned prefix/suffix slots that auto-measure widths and apply matching padding to the input.
#### TagGroup
The TagGroup component provides a compound component pattern for rendering selectable tag groups with optional removal support. It supports single and multiple selection modes, controlled and uncontrolled APIs, two visual variants (default and surface), three sizes, disabled states, and full form field integration with Label, Description, and FieldError.
**Features:**
* Compound sub-components: `TagGroup.List`, `TagGroup.Item`, `TagGroup.ItemLabel`, `TagGroup.ItemRemoveButton`
* Single and multiple selection modes with controlled/uncontrolled APIs
* Two visual variants: `default` and `surface`
* Three sizes: `sm`, `md`, `lg`
* Per-item disabled state and `disabledKeys` support
* Remove functionality via `onRemove` callback and `TagGroup.ItemRemoveButton`
* Empty state rendering via `renderEmptyState` on `TagGroup.List`
* Form field integration with Label, Description, FieldError, `isInvalid`, and `isRequired`
* `useTagGroup` and `useTagGroupItem` hooks for advanced use cases
**Usage:**
```tsx
import { TagGroup } from "heroui-native";
export function BasicTagGroup() {
return (
ReactVueSvelte
);
}
export function RemovableTagGroup() {
const [items, setItems] = useState(["React", "Vue", "Svelte"]);
return (
setItems((prev) => prev.filter((i) => !keys.has(i)))}>
{items.map((item) => (
{item}
))}
);
}
```
For complete documentation and examples, see the [TagGroup component page](/docs/native/components/tag-group).
**Related PR:** [#309](https://github.com/heroui-inc/heroui-native/pull/309)
#### Menu
The Menu component provides a dropdown menu system built on a compound component pattern, supporting both popover and bottom-sheet presentation modes. It includes full Reanimated-based press animations, single and multiple selection modes, item variants (default and danger), indicator styles, and configurable placement.
**Features:**
* Compound sub-components: `Menu.Trigger`, `Menu.Portal`, `Menu.Overlay`, `Menu.Content`, `Menu.Label`, `Menu.Group`, `Menu.Item`, `Menu.ItemTitle`, `Menu.ItemDescription`, `Menu.ItemIndicator`
* Two presentation modes: `popover` and `bottom-sheet` with configurable placement (`top`, `bottom`, `left`, `right`)
* Single and multiple selection via `Menu.Group` with `selectedKeys`/`onSelectionChange`
* Item press animations (scale + background color) via Reanimated with full customization through the `animation` prop
* Item variants: `default` and `danger`
* Indicator variants: `checkmark`, `dot`, and custom content
* `Menu.Label` for section headings
* `shouldCloseOnSelect` control per group
**Usage:**
```tsx
import { Menu } from "heroui-native";
export function BasicMenu() {
return (
);
}
export function MenuWithSections() {
return (
);
}
```
For complete documentation and examples, see the [Menu component page](/docs/native/components/menu).
**Related PR:** [#312](https://github.com/heroui-inc/heroui-native/pull/312)
#### InputGroup
The InputGroup component provides a decorated text input with absolutely-positioned `Prefix` and `Suffix` sub-components that automatically measure their widths via `onLayout` and apply matching padding to the Input. It features a convenient `isDecorative` prop that handles accessibility and pointer-event boilerplate for decorative addons in a single boolean, and a root `isDisabled` prop that cascades disabled state to all children via context.
**Features:**
* Compound sub-components: `InputGroup.Prefix`, `InputGroup.Suffix`, `InputGroup.Input`
* Auto-padding: Prefix/Suffix widths are measured via `onLayout` and automatically applied as `paddingLeft`/`paddingRight` on the Input
* `isDecorative` prop on Prefix/Suffix handles `pointerEvents="none"`, `accessibilityElementsHidden`, and `importantForAccessibility` in a single boolean
* Root `isDisabled` cascades to all children via context (Prefix/Suffix opacity + pointer-events, Input editability)
* `InputGroup.Input` is a direct pass-through — consumers manage `value`/`onChangeText` directly on the Input
**Usage:**
```tsx
import { InputGroup } from "heroui-native";
export function SearchInput() {
return (
);
}
export function DisabledInput() {
return (
);
}
```
For complete documentation and examples, see the [InputGroup component page](/docs/native/components/input-group).
**Related PR:** [#313](https://github.com/heroui-inc/heroui-native/pull/313)
## Component Improvements
### Bottom Sheet Android Back Press Support
The [Bottom Sheet](/docs/native/components/bottom-sheet) shared container now handles the Android hardware back button, dismissing any open bottom sheet when pressed. The `BackHandler` listener is only active while the sheet is open, preventing closed instances from consuming the event. This fix applies globally to all bottom-sheet-based components.
**Supported components:**
* [Bottom Sheet](/docs/native/components/bottom-sheet)
* [Popover](/docs/native/components/popover)
* [Select](/docs/native/components/select)
The fix uses React Native's `BackHandler` API which is a no-op on iOS, so no platform-specific handling is needed.
**Related PR:** [#308](https://github.com/heroui-inc/heroui-native/pull/308)
### Slot `combineStyles` Fix
The Slot primitive's `combineStyles` function now returns style arrays instead of using `StyleSheet.flatten`, which was destroying Reanimated `SharedValue` and `useAnimatedStyle` bindings by deep-copying style objects into plain objects.
**Improvements:**
* `combineStyles` preserves Reanimated animated style bindings by returning arrays
* React Native handles nested style arrays natively, so consumer behavior is unchanged
* Fixes animation breakages across components that compose via the Slot primitive
**Related PR:** [#314](https://github.com/heroui-inc/heroui-native/pull/314)
## Dependencies
### Expo 55 Compatibility
Dependency versions have been updated for Expo SDK 55 compatibility:
* `uniwind`: 1.2.7 → 1.3.2
* `@gorhom/bottom-sheet`: ^5 → ^5.2.8
The `combineStyles` fix described above is the primary code change enabling Expo 55 support, as the previous `StyleSheet.flatten` approach broke Reanimated style bindings in the new SDK.
**Related PR:** [#314](https://github.com/heroui-inc/heroui-native/pull/314)
## Bug Fixes
This release includes fixes for the following issues:
* **[Issue #272](https://github.com/heroui-inc/heroui-native/issues/272)**: Resolved `FullWindowOverlay` interfering with the React Native element inspector.
* **[Issue #280](https://github.com/heroui-inc/heroui-native/issues/280)**: Fixed Avatar component and other Reanimated-dependent components breaking under Expo 55. The `combineStyles` function was destroying Reanimated animated style bindings via `StyleSheet.flatten`; it now returns style arrays to preserve `SharedValue` and `useAnimatedStyle` bindings.
**Related PRs:**
* [#308](https://github.com/heroui-inc/heroui-native/pull/308)
* [#314](https://github.com/heroui-inc/heroui-native/pull/314)
## Updated Documentation
The following documentation pages have been updated to reflect the changes in this release:
* [TagGroup](/docs/native/components/tag-group) - New component documentation with usage examples and API reference
* [Menu](/docs/native/components/menu) - New component documentation with usage examples and API reference
* [InputGroup](/docs/native/components/input-group) - New component documentation with usage examples and API reference
## Links
* [Component Documentation](../components)
* [GitHub Repository](https://github.com/heroui-inc/heroui-native)
## Contributors
Thanks to everyone who contributed to this release!
# RC 4
**Category**: native
**URL**: https://v3.heroui.com/docs/native/releases/rc-4
**Source**: https://raw.githubusercontent.com/heroui-inc/heroui/refs/heads/v3/apps/docs/content/docs/native/releases/rc-4.mdx
> SubMenu component, Slider Output composition, PressableFeedback ripple fix, Bottom Sheet back handler fix
March 6, 2026
RC 4 introduces the SubMenu compound component for nested expandable menus with spring-animated expand/collapse, refactors Slider Output with slot-based styling and `textProps` forwarding, and adds `disallowEmptySelection` to Menu.Group for radio-group behavior. This release also resolves the PressableFeedback ripple blink on rapid presses with a dual-layer buffer system, fixes the Bottom Sheet Android back handler to respect `enablePanDownToClose`.
## Installation
Update to the latest version:
```bash
npm i heroui-native
```
```bash
pnpm add heroui-native
```
```bash
yarn add heroui-native
```
```bash
bun add heroui-native
```
**Using AI assistants?** Simply prompt "Hey Cursor, update HeroUI Native to the latest version" and your AI assistant will automatically compare versions and apply the necessary changes. Learn more about the [HeroUI Native MCP Server](/docs/native/getting-started/mcp-server).
## Try It Out
Experience all the RC 4 improvements in action with our preview app! You can explore the new SubMenu component, improved Slider Output, and all the bug fixes directly on your device.
### Prerequisites
Make sure you have the latest version of [Expo Go](https://expo.dev/go) installed on your mobile device.
### How to Access
**Option 1: Scan the QR Code**
Use your device's camera or Expo Go app to scan:
> **Note for Android users:** If scanning the QR code with your device's camera or other scanner apps redirects to a browser and shows a 404 error, open Expo Go first and use its built-in QR scanner instead.
**Option 2: Click the Link**
**[📱 Open Demo App in Expo Go](https://link.heroui.com/native-demo)**
This will automatically open the app in Expo Go if it's installed on your device.
## What's New
### SubMenu Component
The [Menu](/docs/native/components/menu) component now supports nested expandable sub-menus via the new `SubMenu` compound component. SubMenu nests inside `Menu.Content` and reveals additional items on press with spring-based expand/collapse animations and indicator rotation.
**Features:**
* Compound sub-components: `SubMenu`, `SubMenu.Trigger`, `SubMenu.TriggerIndicator`, `SubMenu.Content`
* Spring-based expand/collapse animation with indicator rotation
* Headless primitive layer with context, controlled/uncontrolled open state, and accessibility attributes (`role`, `aria-expanded`, `aria-disabled`)
* Parent menu coordination: popover scales to 0.98, shadow is removed, and non-SubMenu items fade to 40% opacity with `pointer-events-none` when a SubMenu is open
* Menu content switches to `FadeOut` exit animation when a SubMenu is open to avoid conflicting scale animations
* `useSubMenu` hook for advanced use cases
**Usage:**
```tsx
import { Menu, SubMenu } from "heroui-native";
export function MenuWithSubMenu() {
return (
);
}
```
For complete documentation and examples, see the [Menu component page](/docs/native/components/menu).
**Related PR:** [#331](https://github.com/heroui-inc/heroui-native/pull/331)
## Component Improvements
### Slider Output Composition Refactor
The [Slider](/docs/native/components/slider) Output component has been refactored to use a proper slot-based architecture with `container` and `text` slots, and introduces `textProps` for forwarding props to the inner text element.
**Improvements:**
* Slot-based styling: `output` class split into `container` and `text` slots with a new `classNames` prop (`classNames={{ container, text }}`) for granular style targeting
* Composition fix: `HeroText` now only renders for default content; custom children render directly without an extra text wrapper
* New `textProps` prop on `Slider.Output` for forwarding arbitrary props (e.g., `maxFontSizeMultiplier`) to the inner text element
* `OutputSlots` type exported from the styles module for external consumption
**Related PR:** [#328](https://github.com/heroui-inc/heroui-native/pull/328)
### Menu.Group `disallowEmptySelection`
The [Menu](/docs/native/components/menu) `Menu.Group` component now supports a `disallowEmptySelection` prop that prevents deselecting the last item in `single` selection mode, enabling radio-group behavior.
**Usage:**
```tsx
List ViewGrid View
```
**Related PR:** [#331](https://github.com/heroui-inc/heroui-native/pull/331)
### Bottom Sheet `enablePanDownToClose` Consistency
The [Bottom Sheet](/docs/native/components/bottom-sheet) component now correctly respects the `enablePanDownToClose` prop for Android hardware back button behavior. Previously, the back button would close the sheet even when `enablePanDownToClose` was set to `false`.
**Improvements:**
* The `enablePanDownToClose` prop is threaded through to `BottomSheetContentContainer` (defaults to `true`)
* The `BackHandler` event listener is only registered when both `isOpen` and `enablePanDownToClose` are `true`
* Bottom sheets with `enablePanDownToClose={false}` are no longer dismissible via the Android back button
**Related PR:** [#327](https://github.com/heroui-inc/heroui-native/pull/327)
## ⚠️ Breaking Changes
### Chip Component Sizing
The [Chip](/docs/native/components/chip) component's size variants have been migrated from fixed heights to padding-based sizing to accommodate dynamic text scaling at larger accessibility font sizes.
**Migration:**
Custom styles relying on the previous `h-5`/`h-6`/`h-7` chip heights should be updated to use the new padding-based approach:
```tsx
// Before — Fixed height sizing
// Chip used h-5 (sm), h-6 (md), h-7 (lg)
// After — Padding-based sizing
// Chip uses py-0.5 (sm), py-[3px] (md), py-1 (lg)
// Border radius updated: rounded-xl → rounded-2xl/rounded-3xl
```
## Updated Documentation
The following documentation pages have been updated to reflect the changes in this release:
* [Menu](/docs/native/components/menu) - SubMenu component documentation with anatomy, usage examples, full API reference, and `useSubMenu` hook docs
* [Slider](/docs/native/components/slider) - Updated Output component documentation with slot-based styling and `textProps`
## Links
* [Component Documentation](../components)
* [GitHub Repository](https://github.com/heroui-inc/heroui-native)
## Contributors
Thanks to everyone who contributed to this release!
# All Components
**Category**: react
**URL**: https://v3.heroui.com/docs/react/components
**Source**: https://raw.githubusercontent.com/heroui-inc/heroui/refs/heads/v3/apps/docs/content/docs/react/components/index.mdx
> Explore the full list of components available in the library. More are on the way.
## Buttons
## Collections
## Colors
## Controls
## Data Display
## Date and Time
## Feedback
## Forms
## Layout
## Media
## Navigation
## Overlays
## Pickers
## Typography
## Utilities
# Introduction
**Category**: react
**URL**: https://v3.heroui.com/docs/react/getting-started
**Source**: https://raw.githubusercontent.com/heroui-inc/heroui/refs/heads/v3/apps/docs/content/docs/react/getting-started/index.mdx
> An open-source UI component library for building beautiful and accessible user interfaces.
HeroUI is a React component library built on [Tailwind CSS v4](https://tailwindcss.com/) and [React Aria Components](https://react-spectrum.adobe.com/react-aria/index.html). Every component comes with smooth animations, polished details, and built-in accessibility—ready to use, fully customizable.
## Why HeroUI?
**Beautiful by default** — Professional look out of the box, no extra styling needed.
**Accessible** — Built on [React Aria Components](https://react-spectrum.adobe.com/react-aria/components.html) with focus management, keyboard navigation, and screen reader support.
**Flexible** — Each component is made of customizable parts. Change what you need, leave the rest.
**Developer-friendly** — Fully typed APIs, predictable patterns, and excellent autocompletion.
**Maintained** — We handle updates, bug fixes, and new features. Just update the package.
**Lightweight** — Tree-shaken. Only what you use goes into your app.
**Future-proof** — Built for [React 19](https://react.dev/blog/2024/12/05/react-19) and [Tailwind v4](https://tailwindcss.com/blog/tailwindcss-v4), designed for AI-assisted development.
## A Living Library, Not Copy-Paste
Copy-paste code works until it breaks. You're left maintaining outdated dependencies that stop evolving.
HeroUI is different. It's a living library that grows with you:
* Automatic updates and fixes
* New features without extra work
* Components stay current with React, Tailwind, and browsers
* Deep customization, not shallow theme tweaks
* AI-friendly APIs for code generation
HeroUI v3 is not a snapshot—it's a garden that keeps growing. 🌱
## HeroUI Ecosystem
* **🌐 HeroUI v3** (web) — You're here! React components with Tailwind CSS v4
* **📱 [HeroUI Native](https://link.heroui.com/native)** (mobile) — Beautiful components for React Native
* **🤖 [HeroUI Chat](https://heroui.chat?ref=heroui-v3)** (text-to-app) — Create apps with natural language
* **🧠 UI for LLMs** — New platform & MCPs coming soon
**Why React Aria?** We chose React Aria for accessibility at scale. We've used it since HeroUI v2, and v3 keeps familiar API conventions like `isDisabled` and `onPress`. Thanks to [Devon Govett](https://x.com/devongovett) and the Adobe team.
## FAQ
**Is HeroUI free?**
Yes, completely free and open source under the MIT license.
**Is it production-ready?**
Currently in **beta**. We're actively working towards a stable release with community feedback.
**Can I customize the components?**
Yes! Use Tailwind utilities, CSS variables, [BEM](https://getbem.com/) modifiers, or compose component parts differently. Every slot is customizable.
**Does it work with TypeScript?**
Fully typed with excellent IDE support and autocompletion.
**What about accessibility?**
Built on React Aria Components for WCAG compliance. Keyboard navigation, focus management, and screen reader support included.
**Can I use the styles without React?**
Yes, the CSS can be applied to plain HTML. See our [Tailwind Play example](https://play.tailwindcss.com/Ioomj2xdce).
**Is there a Figma file?**
Yes! Access our design system at [HeroUI Figma Kit V3](https://www.figma.com/community/file/1546526812159103429).
## Get Involved
Join the community, share feedback, or contribute:
* [GitHub Discussions](https://github.com/heroui-inc/heroui/discussions)
* [Discord](https://discord.gg/9b6yyZKmH4)
* [X/Twitter](https://x.com/hero_ui)
* [Contributing Guidelines](https://github.com/heroui-inc/heroui/blob/main/CONTRIBUTING.md)
HeroUI is released under the [MIT License](https://github.com/heroui-inc/heroui/blob/main/LICENSE).
# All Releases
**Category**: react
**URL**: https://v3.heroui.com/docs/react/releases
**Source**: https://raw.githubusercontent.com/heroui-inc/heroui/refs/heads/v3/apps/docs/content/docs/react/releases/index.mdx
> All updates and changes to HeroUI v3, including new features, fixes, and breaking changes.
**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](/docs/ui-for-agents/mcp-server).
## Latest Release
### v3.0.0-rc.1
**March 14, 2026**
Seven new components ([Drawer](/docs/components/drawer), [ToggleButton](/docs/components/toggle-button), [ToggleButtonGroup](/docs/components/toggle-button-group), [Meter](/docs/components/meter), [ProgressBar](/docs/components/progress-bar), [ProgressCircle](/docs/components/progress-circle), [Toolbar](/docs/components/toolbar)), **virtualization** for [Table](/docs/components/table) and [ListBox](/docs/components/list-box), `ButtonGroup.Separator` + vertical orientation for [ButtonGroup](/docs/components/button-group), and React Aria Components bumped to v1.16.0.
[Read full release notes →](/docs/releases/v3-0-0-rc-1)
### v3.0.0-beta.8
**March 2, 2026**
This release adds three new components ([Badge](/docs/components/badge), [Pagination](/docs/components/pagination), [Table](/docs/components/table)) and new `InputContainer` composition APIs for [DateField](/docs/components/date-field) + [TimeField](/docs/components/time-field). ⚠️ **Breaking changes**: TextField CSS classes were renamed from `.text-field` to `.textfield`.
[Read full release notes →](/docs/releases/v3-0-0-beta-8)
### v3.0.0-beta.7
**February 18, 2026**
This release introduces a comprehensive **Date & Time** system with four new components ([Calendar](/docs/components/calendar), [RangeCalendar](/docs/components/range-calendar), [DatePicker](/docs/components/date-picker), [DateRangePicker](/docs/components/date-range-picker)), new [Switch.Content](/docs/components/switch) sub-component, explicit [Tabs.Separator](/docs/components/tabs) for opt-in separator lines, and ⚠️ **breaking changes** removing `hideSeparator` from Tabs and consolidating `DateInputGroup`/`ColorInputGroup` under their respective field components.
[Read full release notes →](/docs/releases/v3-0-0-beta-7)
### v3.0.0-beta.6
**February 6, 2026**
This release introduces a comprehensive **Color System** with six new components ([ColorPicker](/docs/components/color-picker), [ColorArea](/docs/components/color-area), [ColorSlider](/docs/components/color-slider), [ColorField](/docs/components/color-field), [ColorSwatch](/docs/components/color-swatch), [ColorSwatchPicker](/docs/components/color-swatch-picker)), major [Toast](/docs/components/toast) improvements with loading states and promise support, [Separator](/docs/components/separator) variants, and ⚠️ **breaking changes** renaming `Toast.Container` to `Toast.Provider` and updating CSS class names to hyphenated format.
[Read full release notes →](/docs/releases/v3-0-0-beta-6)
### v3.0.0-beta.5
* Fixed build issue
### v3.0.0-beta.4
**January 20, 2026**
**Critical Build Issue Fixed**: This version (beta.4) had a critical build issue that has been fixed in **beta.5**. Please upgrade to `@heroui/styles@3.0.0-beta.5` and `@heroui/react@3.0.0-beta.5` to ensure proper TypeScript declaration generation and export resolution.
This release introduces the new [Theme Builder](/themes) for visual theme customization, three new components ([Autocomplete](/docs/components/autocomplete), [Breadcrumbs](/docs/components/breadcrumbs), [Toast](/docs/components/toast)), secondary variant for [Tabs](/docs/components/tabs), primary/secondary variants for [Input](/docs/components/input) and [InputGroup](/docs/components/input-group), and ⚠️ **breaking changes** removing Link's underline variants and `isInSurface` prop from form components.
[Read full release notes →](/docs/releases/v3-0-0-beta-4)
### v3.0.0-beta.3
**December 19, 2025**
This release introduces seven new components ([ButtonGroup](/docs/components/button-group), [DateField](/docs/components/date-field), [ErrorMessage](/docs/components/error-message), [ScrollShadow](/docs/components/scroll-shadow), [SearchField](/docs/components/search-field), [TagGroup](/docs/components/tag-group), [TimeField](/docs/components/time-field)), adds `fullWidth` support for form and input components, introduces `hideSeparator` to [Tabs](/docs/components/tabs), [ButtonGroup](/docs/components/button-group), and [Accordion](/docs/components/accordion) for cleaner layouts, includes styling fixes, and ⚠️ **breaking changes** removing the `asChild` prop and updating [AlertDialog](/docs/components/alert-dialog) & [Modal](/docs/components/modal) backdrop variant.
[Read full release notes →](/docs/releases/v3-0-0-beta-3)
### v3.0.0-beta.2
**November 20, 2025**
This release introduces six essential new components ([AlertDialog](/docs/components/alert-dialog), [ComboBox](/docs/components/combo-box), [Dropdown](/docs/components/dropdown), [InputGroup](/docs/components/input-group), [Modal](/docs/components/modal), [NumberField](/docs/components/number-field)), enhances theme compatibility and motion preferences, improves the [Select](/docs/components/select) component API with a ⚠️ **breaking change**, plus various refinements and bug fixes.
[Read full release notes →](/docs/releases/v3-0-0-beta-2)
### v3.0.0-beta.1
**November 6, 2025**
This release introduces a comprehensive redesign of HeroUI v3, merging v2's beauty and animations with v3's simplicity. All components have been redesigned, 8 new components added ([Alert](/docs/compoenents/alert), [Checkbox](/docs/components/checkbox), [InputOTP](/docs/components/input-otp), [ListBox](/docs/components/listbox), [Select](/docs/components/select), [Slider](/docs/components/slider), [Surface](/docs/components/surface)), and the design system has been completely overhauled with better color tokens, shadows, and architecture. Includes breaking changes to design system variables, component APIs, and flexible component patterns.
[Read full release notes →](/docs/releases/v3-0-0-beta-1)
## Previous Releases
### v3.0.0-alpha.35
**October 21, 2025**
#### React Server Components Support
* Fixed critical issue where compound components didn't work in React Server Components (RSC)
* Moved compound pattern logic from components to index files, resolving `"use client"` conflicts
* **(⚠️ Breaking change)**: Main component now requires `.Root` suffix (e.g., `` → ``)
* Named exports remain unchanged and fully supported
#### React 19 Improvements
* Removed `forwardRef` (now native in [React 19](https://react.dev/blog/2024/12/05/react-19#ref-as-a-prop))
* Simplified Context usage (`Context.Provider` → [React 19](https://react.dev/blog/2024/12/05/react-19#context-as-a-provider))
#### Switch Component Refactoring
* **(⚠️ Breaking change)**: Split Switch and SwitchGroup into separate components
* Cleaner API: `` replaces `` and ``
* Matches Radio/RadioGroup pattern for consistency
* Separate styles, types, and implementations
#### Affected Components
All compound components now require `.Root` suffix: `Accordion`, `Avatar`, `Card`, `Disclosure`, `Fieldset`, `Kbd`, `Link`, `Popover`, `Radio`, `Switch`, `Tabs`, `Tooltip`
[Read full release notes →](/docs/releases/v3-0-0-alpha-35)
### v3.0.0-alpha.34
**October 15, 2025**
* Added Form-based components: [Description](/docs/components/description), [FieldError](/docs/components/field-error), [Fieldset](/docs/components/fieldset), [Form](/docs/components/form), [Input](/docs/components/input), [Label](/docs/components/label), [RadioGroup](/docs/components/radio-group), [TextField](/docs/components/text-field), and [TextArea](/docs/components/textarea).
* Introduced form field tokens `--field-*`
* Reorganized Storybook by category
* **(Breaking change)**: Renamed `--skeleton-default-animation-type` to `--skeleton-animation` in [Skeleton](/docs/components/skeleton)
* Aligned data-slot markers across components
* Improved documentation
[Read full release notes →](/docs/releases/v3-0-0-alpha-34)
### v3.0.0-alpha.33
**October 5, 2025**
* Upgraded RAC with [October 2, 2025 Release](https://react-spectrum.adobe.com/releases/2025-10-02.html)
* Reordered [Tabs](/docs/components/tabs) Indicator (**Breaking change**)
* Updated [Tabs](/docs/components/tabs) component to use React Aria's `SelectionIndicator`, now supports SSR
* Updated [Disclosure](/docs/components/disclosure) and [Disclosure Group](/docs/components/disclosure-group) components to use RAC CSS variables for the expand and collapse animations
* Updated [Switch](/docs/components/switch) component styles and animations
* Added `size` variants and added demo in [Switch](/docs/components/switch#sizes)
* Added related showcases in [Button](/docs/components/button), [Tabs](/docs/components/tabs), [Disclosure](/docs/components/disclosure), [Disclosure Group](/docs/components/disclosure-group)
* Improved documentation
[Read full release notes →](/docs/releases/v3-0-0-alpha-33)
### v3.0.0-alpha.32
**October 1, 2025**
Card component redesigned with [new variants](/docs/components/card), added [CloseButton](/docs/components/close-button) component, [MCP Server](/docs/ui-for-agents/mcp-server) for AI coding assistants, and improved documentation.
[Read full release notes →](/docs/releases/v3-0-0-alpha-32)
### v3.0.0-alpha.31
**September 22, 2025**
* 🎨 **Showcases page** - Gallery of sites built with HeroUI
* 🌀 **DisclosureGroup component** - Groups multiple disclosures together
* 📇 **Card component** (preview) - First version of card component
* 🔀 **Switch component** (preview) - Toggle switch for settings
## Release Schedule
HeroUI v3 follows a regular release cycle:
* **Alpha releases**: Weekly to bi-weekly during active development
* **Beta releases**: Monthly stabilization releases - In progress
* **Stable releases**: Quarterly major versions (Q4 2025 target)
## Contributing
Found an issue or want to contribute? Check out our [GitHub repository](https://github.com/heroui-inc/heroui).
# v3.0.0-alpha.32
**Category**: react
**URL**: https://v3.heroui.com/docs/react/releases/v3-0-0-alpha-32
**Source**: https://raw.githubusercontent.com/heroui-inc/heroui/refs/heads/v3/apps/docs/content/docs/react/releases/v3-0-0-alpha-32.mdx
> Card component redesign, CloseButton, MCP Server for AI assistants
October 1, 2025
This release adds AI development tools, updates the [Card component](/docs/components/card) API, and improves the developer experience.
## Installation
Update to the latest version:
```bash
npm i @heroui/styles@alpha @heroui/react@alpha
```
```bash
pnpm add @heroui/styles@alpha @heroui/react@alpha
```
```bash
yarn add @heroui/styles@alpha @heroui/react@alpha
```
```bash
bun add @heroui/styles@alpha @heroui/react@alpha
```
## What's New
### MCP Server
HeroUI now includes an [MCP server](/docs/ui-for-agents/mcp-server) that lets AI assistants like Cursor, Claude Code, and VS Code Copilot access HeroUI v3 documentation and component information directly.
**Quick Setup:**
### Cursor
Or manually add to **Cursor Settings** → **Tools** → **MCP Servers**:
```json
{
"mcpServers": {
"heroui-react": {
"command": "npx",
"args": ["-y", "@heroui/react-mcp@latest"]
}
}
}
```
### Claude Code
Run this command in your terminal:
```bash
claude mcp add heroui-react -- npx -y @heroui/react-mcp@latest
```
[Learn more](/docs/ui-for-agents/mcp-server)
### Card Component API Redesign
The [Card component](/docs/components/card) has been updated with a new variant system that makes it more flexible.
**Breaking Changes:**
* Replaced `surface` prop with new `variant` system
* Removed `Card.Image`, `Card.Details`, and `Card.CloseButton` (use composition instead)
* New variants: `flat`, `outlined`, `elevated`, `filled`
**Before:**
```tsx
Old Card
```
**After:**
```tsx
New Card
```
**New Features:**
* Horizontal layout support
* Avatar integration
* Background image support
* Improved accessibility with semantic HTML
[View Card documentation](/docs/components/card)
### CloseButton Component
Added a [CloseButton component](/docs/components/close-button) for closing dialogs, modals, and other dismissible elements.
```tsx
import {CloseButton} from "@heroui/react";
// Basic usage
console.log("Closed")} />
// With custom icon
```
## Documentation Improvements
### UI for Agents
* **[MCP Server documentation](/docs/ui-for-agents/mcp-server)** for development with AI assistants
* **[llms.txt](/docs/ui-for-agents/llms-txt)** file for LLM-friendly documentation
* Setup guides for popular AI coding tools
### Component Documentation
* **[Card](/docs/components/card)**: Rewrote documentation with anatomy, variants, and more examples
* **[Switch](/docs/components/switch)**: Added anatomy diagrams and better examples
* **[CloseButton](/docs/components/close-button)**: New documentation with usage examples
## Migration Guide
### Card Component Migration
1. **Update variant prop:**
* `surface="1"` → `variant="flat"`
* `surface="2"` → `variant="outlined"`
* `surface="3"` → `variant="elevated"`
* `surface="4"` → `variant="filled"`
* Custom surfaces → Use new variant system
2. **Update component structure:**
* Replace `Card.Image` with `` in `Card.Header`
* Replace `Card.Details` with `Card.Body`
* Move `Card.CloseButton` to use new `CloseButton` component
3. **Update imports:**
```tsx
// Add CloseButton if needed
import {Card, CloseButton} from "@heroui/react";
```
## Links
* [GitHub PR #5747](https://github.com/heroui-inc/heroui/pull/5747)
* [MCP Server Documentation](/docs/ui-for-agents/mcp-server)
* [Card Component Guide](/docs/components/card)
* [CloseButton Component](/docs/components/close-button)
## Contributors
Thanks to everyone who contributed to this release!
# v3.0.0-alpha.33
**Category**: react
**URL**: https://v3.heroui.com/docs/react/releases/v3-0-0-alpha-33
**Source**: https://raw.githubusercontent.com/heroui-inc/heroui/refs/heads/v3/apps/docs/content/docs/react/releases/v3-0-0-alpha-33.mdx
> RAC upgrade, Tabs indicator redesign, Switch size variant, Related showcase
October 5, 2025
This release upgrades React Aria Components, redesigns the Tabs indicator, adds Switch sizes, and includes component showcases.
## Installation
Update to the latest version:
```bash
npm i @heroui/styles@alpha @heroui/react@alpha
```
```bash
pnpm add @heroui/styles@alpha @heroui/react@alpha
```
```bash
yarn add @heroui/styles@alpha @heroui/react@alpha
```
```bash
bun add @heroui/styles@alpha @heroui/react@alpha
```
## What's New
### RAC Upgrade
Upgraded React Aria Components to the [October 2, 2025 Release](https://react-spectrum.adobe.com/releases/2025-10-02.html).
This release includes:
* CSS variables for animations
* Better SSR support
* Performance improvements for selection indicators
### Disclosure and Disclosure Group Updates
[Disclosure](/docs/components/disclosure) and [Disclosure Group](/docs/components/disclosure-group) now use React Aria's CSS variables for animations. The components use `--disclosure-panel-width` and `--disclosure-panel-height` variables that track the panel's actual size during expand/collapse.
### Tabs Indicator Redesign
[Tabs](/docs/components/tabs) now uses React Aria's `SelectionIndicator` and supports SSR. This fixes layout shifts on initial render.
**🚧 Breaking Changes:**
* Moved `Tabs.Indicator` inside each `Tabs.Tab`
**Before:**
```diff tsx
+
-
```
### Switch Updates
[Switch](/docs/components/switch) has updated styles and animations. Added `size` prop with options: `sm`, `md`, `lg`.
```tsx
import {Label, Switch} from "@heroui/react";
export function Sizes() {
return (
);
}
```
### Related showcases
Related showcases have been added in [Button](/docs/components/button), [Disclosure](/docs/components/disclosure), [Disclosure Group](/docs/components/disclosure-group) and [Tabs](/docs/components/tabs).
## Documentation Improvements
### Component Documentation
* **[Tabs](/docs/components/tabs)**: Updated anatomy, revised examples with new indicator design and added related showcase
* **[Switch](/docs/components/switch)**: Added size example and revised with-icon example
* **[Button](/docs/components/button)**, **[Disclosure](/docs/components/disclosure)**, **[Disclosure Group](/docs/components/disclosure-group)**: Added related showcase
## Migration Guide
### Tabs Component Migration
1. **Update component structure:**
* move `` inside each ``
## Links
* [GitHub PR #5777](https://github.com/heroui-inc/heroui/pull/5777)
* [Tabs Component](/docs/components/tabs)
* [Switch Component](/docs/components/switch)
* [Button Component](/docs/components/button)
* [Disclosure Component](/docs/components/disclosure)
* [Disclosure Group Component](/docs/components/disclosure-group)
## Contributors
Thanks to everyone who contributed to this release!
# v3.0.0-alpha.34
**Category**: react
**URL**: https://v3.heroui.com/docs/react/releases/v3-0-0-alpha-34
**Source**: https://raw.githubusercontent.com/heroui-inc/heroui/refs/heads/v3/apps/docs/content/docs/react/releases/v3-0-0-alpha-34.mdx
> Essentials for building forms with a clean API Form, TextField, RadioGroup, Label, Input, Fieldset and more.
October 15, 2025
This release introduces Form-based components, form field tokens, reorganizes Storybook, and aligns data-slot markers across components.
## Installation
Update to the latest version:
```bash
npm i @heroui/styles@alpha @heroui/react@alpha
```
```bash
pnpm add @heroui/styles@alpha @heroui/react@alpha
```
```bash
yarn add @heroui/styles@alpha @heroui/react@alpha
```
```bash
bun add @heroui/styles@alpha @heroui/react@alpha
```
**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](/docs/ui-for-agents/mcp-server).
## What's New
### Form-based Components
We've introduced a comprehensive set of form-based components built on React Aria Components, providing accessible and composable building blocks for creating forms. These components include [Description](/docs/components/description), [FieldError](/docs/components/field-error), [Fieldset](/docs/components/fieldset), [Form](/docs/components/form), [Input](/docs/components/input), [Label](/docs/components/label), [RadioGroup](/docs/components/radio-group), [TextField](/docs/components/text-field), and [TextArea](/docs/components/textarea).
#### Description
```tsx
import {Description, Input, Label} from "@heroui/react";
export function Basic() {
return (
We'll never share your email with anyone else.
);
}
```
#### FieldError
```tsx
"use client";
import {FieldError, Input, Label, TextField} from "@heroui/react";
import {useState} from "react";
export function Basic() {
const [value, setValue] = useState("jr");
const isInvalid = value.length > 0 && value.length < 3;
return (
setValue(e.target.value)}
/>
Username must be at least 3 characters
);
}
```
#### Fieldset
```tsx
"use client";
import {FloppyDisk} from "@gravity-ui/icons";
import {
Button,
Description,
FieldError,
FieldGroup,
Fieldset,
Form,
Input,
Label,
TextArea,
TextField,
} from "@heroui/react";
export function Basic() {
const onSubmit = (e: React.FormEvent) => {
e.preventDefault();
const formData = new FormData(e.currentTarget);
const data: Record = {};
// Convert FormData to plain object
formData.forEach((value, key) => {
data[key] = value.toString();
});
alert("Form submitted successfully!");
};
return (
);
}
```
#### Form
```tsx
"use client";
import {Check} from "@gravity-ui/icons";
import {Button, Description, FieldError, Form, Input, Label, TextField} from "@heroui/react";
export function Basic() {
const onSubmit = (e: React.FormEvent) => {
e.preventDefault();
const formData = new FormData(e.currentTarget);
const data: Record = {};
// Convert FormData to plain object
formData.forEach((value, key) => {
data[key] = value.toString();
});
alert(`Form submitted with: ${JSON.stringify(data, null, 2)}`);
};
return (
);
}
```
#### Input
```tsx
import {Input} from "@heroui/react";
export function Basic() {
return ;
}
```
#### Label
```tsx
import {Input, Label} from "@heroui/react";
export function Basic() {
return (
);
}
```
#### RadioGroup
```tsx
import {Description, Label, Radio, RadioGroup} from "@heroui/react";
export function Basic() {
return (
Choose the plan that suits you bestIncludes 100 messages per monthIncludes 200 messages per monthUnlimited messages
);
}
```
#### TextField
#### TextArea
```tsx
import {TextArea} from "@heroui/react";
export function Basic() {
return (
);
}
```
### Form Field Tokens
Introduced form field tokens `--field-*` for consistent styling across form components. See [Theming](/docs/handbook/theming#calculated-variables-tailwind) for the `--field-*` variables.
### Storybook Organization
Reorganized Storybook by category for better navigation and component discovery.
### Skeleton Animation Token
**🚧 Breaking Changes:** Renamed `--skeleton-default-animation-type` to `--skeleton-animation` in [Skeleton](/docs/components/skeleton) for consistency with other component tokens.
### Data-Slot Alignment
Aligned data-slot markers across components for consistent styling and customization. This standardization makes it easier to target specific component parts with CSS selectors and improves the overall developer experience when customizing component styles.
Components now use consistent `data-slot` attributes like:
* `data-slot="base"` for the root element
* `data-slot="label"` for label text
* `data-slot="description"` for description text
* `data-slot="error"` for error messages
This allows for predictable CSS targeting across all form components:
```css
.radio {
[data-slot="label"] {
/* Styles apply to radio labels */
}
}
```
## Documentation Improvements
### Component Documentation
* **[Link](/docs/components/link)**: Added Anatomy, and examples with Icon. Updated Link and Link.Icon props section.
* **[Description](/docs/components/description)**, **[FieldError](/docs/components/field-error)**, **[Fieldset](/docs/components/fieldset)**, **[Form](/docs/components/form)**, **[Input](/docs/components/input)**, **[Label](/docs/components/label)**, **[RadioGroup](/docs/components/radio-group)**, **[TextField](/docs/components/text-field)**, and **[TextArea](/docs/components/textarea)**: New documentation with usage examples
## Migration Guide
### Skeleton Component Migration
1. **Update animation token:**
* Replace `--skeleton-default-animation-type` with `--skeleton-animation`
## Links
* [GitHub PR #5780](https://github.com/heroui-inc/heroui/pull/5780)
* [Description Component](/docs/components/description)
* [FieldError Component](/docs/components/field-error)
* [Fieldset Component](/docs/components/fieldset)
* [Form Component](/docs/components/form)
* [Input Component](/docs/components/input)
* [Label Component](/docs/components/label)
* [RadioGroup Component](/docs/components/radio-group)
* [TextField Component](/docs/components/text-field)
* [TextArea Component](/docs/components/textarea)
* [Skeleton Component](/docs/components/skeleton)
## Contributors
Thanks to everyone who contributed to this release!
# v3.0.0-alpha.35
**Category**: react
**URL**: https://v3.heroui.com/docs/react/releases/v3-0-0-alpha-35
**Source**: https://raw.githubusercontent.com/heroui-inc/heroui/refs/heads/v3/apps/docs/content/docs/react/releases/v3-0-0-alpha-35.mdx
> React Server Components support for compound components, React 19 improvements, and critical bug fixes.
October 21, 2025
This release fixes a critical issue where **compound components didn't work correctly in React Server Components (RSC)**. Additionally, this release adopts React 19 best practices by removing `forwardRef` and simplifying context usage. The Switch component has been refactored to match the Radio/RadioGroup pattern, providing a cleaner and more consistent API.
## Installation
Update to the latest version:
```bash
npm i @heroui/styles@alpha @heroui/react@alpha
```
```bash
pnpm add @heroui/styles@alpha @heroui/react@alpha
```
```bash
yarn add @heroui/styles@alpha @heroui/react@alpha
```
```bash
bun add @heroui/styles@alpha @heroui/react@alpha
```
**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](/docs/ui-for-agents/mcp-server).
## What's New
### React Server Components Support
Compound components now work correctly in React Server Components. The previous implementation had the compound pattern logic inside components, which conflicted with the `"use client"` directive. This has been fixed by moving the pattern logic to component index files.
### React 19 Improvements
This release adopts React 19 best practices:
1. **Removed `forwardRef`**: No longer needed in React 19, where `ref` is now a prop ([React 19 docs](https://react.dev/blog/2024/12/05/react-19#ref-as-a-prop))
2. **Simplified Context**: `Context.Provider` replaced with just `Context` ([React 19 docs](https://react.dev/blog/2024/12/05/react-19#context-as-a-provider))
### Switch Component Architecture Improvement
The Switch component has been refactored to follow the same clean separation pattern as Radio/RadioGroup:
* **Separate Components**: Switch and SwitchGroup are now independent components (previously combined)
* **Cleaner API**: `` replaces the nested `` and `` pattern
* **Better Organization**: Separate styles, types, and implementations for each component
* **Consistent Pattern**: Matches the Radio/RadioGroup architecture for a more predictable API
**Before:**
```tsx
...
```
**After:**
```tsx
......
```
## ⚠️ Breaking Changes
### Main Component Requires `.Root` Suffix
To support React Server Components, the compound component pattern has been restructured. The main component now requires the `.Root` suffix when using the compound pattern.
**Before:**
```tsx
import { Avatar } from "@heroui/react"
JR
```
**After:**
```tsx
import { Avatar } from "@heroui/react"
JR
```
**Note:** Named exports (e.g., ``, ``, ``) remain unchanged and fully supported.
### Switch Component API Changes
The Switch component grouping API has been restructured to match the Radio/RadioGroup pattern:
**Before:**
```tsx
import { Switch } from "@heroui/react"
```
**After:**
```tsx
import { Switch, SwitchGroup } from "@heroui/react"
```
This change helps to:
* **Separate Components**: Switch and SwitchGroup are now independent components (previously combined)
* **Cleaner API**: `` replaces the nested `` and `` pattern
* **Better Organization**: Separate styles, types, and implementations for each component
* **Consistent Pattern**: Matches the Radio/RadioGroup architecture for a more predictable API
**Migration Steps:**
1. Import `SwitchGroup` separately: `import { Switch, SwitchGroup } from "@heroui/react"`
2. Replace `` with ``
3. Remove the nested `` wrapper
4. Individual `Switch.Root` components remain unchanged
#### Affected Components
All compound components are affected:
* `Accordion` → `Accordion.Root`
* `Avatar` → `Avatar.Root`
* `Card` → `Card.Root`
* `Disclosure` → `Disclosure.Root`
* `Fieldset` → `Fieldset.Root`
* `Kbd` → `Kbd.Root`
* `Link` → `Link.Root`
* `Popover` → `Popover.Root`
* `RadioGroup` → `RadioGroup.Root`
* `Switch` → `Switch.Root`
* `Tabs` → `Tabs.Root`
* `Tooltip` → `Tooltip.Root`
## Migration Guide
You have two options for using HeroUI compound components:
### Option 1: Update to Use `.Root` (Compound Pattern)
If you're using the compound pattern (dot notation), update your code to use `.Root` for the main component:
**Card Example:**
```tsx
import { Card } from "@heroui/react"
Card TitleCard description
Card content
Card footer
```
**Tabs Example:**
```tsx
import { Tabs } from "@heroui/react"
Tab 1Tab 2Panel 1Panel 2
```
[See more examples in the documentation](/docs/components/card)
**Avatar Example:**
```tsx
import { Avatar } from "@heroui/react"
JD
```
[See more examples in the documentation](/docs/components/avatar)
### Option 2: Use Named Exports
We added support for named exports for all compound components. You can use them like this:
**Card Example:**
```tsx
import {
CardRoot,
CardHeader,
CardTitle,
CardDescription,
CardContent,
CardFooter,
} from "@heroui/react"
Card TitleCard description
Card content
Card footer
```
**Tabs Example:**
```tsx
import { TabsRoot, TabListContainer, TabList, Tab, TabIndicator, TabPanel } from "@heroui/react"
Tab 1Tab 2Panel 1Panel 2
```
**Avatar Example:**
```tsx
import { Avatar, AvatarImage, AvatarFallback } from "@heroui/react"
JD
```
### Migration Steps
If you're using the compound pattern, you only need to update the main component to use `.Root`:
1. **Find all instances of compound components** (e.g., `` with `` inside)
2. **Add `.Root` to the main component**:
```tsx
// Before
// After
```
3. **That's it!** All child components (e.g., `Avatar.Image`, `Avatar.Fallback`) remain unchanged.
### Complete Migration Reference
| Component | Named Export Pattern | Compound Pattern (with `.Root`) | Additional Changes |
| -------------- | ------------------------------- | ------------------------------------- | ------------------------------------------------------- |
| **Accordion** | `` | `` | - |
| **Avatar** | `` | `` | - |
| **Card** | `` | `` | - |
| **Disclosure** | `` | `` | - |
| **Fieldset** | `
# v3.0.0-beta.1
**Category**: react
**URL**: https://v3.heroui.com/docs/react/releases/v3-0-0-beta-1
**Source**: https://raw.githubusercontent.com/heroui-inc/heroui/refs/heads/v3/apps/docs/content/docs/react/releases/v3-0-0-beta-1.mdx
> Major redesign with new design system, 8 new components, and improved developer experience.
November 6, 2025
This release introduces a comprehensive redesign of HeroUI v3, merging v2's beauty and animations with v3's simplicity. All components redesigned, 8 new components, and improved design system with better color tokens, shadows, and architecture.
## Installation
Update to the latest version:
```bash
npm i @heroui/styles@beta @heroui/react@beta
```
```bash
pnpm add @heroui/styles@beta @heroui/react@beta
```
```bash
yarn add @heroui/styles@beta @heroui/react@beta
```
```bash
bun add @heroui/styles@beta @heroui/react@beta
```
**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](/docs/ui-for-agents/mcp-server).
## What's New
### New Design System
We've spent weeks crafting a new design system that merges the soul of HeroUI v2 with the simplicity of v3. Every component has been redesigned with attention to detail, smooth animations, and improved developer experience. The new design system is available in our [Figma Kit V3](https://www.figma.com/community/file/1546526812159103429/heroui-figma-kit-v3).
The redesign brings:
* New color system that brings v3's vision to life and stands out for its uniqueness
* Refined shadow system for better depth perception
* New variables and tokens for better customization
* Automatic `isOnSurface` support for form-based components
* Enhanced border and spacing tokens
* Better contrast and accessibility
* Consistent component patterns across web and native
### New Components
This release introduces **8 new** essential components:
* **[Alert](#alert)**: Display important messages and notifications with status indicators.
* **[Checkbox & CheckboxGroup](#checkbox-checkboxgroup)**: Select multiple items from a list.
* **[InputOTP](#inputotp)**: One-time password input for authentication flows.
* **[Listbox](#listbox)**: Display a list of options and allow single or multiple selection.
* **[Select](#select)**: Dropdown selection component built on top of Listbox.
* **[Slider](#slider)**: Select a value from a range with custom marks and labels.
* **[Surface](#surface)**: Base surface component for creating elevated containers.
### Alert
```tsx
import {Alert, Button, CloseButton, Spinner} from "@heroui/react";
import React from "react";
export function Basic() {
return (
{/* Default - General information */}
New features available
Check out our latest updates including dark mode support and improved accessibility
features.
{/* Accent - Important information with action */}
Update available
A new version of the application is available. Please refresh to get the latest features
and bug fixes.
{/* Danger - Error with detailed steps */}
Unable to connect to server
We're experiencing connection issues. Please try the following:
Check your internet connection
Refresh the page
Clear your browser cache
{/* Without description */}
Profile updated successfully
{/* Custom indicator - Loading state */}
Processing your request
Please wait while we sync your data. This may take a few moments.
{/* Without close button */}
Scheduled maintenance
Our services will be unavailable on Sunday, March 15th from 2:00 AM to 6:00 AM UTC for
scheduled maintenance.
);
}
```
### Checkbox & CheckboxGroup
```tsx
import {Checkbox, Label} from "@heroui/react";
export function Basic() {
return (
);
}
```
```tsx
import {Checkbox, CheckboxGroup, Description, Label} from "@heroui/react";
export function Basic() {
return (
Choose all that applyLove building softwareEnjoy creating beautiful interfacesPassionate about content creation
);
}
```
### InputOTP
```tsx
import {InputOTP, Label, Link} from "@heroui/react";
export function Basic() {
return (
We've sent a code to a****@gmail.com
Didn't receive a code?
Resend
);
}
```
### Listbox
```tsx
import {Avatar, Description, Label, ListBox} from "@heroui/react";
export function Default() {
return (
B
bob@heroui.com
F
fred@heroui.com
M
martha@heroui.com
);
}
```
### Select
```tsx
import {Label, ListBox, Select} from "@heroui/react";
export function Default() {
return (
);
}
```
### Slider
```tsx
import {Label, Slider} from "@heroui/react";
export function Default() {
return (
);
}
```
### Surface
```tsx
import {Surface} from "@heroui/react";
export function Variants() {
return (
Default
Surface Content
This is a default surface variant. It uses bg-surface styling.
Secondary
Surface Content
This is a secondary surface variant. It uses bg-surface-secondary styling.
Tertiary
Surface Content
This is a tertiary surface variant. It uses bg-surface-tertiary styling.
Transparent
Surface Content
This is a transparent surface variant. It has no background, suitable for overlays and
cards with custom backgrounds.
);
}
```
### Improved Component APIs
Several components have been refined with better APIs:
* **Link**: Added `underline` and `underlineOffset` props for better customization
```tsx
import {Link} from "@heroui/react";
export function LinkBasic() {
return (
Call to action
);
}
```
* **Card**: Improved variants and styling system
```tsx
import {CircleDollar} from "@gravity-ui/icons";
import {Avatar, Button, Card, CloseButton, Link} from "@heroui/react";
export function WithImages() {
return (
{/* Row 1: Large Product Card - Available Soon */}
Become an ACME Creator!
Lorem ipsum dolor sit amet consectetur. Sed arcu donec id aliquam dolor sed amet
faucibus etiam.
Only 10 spotsSubmission ends Oct 10.
{/* Row 2 */}
{/* Left Column */}
{/* Top Card */}
PAYMENT
You can now withdraw on crypto
Add your wallet in settings to withdraw
Go to settings
{/* Bottom cards */}
{/* Left Card */}
JK
Indie Hackers
148 members
JK
By John
{/* Right Card */}
AB
AI Builders
362 members
M
By Martha
{/* Right Column */}
{/* Background image */}
{/* Header */}
NEO
Home Robot
{/* Footer */}
Available soon
Get notified
{/* Row 3 */}
{/* Left Column: Card */}
NEO
$499/m
{/* Right Column: Cards Stack */}
{/* 1 */}
Bridging the FutureToday, 6:30 PM
{/* 2 */}
Avocado HackathonWed, 4:30 PM
{/* 3 */}
Sound Electro | Beyond artFri, 8:00 PM
);
}
```
* **Chip**: Enhanced with size variants and improved color system
```tsx
import {Chip} from "@heroui/react";
export function ChipBasic() {
return (
DefaultAccentSuccessWarningDanger
);
}
```
* **Switch**: Redesigned from the ground up with improved visual design and animations
```tsx
import {Label, Switch} from "@heroui/react";
export function Basic() {
return (
);
}
```
* **RadioGroup**: Redesigned from the ground up with better API and styling
```tsx
import {Description, Label, Radio, RadioGroup} from "@heroui/react";
export function Basic() {
return (
Choose the plan that suits you bestIncludes 100 messages per monthIncludes 200 messages per monthUnlimited messages
);
}
```
### Flexible Component Patterns
HeroUI now supports flexible component syntax. Use compound patterns with or without `.Root`, or named exports - all three patterns work identically.
**Available patterns:**
```tsx
import { Avatar } from "@heroui/react"
// 1. Compound pattern (no .Root needed) - recommended
JD
// 2. Compound pattern with .Root - still supported
JD
// 3. Named exports
import { AvatarRoot, AvatarImage, AvatarFallback } from "@heroui/react"
JD
```
**Simple components** like Button work the same way:
```tsx
import { Button } from "@heroui/react"
// No .Root needed
// Or with .Root
Label
// Or named export
import { ButtonRoot } from "@heroui/react"
Label
```
**You can mix compound and named exports** in the same component:
```tsx
import { Avatar, AvatarFallback } from "@heroui/react"
JD
```
This provides:
* **Simpler API**: Main components no longer require `.Root` suffix
* **Flexibility**: Choose between compound pattern, compound with `.Root`, or named exports
* **Backward Compatibility**: The `.Root` pattern still works
* **Naming Consistency**: Standardized naming (e.g., "Container" instead of "Wrapper")
### Global Animation Control
HeroUI now supports easy global animation control through the `data-reduce-motion` attribute. Simply add `data-reduce-motion="true"` to your `` or `` tag to disable all animations across your application.
```html
```
HeroUI automatically respects user motion preferences using the `prefers-reduced-motion` media query and extends Tailwind's `motion-reduce:` variant to support both system preferences and manual control via the data attribute. This provides flexible control over animations while maintaining accessibility best practices.
Learn more about animations and motion preferences in the [Animation documentation](/docs/handbook/animation).
## ⚠️ Breaking Changes
### Design System Variables
#### Panel → Surface & Overlay
The `--panel` variable has been replaced with `--surface` and `--overlay` to better distinguish between non-overlay components (cards, accordions) and floating components (tooltips, popovers, modals).
**Before:**
```css
--panel: var(--white);
--panel-foreground: var(--foreground);
--shadow-panel: 0 0 1px 0 rgba(0, 0, 0, 0.3) inset, 0 2px 8px 0 rgba(0, 0, 0, 0.08);
```
**After:**
```css
--surface: var(--white);
--surface-foreground: var(--foreground);
--overlay: var(--white);
--overlay-foreground: var(--foreground);
--shadow-surface: 0 2px 4px 0 rgba(0, 0, 0, 0.04), 0 1px 2px 0 rgba(0, 0, 0, 0.06), 0 0 1px 0 rgba(0, 0, 0, 0.06);
--shadow-overlay: 0 4px 16px 0 rgba(24, 24, 27, 0.08), 0 8px 24px 0 rgba(24, 24, 27, 0.09);
```
**Migration:**
* Replace `bg-panel` with `bg-surface` for non-overlay components
* Replace `bg-panel` with `bg-overlay` for floating components
* Replace `shadow-panel` with `shadow-surface` or `shadow-overlay`
* Replace `--color-panel` with `--color-surface` or `--color-overlay`
#### Surface Levels Simplified
The `--surface-1`, `--surface-2`, and `--surface-3` variables have been removed. Surface levels are now automatically calculated from `--surface` using `color-mix`, so you only need to declare the base surface color.
**Before (manual declaration):**
```css
--surface-1: var(--background);
--surface-2: var(--color-neutral-100);
--surface-3: var(--color-neutral-200);
```
**After (auto-calculated):**
```css
/* You only declare the base surface */
--surface: var(--white);
--surface-foreground: var(--foreground);
/* HeroUI automatically calculates these using color-mix */
--color-surface-secondary: color-mix(in oklab, var(--surface) 94%, var(--surface-foreground) 6%);
--color-surface-tertiary: color-mix(in oklab, var(--surface) 92%, var(--surface-foreground) 8%);
--color-surface-quaternary: color-mix(in oklab, var(--surface) 86%, var(--surface-foreground) 14%);
```
**Customization:**
You can override the default calculations using Tailwind's `@theme` directive:
```css
@theme inline {
--color-surface-secondary: color-mix(in oklab, var(--surface) 96%, var(--surface-foreground) 4%);
--color-surface-tertiary: color-mix(in oklab, var(--surface) 94%, var(--surface-foreground) 6%);
--color-surface-quaternary: color-mix(in oklab, var(--surface) 90%, var(--surface-foreground) 10%);
}
```
**Migration:**
* Replace `bg-surface-1` with `bg-surface` (base surface)
* Replace `bg-surface-2` with `bg-surface-secondary` (auto-calculated)
* Replace `bg-surface-3` with `bg-surface-tertiary` (auto-calculated)
The same auto-calculation pattern applies to:
* **Background shades**: Calculated from `--background` → `background-secondary`, `background-tertiary`, `background-quaternary`
* **Soft colors**: Calculated from status colors → `accent-soft`, `danger-soft`, `warning-soft`, `success-soft`
#### Border Width Default Changed
The default border width has changed from `1px` to `0px`. Borders are now opt-in rather than default.
**Before:**
```css
--border-width: 1px;
```
**After:**
```css
--border-width: 0px; /* no border by default */
```
**Migration:**
* If you rely on default borders, explicitly set `border-width` in your custom styles
* Form fields now use `transparent` borders by default
#### Border Color Default Changed
The default border color opacity has changed from `15%` to `0%` (transparent).
**Before:**
```css
--border: oklch(0 0 0 / 15%);
```
**After:**
```css
--border: oklch(0 0 0 / 0%);
```
**Field Border Default:**
```css
--field-border: transparent; /* no border by default on form fields */
```
#### Shadow System Updates
The shadow system has been completely redesigned with separate shadows for surfaces and overlays.
**Before:**
```css
--panel-shadow: 0 0 1px 0 rgba(0, 0, 0, 0.3) inset, 0 2px 8px 0 rgba(0, 0, 0, 0.08);
--field-shadow: 0 0 0 0 rgba(255, 255, 255, 0.1) inset, 0 1px 2px 0 rgba(0, 0, 0, 0.05);
```
**After (Light):**
```css
--surface-shadow: 0 2px 4px 0 rgba(0, 0, 0, 0.04), 0 1px 2px 0 rgba(0, 0, 0, 0.06), 0 0 1px 0 rgba(0, 0, 0, 0.06);
--overlay-shadow: 0 4px 16px 0 rgba(24, 24, 27, 0.08), 0 8px 24px 0 rgba(24, 24, 27, 0.09);
--field-shadow: 0 2px 4px 0 rgba(0, 0, 0, 0.04), 0 1px 2px 0 rgba(0, 0, 0, 0.06), 0 0 1px 0 rgba(0, 0, 0, 0.06);
```
**After (Dark):**
```css
--surface-shadow: 0 0 0 0 transparent inset; /* No shadow on dark mode */
--overlay-shadow: 0 0 0 0 transparent inset; /* No shadow on dark mode */
--field-shadow: 0 0 0 0 transparent inset; /* Transparent shadow to allow ring utilities to work */
```
#### Accent Color Updates
The accent color has been updated for better contrast and visual appeal.
**Before:**
```css
--accent: var(--color-neutral-950);
--accent-foreground: var(--snow);
```
**After:**
```css
--accent: oklch(0.6204 0.195 253.83);
--accent-foreground: var(--snow);
```
#### Status Color Refinements
Success, warning, and danger colors have been refined for better consistency and contrast.
**Success:**
* **Before:** `oklch(0.5503 0.1244 153.56)`
* **After:** `oklch(0.7329 0.1935 150.81)`
* Foreground changed from `var(--snow)` to `var(--eclipse)` in light mode
**Warning:**
* **Before:** `oklch(0.7186 0.1521 64.85)`
* **After:** `oklch(0.7819 0.1585 72.33)` (light), `oklch(0.8203 0.1388 76.34)` (dark)
**Danger:**
* **Before:** `oklch(0.6259 0.1908 29.19)`
* **After:** `oklch(0.6532 0.2328 25.74)` (light), `oklch(0.594 0.1967 24.63)` (dark)
### Component API Changes
#### Chip Component
The Chip component's `type` prop has been renamed to `color`, and a new `size` prop has been added. A new `soft` variant has been introduced.
**Before:**
```tsx
import { Chip } from "@heroui/react";
Label
```
**After:**
```tsx
import { Chip } from "@heroui/react";
Label
```
**Migration:**
* Replace `type` prop with `color` prop
* Use `size` prop (`sm`, `md`, `lg`) to control chip size
* The `soft` variant provides a subtle appearance for less prominent chips
#### Link Component
The Link component now supports `underline` and `underlineOffset` props, and includes `asChild` support.
**Before:**
```tsx
import { Link } from "@heroui/react";
Link text
```
**After:**
```tsx
import { Link } from "@heroui/react";
Link text
```
**New Props:**
* `underline`: `"none" | "hover" | "always"` - Controls underline visibility
* `underlineOffset`: `number` - Controls underline offset from text
#### Type Reference Syntax
Due to the dual pattern implementation, type references through the namespace syntax are no longer supported. Use object-style syntax or named type imports instead.
**Before (no longer works):**
```tsx
type AvatarProps = Avatar.RootProps
```
**After (Option 1 - Object-style syntax):**
```tsx
type AvatarProps = Avatar["RootProps"]
```
**After (Option 2 - Named type imports, recommended):**
```tsx
import type { AvatarRootProps } from "@heroui/react"
type AvatarProps = AvatarRootProps
```
This change affects all compound components when accessing prop types.
#### Tabs Component Renaming
The Tabs component's wrapper element has been renamed for consistency:
* **Compound property**: `Tabs.ListWrapper` → `Tabs.ListContainer`
* **Named export**: `TabListWrapper` → `TabListContainer`
* **CSS class**: `.tabs__list-wrapper` → `.tabs__list-container`
* **Data attribute**: `data-slot="tabs-list-wrapper"` → `data-slot="tabs-list-container"`
**Migration:**
Find and replace all instances of `TabListWrapper` with `TabListContainer`:
```bash
# Component usage
TabListWrapper → TabListContainer
Tabs.ListWrapper → Tabs.ListContainer
# CSS selectors (if using custom styles)
.tabs__list-wrapper → .tabs__list-container
[data-slot="tabs-list-wrapper"] → [data-slot="tabs-list-container"]
```
#### Removed Variables
The following variables have been removed:
* `--panel` → Use `--surface` or `--overlay`
* `--panel-foreground` → Use `--surface-foreground` or `--overlay-foreground`
* `--surface-1`, `--surface-2`, `--surface-3` → Use background shades or surface levels
* `--accent-soft` → Use `--color-accent-soft` (now calculated)
* `--radius-panel` and `--radius-panel-inner` → Use standard radius values
## Design System Updates
### New Color System
#### Surface vs Overlay Concept
The design system now distinguishes between two types of elevated components:
* **Surface**: Used for non-overlay components like cards, accordions, and disclosure groups that sit on the page
* **Overlay**: Used for floating components like tooltips, popovers, modals, and menus that appear above the page
This distinction provides:
* Better visual hierarchy
* Appropriate shadow depths
* Improved dark mode contrast
* Clearer component semantics
#### Auto-Calculated Color System
HeroUI now automatically calculates shade levels and soft color variants using CSS `color-mix`. You only need to declare the base colors, and HeroUI handles the rest.
**Background Shade Levels**
Background shades are automatically calculated from `--background`:
```css
/* You only declare the base */
--background: oklch(0.9702 0 0);
--foreground: var(--eclipse);
/* HeroUI automatically calculates these */
--color-background-secondary: color-mix(in oklab, var(--color-background) 96%, var(--color-foreground) 4%);
--color-background-tertiary: color-mix(in oklab, var(--color-background) 92%, var(--color-foreground) 8%);
--color-background-quaternary: color-mix(in oklab, var(--color-background) 86%, var(--color-foreground) 14%);
```
**Surface Levels**
Surface levels are automatically calculated from `--surface`:
```css
/* You only declare the base */
--surface: var(--white);
--surface-foreground: var(--foreground);
/* HeroUI automatically calculates these */
--color-surface-secondary: color-mix(in oklab, var(--surface) 94%, var(--surface-foreground) 6%);
--color-surface-tertiary: color-mix(in oklab, var(--surface) 92%, var(--surface-foreground) 8%);
--color-surface-quaternary: color-mix(in oklab, var(--surface) 86%, var(--surface-foreground) 14%);
```
**Soft Color Variants**
Soft color variants are automatically calculated from status colors:
```css
/* You declare the base status colors */
--accent: oklch(0.6204 0.195 253.83);
--danger: oklch(0.6532 0.2328 25.74);
--warning: oklch(0.7819 0.1585 72.33);
--success: oklch(0.7329 0.1935 150.81);
/* HeroUI automatically calculates these at 15% opacity */
--color-accent-soft: color-mix(in oklab, var(--color-accent) 15%, transparent);
--color-danger-soft: color-mix(in oklab, var(--color-danger) 15%, transparent);
--color-warning-soft: color-mix(in oklab, var(--color-warning) 15%, transparent);
--color-success-soft: color-mix(in oklab, var(--color-success) 15%, transparent);
```
Each soft variant includes hover states (20% opacity) and foreground colors for proper contrast.
**Customization:**
You can override any auto-calculated values using Tailwind's `@theme` directive:
```css
@theme inline {
/* Adjust surface levels */
--color-surface-secondary: color-mix(in oklab, var(--surface) 96%, var(--surface-foreground) 4%);
/* Adjust soft colors */
--color-accent-soft: color-mix(in oklab, var(--color-accent) 20%, transparent);
}
```
This auto-calculation system reduces the number of variables you need to manage while providing full customization when needed.
### Shadow System
The shadow system has been redesigned to provide:
* Separate shadows for surfaces and overlays
* Better depth perception
* Dark mode support (transparent shadows)
* Consistent field shadows
Shadows automatically adapt to light and dark modes, providing appropriate depth cues for each theme.
### Focus System
The focus color now uses the accent color for consistency:
```css
--focus: var(--accent);
```
This ensures focus indicators align with your brand colors while maintaining accessibility.
### Typography Tokens
Several typography-related variables have been removed in favor of using Tailwind's typography utilities directly. The design system now focuses on color and spacing tokens, letting Tailwind handle typography.
## Migration Guide
### Step 1: Update Design System Variables
Replace old panel variables with surface/overlay:
```css
/* Before */
.my-card {
background: var(--panel);
box-shadow: var(--shadow-panel);
}
/* After */
.my-card {
background: var(--surface);
box-shadow: var(--shadow-surface);
}
.my-tooltip {
background: var(--overlay);
box-shadow: var(--shadow-overlay);
}
```
### Step 2: Update Surface Levels
Surface levels are now automatically calculated from `--surface`, so you don't need to manually declare them. Simply use the new utility classes:
```css
/* Before */
.bg-surface-1 → .bg-surface (base surface)
.bg-surface-2 → .bg-surface-secondary (auto-calculated)
.bg-surface-3 → .bg-surface-tertiary (auto-calculated)
/* You can also use background shades */
.bg-surface-2 → .bg-background-secondary (auto-calculated from --background)
.bg-surface-3 → .bg-background-tertiary (auto-calculated from --background)
```
**Note:** Surface levels (`surface-secondary`, `surface-tertiary`, etc.) are automatically calculated based on your `--surface` color. No manual CSS variables needed unless you want to customize the calculations.
### Step 3: Update Component Props
Update Chip and Link components:
```tsx
// Chip: type → color, add size if needed
→
// Link: Add underline props if customizing underlines
Text // Still works, underline props are optional
```
### Step 4: Simplify Component Patterns (Optional)
If you adopted the `.Root` suffix from v3.0.0-alpha.35, you can now simplify your code by removing it:
**Before (v3.0.0-alpha.35):**
```tsx
JD
```
**After (simpler):**
```tsx
JD
```
**Note:** The `.Root` syntax still works if you prefer it.
### Step 5: Update Type References
If you're using namespace syntax for types, switch to object-style syntax or named imports:
**Before:**
```tsx
type ButtonProps = Button.RootProps
```
**After (Option 1 - Object-style):**
```tsx
type ButtonProps = Button["RootProps"]
```
**After (Option 2 - Named imports, recommended):**
```tsx
import type { ButtonRootProps } from "@heroui/react"
type ButtonProps = ButtonRootProps
```
### Step 6: Update Tabs Component
Replace `TabListWrapper` with `TabListContainer`:
**Before:**
```tsx
import { Tabs } from "@heroui/react"
HomeContent
```
**After:**
```tsx
import { Tabs } from "@heroui/react"
HomeContent
```
### Step 7: Handle Border Changes
If your custom styles rely on default borders:
```css
/* Add explicit borders where needed */
.my-component {
border-width: 1px;
border-color: var(--color-border);
}
```
### Step 8: Update Status Colors
If you've customized status colors, review the new values and adjust your custom theme if needed:
```css
/* Check if your custom status colors need updates */
--success: oklch(0.7329 0.1935 150.81); /* New value */
--warning: oklch(0.7819 0.1585 72.33); /* New value */
--danger: oklch(0.6532 0.2328 25.74); /* New value */
```
### Automated Migration
For large codebases, you can use find-and-replace:
```bash
# Panel → Surface
--panel → --surface
bg-panel → bg-surface
shadow-panel → shadow-surface
# Panel → Overlay (for floating components)
--panel → --overlay (where appropriate)
bg-panel → bg-overlay (for tooltips, popovers, etc.)
shadow-panel → shadow-overlay (for floating components)
# Chip type prop
type=" → color="
# Surface levels
bg-surface-1 → bg-surface
bg-surface-2 → bg-surface-secondary
bg-surface-3 → bg-surface-tertiary
# Tabs component
TabListWrapper → TabListContainer
Tabs.ListWrapper → Tabs.ListContainer
# Type references
Component.RootProps → Component["RootProps"] or use named imports
```
## Component Updates
### Card Component
Card component has been refined with improved variants and better semantic structure. The component now uses the new surface system for consistent styling.
### Accordion Component
Accordion now uses the surface system for better visual consistency with other components.
### Form Components
Form components (Input, TextField, TextArea) have been updated to use the new field border system (transparent by default) for a cleaner look while maintaining accessibility.
### Component Pattern Updates
All components now support flexible patterns. Components that support the dual pattern include:
* **Simple components**: Button, Link, Spinner, Chip, Kbd
* **Compound components**: Accordion, Avatar, Card, Disclosure, Fieldset, Popover, RadioGroup, Switch, Tabs, Tooltip
You can use any of the three patterns (compound without `.Root`, compound with `.Root`, or named exports) with all these components.
## HeroUI Pro
HeroUI Pro is being reshaped from the ground up on top of the new design system. The new Pro version will feature:
* New components built on top of HeroUI v3
* Tailwind CSS v4 native support
* CSS native animations
* Enhanced customization options
We'll share more updates soon.
## Roadmap
We're working towards a stable release in **Q4** this year (2025). This beta release brings us significantly closer to that goal with:
* Comprehensive component set
* Refined design system
* Improved developer experience
* Better performance
## Community
The reception on the native side has been phenomenal. Thank you for supporting us as we build HeroUI v3! Your feedback helps us improve every day.
See what the community is saying: [HeroUI Native Reception](https://x.com/hero_ui/status/1985721976220966926)
## Links
* [Component Documentation](/docs/react/components)
* [Design System - Figma Kit V3](https://www.figma.com/community/file/1546526812159103429/heroui-figma-kit-v3)
* [HeroUI Native](https://link.heroui.com/native)
* [GitHub Repository](https://github.com/heroui-inc/heroui)
* [GitHub PR #5872](https://github.com/heroui-inc/heroui/pull/5872)
## Contributors
Thanks to everyone who contributed to this release, helping us create a design system that's both beautiful and practical!
# v3.0.0-beta.2
**Category**: react
**URL**: https://v3.heroui.com/docs/react/releases/v3-0-0-beta-2
**Source**: https://raw.githubusercontent.com/heroui-inc/heroui/refs/heads/v3/apps/docs/content/docs/react/releases/v3-0-0-beta-2.mdx
> Six new components (AlertDialog, ComboBox, Dropdown, InputGroup, Modal, NumberField), Select API improvements, and component refinements.
November 20, 2025
This release introduces six essential new components, improves the Select component API, and includes various refinements and bug fixes.
## Installation
Update to the latest version:
```bash
npm i @heroui/styles@beta @heroui/react@beta
```
```bash
pnpm add @heroui/styles@beta @heroui/react@beta
```
```bash
yarn add @heroui/styles@beta @heroui/react@beta
```
```bash
bun add @heroui/styles@beta @heroui/react@beta
```
**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](/docs/ui-for-agents/mcp-server).
## What's New
### New Components
This release introduces **6 new** essential components:
* **[AlertDialog](#alert-dialog)**: Modal dialog for important decisions that require user confirmation. ([Documentation](/docs/components/alert-dialog))
* **[ComboBox](#combo-box)**: Combines a text input with a listbox, allowing users to filter a list of options. ([Documentation](/docs/components/combo-box))
* **[Dropdown](#dropdown)**: Displays a list of actions or options that a user can choose. ([Documentation](/docs/components/dropdown))
* **[InputGroup](#inputgroup)**: Group related input controls with prefix and suffix elements for enhanced form fields. ([Documentation](/docs/components/input-group))
* **[Modal](#modal)**: Dialog overlay for focused user interactions and important content. ([Documentation](/docs/components/modal))
* **[NumberField](#numberfield)**: Number input with increment/decrement buttons, validation, and internationalized formatting. ([Documentation](/docs/components/number-field))
### AlertDialog
```tsx
"use client";
import {AlertDialog, Button} from "@heroui/react";
export function Default() {
return (
Delete project permanently?
This will permanently delete My Awesome Project and all of its
data. This action cannot be undone.
);
}
```
### ComboBox
```tsx
"use client";
import {ComboBox, Input, Label, ListBox} from "@heroui/react";
export function Default() {
return (
Aardvark
Cat
Dog
Kangaroo
Panda
Snake
);
}
```
### Dropdown
```tsx
"use client";
import {Button, Dropdown, Label} from "@heroui/react";
export function Default() {
return (
console.log(`Selected: ${key}`)}>
);
}
```
### Modal
```tsx
"use client";
import {Rocket} from "@gravity-ui/icons";
import {Button, Modal} from "@heroui/react";
export function Default() {
return (
Welcome to HeroUI
A beautiful, fast, and modern React UI library for building accessible and
customizable web applications with ease.
);
}
```
### InputGroup
```tsx
"use client";
import {Globe} from "@gravity-ui/icons";
import {InputGroup, Label, TextField} from "@heroui/react";
export function WithIconPrefixAndTextSuffix() {
return (
.com
);
}
```
### NumberField
```tsx
import {Label, NumberField} from "@heroui/react";
export function Basic() {
return (
);
}
```
### Style Improvements
#### Custom Variants and Theme Compatibility
Enhanced CSS variants and theme system for better customization:
**Motion Preferences**:
* New `motion-safe` variant with `data-reduce-motion="true"` attribute matching
* Enhanced `motion-reduce` now supports ancestor elements and pseudo-elements
**Dark Mode**:
* Class and `data-theme="dark"` attribute selectors now take precedence over `prefers-color-scheme`
* Full support for pseudo-elements in dark mode
**Theme Variables**:
* Expanded light theme scope to support nested themes (`:root`, `.light`, `.default`, `[data-theme="light"]`, `[data-theme="default"]`)
### Component Improvements
#### Select Component API Update
The Select component's API has been improved for better consistency with other components. The `Content` subcomponent has been renamed to `Popover`.
**Before:**
```tsx
```
**After:**
```tsx
```
#### Chip Component Refinements
Chip component sizes have been updated for better consistency:
* **Small (`sm`)**: `px-1 py-0 text-xs`
* **Medium (`md`)**: `text-xs` (now explicitly set)
* **Large (`lg`)**: `px-3 py-1 text-sm font-medium`
#### Separator Component Enhancement
The Separator component now automatically detects when it's placed inside a surface component (one that uses `bg-surface`) and applies the appropriate divider color for better visibility. A new `isOnSurface` prop is also available for manual control.
**New Calculated Variable:**
* `--color-separator-on-surface`: A calculated variable (automatically generated using `color-mix`) that ensures the separator is visible when placed on a surface background. Like other calculated variables, it can be overridden in your theme.
**Usage:**
```tsx
```
The `isOnSurface` prop is automatically applied when the Separator detects a `SurfaceContext` provider (used by components like Card, Alert, Popover, Modal, etc.).
You can also use the calculated variable directly with Tailwind classes:
```tsx
```
#### Animation Improvements
* Loading state spinner color updated for better visibility
* Select and Slider component styles adjusted for improved animations
* Checkbox animation improved (faster transition)
* Better support for `prefers-reduced-motion` with pseudo elements
## ⚠️ Breaking Changes
### Select Component
The `Select.Content` subcomponent has been renamed to `Select.Popover` for consistency with other components like ComboBox and Dropdown.
**Migration:**
Replace all instances of `Select.Content` with `Select.Popover`:
```tsx
// Before
...
// After
...
```
**Type imports:**
```tsx
// Before
import type { SelectContentProps } from "@heroui/react"
// After
import type { SelectPopoverProps } from "@heroui/react"
```
**Named exports:**
```tsx
// Before
import { SelectContent } from "@heroui/react"
// After
import { SelectPopover } from "@heroui/react"
```
### CSS Variables and Utilities: Divider → Separator
All CSS variables and utility classes related to `divider` have been renamed to `separator` for consistency with the Separator component name.
**CSS Variables:**
```css
/* Before */
border-bottom: 1px solid var(--divider);
/* After */
border-bottom: 1px solid var(--separator);
```
**Tailwind Utility Classes:**
```tsx
// Before
// After
```
**Theme Overrides:**
If you have custom themes that override the divider variable, update them:
```css
/* Before */
:root {
--divider: oklch(92% 0.004 286.32);
}
.dark {
--divider: oklch(22% 0.006 286.033);
}
/* After */
:root {
--separator: oklch(92% 0.004 286.32);
}
.dark {
--separator: oklch(22% 0.006 286.033);
}
```
## Bug Fixes
* Fixed loading state spinner color for better visibility
* Fixed bordered focus styles taking precedence over hover states
* Fixed animation stuttering in documentation
* Improved modal form styling
* Enhanced motion reduce support for pseudo elements
* Fixed mobile hover states sticking after touch interactions by wrapping hover styles in `@media (hover: hover)` media queries. Also simplified data attribute selectors by removing unnecessary `="true"` value checks.
## Links
* [Component Documentation](/docs/react/components)
* [Design System - Figma Kit V3 (updated)](https://www.figma.com/community/file/1546526812159103429/heroui-figma-kit-v3)
* [GitHub Repository](https://github.com/heroui-inc/heroui)
* [GitHub PR #5885](https://github.com/heroui-inc/heroui/pull/5885)
## Contributors
Thanks to everyone who contributed to this release!
# v3.0.0-beta.3
**Category**: react
**URL**: https://v3.heroui.com/docs/react/releases/v3-0-0-beta-3
**Source**: https://raw.githubusercontent.com/heroui-inc/heroui/refs/heads/v3/apps/docs/content/docs/react/releases/v3-0-0-beta-3.mdx
> Seven new components, fullWidth and hideSeparator support, style fixes, and breaking changes for AlertDialog/Modal backdrop variants and asChild prop removal.
December 19, 2025
This release introduces seven new components ([ButtonGroup](/docs/components/button-group), [DateField](/docs/components/date-field), [ErrorMessage](/docs/components/error-message), [ScrollShadow](/docs/components/scroll-shadow), [SearchField](/docs/components/search-field), [TagGroup](/docs/components/tag-group), [TimeField](/docs/components/time-field)), adds `fullWidth` support for form components and `hideSeparator` to [Tabs](/docs/components/tabs), [ButtonGroup](/docs/components/button-group), and [Accordion](/docs/components/accordion), includes style fixes, and ⚠️ **breaking changes** removing the `asChild` prop and updating [AlertDialog](/docs/components/alert-dialog) & [Modal](/docs/components/modal) backdrop variants.
## Installation
Update to the latest version:
```bash
npm i @heroui/styles@beta @heroui/react@beta
```
```bash
pnpm add @heroui/styles@beta @heroui/react@beta
```
```bash
yarn add @heroui/styles@beta @heroui/react@beta
```
```bash
bun add @heroui/styles@beta @heroui/react@beta
```
**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](/docs/ui-for-agents/mcp-server).
## What's New
### New Components
This release introduces **7 new** essential components:
* **[ButtonGroup](#button-group)**: Groups related buttons with consistent styling and spacing. ([Documentation](/docs/components/button-group))
* **[DateField](#date-field)**: Date input field with labels, descriptions, and validation built on React Aria DateField. ([Documentation](/docs/components/date-field))
* **[ErrorMessage](#error-message)**: Low-level error message component for displaying errors in non-form components. ([Documentation](/docs/components/error-message))
* **[ScrollShadow](#scroll-shadow)**: Apply visual shadows to indicate scrollable content overflow with automatic detection of scroll position. ([Documentation](/docs/components/scroll-shadow))
* **[SearchField](#search-field)**: Search input field with built-in search icon and clear button. ([Documentation](/docs/components/search-field))
* **[TagGroup](#tag-group)**: Focusable list of tags with support for keyboard navigation, selection, and removal. ([Documentation](/docs/components/tag-group))
* **[TimeField](#time-field)**: Time input field with labels, descriptions, and validation built on React Aria TimeField. ([Documentation](/docs/components/time-field))
### ButtonGroup
```tsx
import {
ChevronDown,
ChevronLeft,
ChevronRight,
CodeFork,
Ellipsis,
Picture,
Pin,
QrCode,
Star,
TextAlignCenter,
TextAlignJustify,
TextAlignLeft,
TextAlignRight,
ThumbsDown,
ThumbsUp,
Video,
} from "@gravity-ui/icons";
import {Button, ButtonGroup, Chip, Description, Dropdown, Label} from "@heroui/react";
export function Basic() {
return (
{/* Single button with dropdown */}
All commits from this branch will be added to the base branch
The 14 commits from this branch will be combined into one commit in the base
branch
The 14 commits from this branch will be rebased and added to the base branch
{/* Individual buttons */}
{/* Previous/Next Button Group */}
{/* Content Selection Button Group */}
{/* Text Alignment Button Group */}
{/* Icon-Only Alignment Button Group */}
);
}
```
### DateField
```tsx
"use client";
import {DateField, Label} from "@heroui/react";
export function Basic() {
return (
{(segment) => }
);
}
```
### ErrorMessage
```tsx
"use client";
import type {Key} from "@heroui/react";
import {Description, ErrorMessage, Label, Tag, TagGroup} from "@heroui/react";
import {useMemo, useState} from "react";
export function ErrorMessageBasic() {
const [selected, setSelected] = useState>(new Set());
const isInvalid = useMemo(() => Array.from(selected).length === 0, [selected]);
return (
setSelected(keys)}
>
NewsTravelGamingShoppingSelect at least one category{!!isInvalid && <>Please select at least one category>}
);
}
```
### SearchField
```tsx
import {Label, SearchField} from "@heroui/react";
export function Basic() {
return (
);
}
```
### ScrollShadow
```tsx
import {Card, ScrollShadow} from "@heroui/react";
const images = [
"https://heroui-assets.nyc3.cdn.digitaloceanspaces.com/docs/robot1.jpeg",
"https://heroui-assets.nyc3.cdn.digitaloceanspaces.com/docs/avocado.jpeg",
"https://heroui-assets.nyc3.cdn.digitaloceanspaces.com/docs/oranges.jpeg",
];
export default function Orientation() {
const getRandomImage = (idx: number) => {
return images[idx % images.length];
};
return (
Vertical
{Array.from({length: 10}).map((_, idx) => (
Lorem ipsum dolor sit amet, consectetur adipiscing elit. Nullam pulvinar risus non
risus hendrerit venenatis. Pellentesque sit amet hendrerit risus, sed porttitor
quam. Morbi accumsan cursus enim, sed ultricies sapien.
))}
Horizontal
{Array.from({length: 10}).map((_, idx) => (
Bridging the FutureToday, 6:30 PM
))}
);
}
```
### TagGroup
```tsx
"use client";
import {PlanetEarth, Rocket, ShoppingBag, SquareArticle} from "@gravity-ui/icons";
import {Tag, TagGroup} from "@heroui/react";
export function TagGroupBasic() {
return (
News
Travel
Gaming
Shopping
);
}
```
### TimeField
```tsx
"use client";
import {Label, TimeField} from "@heroui/react";
export function Basic() {
return (
{(segment) => }
);
}
```
### Full-Width Support
Added `fullWidth` support to form and input components, allowing them to span the full width of their container. This is particularly useful for creating consistent form layouts and responsive designs.
**Supported components:**
* [ButtonGroup](/docs/components/button-group)
* [Button](/docs/components/button)
* [ComboBox](/docs/components/combo-box)
* [DateField](/docs/components/date-field)
* [DateInputGroup](/docs/components/date-input-group)
* [InputGroup](/docs/components/input-group)
* [Input](/docs/components/input)
* [NumberField](/docs/components/number-field)
* [SearchField](/docs/components/search-field)
* [Select](/docs/components/select)
* [TextField](/docs/components/text-field)
* [TextArea](/docs/components/textarea)
* [TimeField](/docs/components/time-field)
## Component Improvements
### Separator Control Enhancement
Added `hideSeparator` prop to [Tabs](/docs/components/tabs), [ButtonGroup](/docs/components/button-group), and [Accordion](/docs/components/accordion) components, allowing you to hide separator lines between items for a cleaner, more minimal appearance.
**Tabs:**
```tsx
OverviewAnalytics
```
**ButtonGroup:**
```tsx
```
**Accordion:**
```tsx
Item 1Content
```
### Documentation Icons Integration
Integrated [@gravity-ui/icons](https://github.com/gravity-ui/icons) into documentation components for consistent icon rendering with improved SSR support and better performance.
## Dependencies
### React Aria Components v1.14.0
Upgraded [react-aria-components](https://react-aria.adobe.com/releases/v1-14-0) to v1.14.0. This release includes:
**Enhancements:**
* SearchField: Added `isReadOnly` and `isRequired` to render props
* Tooltip: Added `shouldCloseOnPress` prop
* Tabs: Support for animated transitions between tab panels
* Miscellaneous: Support for `setState` callback in `useControlledState`
**Fixes:**
* ComboBox: Fixed VoiceOver announcement not respecting `aria-label` of ListBoxItem
* Date and Time: Enhanced error handling for absolute date and date time strings
* NumberField: Prevented incrementing/decrementing when scrolling on mobile
* Overlays: Fixed overlay positioning and flipping when boundary container is set
* Table: Fixed crash in drag and drop when keyboard navigating
* Various other bug fixes and improvements
For the complete list of changes, see the [React Aria Components v1.14.0 release notes](https://react-aria.adobe.com/releases/v1-14-0).
### Other Dependency Upgrades
* `@internationalized/date`: 3.10.0 → 3.10.1
* `@radix-ui/react-avatar`: 1.1.10 → 1.1.11
* `tailwind-merge`: 3.3.1 → 3.4.0
* `tailwind-variants`: 3.1.1 → 3.2.2
## Style Fixes
### Form Component Disabled State
Fixed disabled state styling for [Input](/docs/components/input) and [TextArea](/docs/components/textarea) components.
### Style Optimizations
* **Improved selector precision**: Enhanced CSS selector specificity for better style isolation and performance
* **Enhanced animations**: Improved animation performance and smoothness across components
* **Added no-highlight utility**: Added `no-highlight` utility class to prevent text selection on interactive elements for improved user experience
* **Optimized will-change properties**: Updated `will-change` CSS properties across components for better animation performance
* **Removed global scrollbar styling**: Removed global scrollbar styles to prevent conflicts with custom scrollbar implementations and fix modal/overlay interaction issues
## ⚠️ Breaking Changes
### AlertDialog & Modal Backdrop Variant
Renamed `backdropVariant`/`variant` prop value from `"solid"` to `"opaque"` for better semantic clarity. The term "opaque" more accurately describes the backdrop's visual appearance.
**Migration:**
Update all instances of `backdropVariant="solid"` to `backdropVariant="opaque"` for AlertDialog, and `variant="solid"` to `variant="opaque"` for Modal:
```tsx
// Before
{/* content */}
{/* content */}
// After
{/* content */}
{/* content */}
```
**Available backdrop variants:**
* `"opaque"` - Dark backdrop that completely obscures the background (formerly `"solid"`)
* `"blur"` - Blurred backdrop that softly obscures the background
* `"transparent"` - Transparent backdrop that keeps the background visible
### Removed `asChild` Prop
Removed the `asChild` prop pattern from components for cleaner APIs, improved type safety, and simplified usage.
For more details about component composition patterns, see the [Composition guide](/docs/handbook/composition).
## Bug Fixes
* Fixed `isInvalid` styles when components are used on surface backgrounds
* Fixed AlertDialog and Modal re-rendering issues after close
* Fixed overlay close issue that prevented proper cleanup when closing overlays
* Fixed Storybook links and navigation issues
## Links
* [Component Documentation](/docs/react/components)
* [Design System - Figma Kit V3 (updated)](https://www.figma.com/community/file/1546526812159103429/heroui-figma-kit-v3)
* [GitHub Repository](https://github.com/heroui-inc/heroui)
* [GitHub PR #5923](https://github.com/heroui-inc/heroui/pull/5923)
## Contributors
Thanks to everyone who contributed to this release!
# v3.0.0-beta.4
**Category**: react
**URL**: https://v3.heroui.com/docs/react/releases/v3-0-0-beta-4
**Source**: https://raw.githubusercontent.com/heroui-inc/heroui/refs/heads/v3/apps/docs/content/docs/react/releases/v3-0-0-beta-4.mdx
> New Theme Builder, three new components (Autocomplete, Breadcrumbs, Toast), Tabs secondary variant, Input/InputGroup variants, and various improvements.
January 20, 2026
**Critical Build Issue Fixed**: This version (beta.4) had a critical build issue that has been fixed in **beta.5**. Please upgrade to `@heroui/styles@3.0.0-beta.5` and `@heroui/react@3.0.0-beta.5` to ensure proper TypeScript declaration generation and export resolution.
This release introduces the new [Theme Builder](/themes) for visual theme customization, three new components ([Autocomplete](/docs/components/autocomplete), [Breadcrumbs](/docs/components/breadcrumbs), [Toast](/docs/components/toast)), adds secondary variant to [Tabs](/docs/components/tabs), primary/secondary variants to [Input](/docs/components/input) and [InputGroup](/docs/components/input-group), TextArea support for InputGroup, and ⚠️ **breaking changes** removing Link's underline variants and the `isInSurface` prop from form components.
## Installation
Update to the latest version:
```bash
npm i @heroui/styles@beta @heroui/react@beta
```
```bash
pnpm add @heroui/styles@beta @heroui/react@beta
```
```bash
yarn add @heroui/styles@beta @heroui/react@beta
```
```bash
bun add @heroui/styles@beta @heroui/react@beta
```
**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](/docs/ui-for-agents/mcp-server).
## What's New
### Theme Builder
We're excited to introduce the **[Theme Builder](/themes)** - a powerful visual tool for creating and customizing HeroUI themes. Build your perfect theme with real-time preview and export ready-to-use CSS.
**Key features:**
* **Visual Color Editing**: Adjust colors using OKLCH color pickers with intuitive sliders for lightness, chroma, and hue
* **Real-time Preview**: See your changes instantly on live component previews
* **Custom Accent Colors**: Define your brand colors and watch them propagate across all components
* **Preset Themes**: Start from curated presets like Default, Airbnb, Coinbase, Discord, and more
* **Export Ready**: Generate CSS variables ready to copy into your project
* **Light & Dark Mode**: Customize both themes simultaneously with linked or independent values
* **Keyboard Shortcuts**: Undo/redo support and quick actions for efficient workflow
Try it now at [v3.heroui.com/themes](/themes).
### New Components
This release introduces **3 new** essential components:
* **[Autocomplete](#autocomplete)**: Combines a select with filtering, allowing users to search and select from a list of options. ([Documentation](/docs/components/autocomplete))
* **[Breadcrumbs](#breadcrumbs)**: Navigation breadcrumbs showing the current page's location within a hierarchy. ([Documentation](/docs/components/breadcrumbs))
* **[Toast](#toast)**: Display temporary notifications and messages with automatic dismissal and customizable placement. ([Documentation](/docs/components/toast))
### Autocomplete
```tsx
"use client";
import type {Key} from "@heroui/react";
import {
Autocomplete,
EmptyState,
Label,
ListBox,
SearchField,
Tag,
TagGroup,
useFilter,
} from "@heroui/react";
import {useState} from "react";
export default function Default() {
const {contains} = useFilter({sensitivity: "base"});
const [selectedKeys, setSelectedKeys] = useState([]);
const items = [
{id: "florida", name: "Florida"},
{id: "delaware", name: "Delaware"},
{id: "california", name: "California"},
{id: "texas", name: "Texas"},
{id: "new-york", name: "New York"},
{id: "washington", name: "Washington"},
];
const onRemoveTags = (keys: Set) => {
setSelectedKeys((prev) => prev.filter((key) => !keys.has(key)));
};
return (
setSelectedKeys(keys as Key[])}
>
{({defaultChildren, isPlaceholder, state}: any) => {
if (isPlaceholder || state.selectedItems.length === 0) {
return defaultChildren;
}
const selectedItemsKeys = state.selectedItems.map((item: any) => item.key);
return (
{selectedItemsKeys.map((selectedItemKey: Key) => {
const item = items.find((s) => s.id === selectedItemKey);
if (!item) return null;
return (
{item.name}
);
})}
);
}}
No results found}>
{items.map((item) => (
{item.name}
))}
);
}
```
### Breadcrumbs
```tsx
"use client";
import {Breadcrumbs} from "@heroui/react";
export default function BreadcrumbsBasic() {
return (
HomeProductsElectronicsLaptop
);
}
```
### Toast
This component is currently in preview and some features might not work as expected.
```tsx
"use client";
import {HardDrive, Persons} from "@gravity-ui/icons";
import {Button, toast} from "@heroui/react";
const noop = () => {};
export function Variants() {
return (
);
}
```
## Component Improvements
### Tabs Secondary Variant
Added a new `secondary` variant to [Tabs](/docs/components/tabs) with an underline indicator style. The secondary variant supports both horizontal and vertical orientations.
```tsx
import {Tabs} from "@heroui/react";
export function Secondary() {
return (
Overview
Analytics
Reports
View your project overview and recent activity.
Track your metrics and analyze performance data.
Generate and download detailed reports.
);
}
```
**Usage:**
```tsx
Overview
Analytics
ContentContent
```
### Input Variants
Added `primary` and `secondary` variants to the [Input](/docs/components/input) component:
* **`primary`** (default): Standard styling with shadow, suitable for most use cases
* **`secondary`**: Lower emphasis variant without shadow, suitable for use in Surface components
```tsx
import {Input} from "@heroui/react";
export function Variants() {
return (
);
}
```
### InputGroup Enhancements
The [InputGroup](/docs/components/input-group) component received several improvements:
**TextArea Support**: Use `InputGroup.TextArea` for multiline text inputs with prefix and suffix elements.
```tsx
"use client";
import {ArrowUp, At, Microphone, PlugConnection, Plus} from "@gravity-ui/icons";
import {Button, InputGroup, Kbd, Spinner, TextField, Tooltip} from "@heroui/react";
import {useState} from "react";
export function WithTextArea() {
const [value, setValue] = useState("");
const [isSubmitting, setIsSubmitting] = useState(false);
const handleSubmit = () => {
if (!value.trim()) return;
setIsSubmitting(true);
setTimeout(() => {
setIsSubmitting(false);
setValue("");
}, 1000);
};
return (
setValue(event.target.value)}
/>
Add a files and more
Connect apps
Voice input
Send
);
}
```
**Variants**: Added `primary` and `secondary` variants matching the Input component.
```tsx
import {Envelope} from "@gravity-ui/icons";
import {InputGroup, Label, TextField} from "@heroui/react";
export function Variants() {
return (
);
}
```
### Button & ButtonGroup Outline Variants
Added a new `outline` variant to both [Button](/docs/components/button) and [ButtonGroup](/docs/components/button-group) components for outlined styling.
```tsx
import {Button, ButtonGroup} from "@heroui/react";
export function OutlineVariant() {
return (
Button
ButtonGroup
);
}
```
### AlertDialog Size Support
Added size support to [AlertDialog](/docs/components/alert-dialog) component, allowing you to control the dialog size.
```tsx
"use client";
import {Rocket} from "@gravity-ui/icons";
import {AlertDialog, Button} from "@heroui/react";
export function Sizes() {
const sizes = ["xs", "sm", "md", "lg", "cover"] as const;
return (
{size === "cover" ? (
<>
This alert dialog uses the cover size variant. It spans the
full screen with margins: 16px on mobile and 40px on desktop. Maintains
rounded corners and standard padding. Perfect for critical confirmations
that need maximum width while preserving alert dialog aesthetics.
>
) : (
<>
This alert dialog uses the {size} size variant. On mobile
devices, all sizes adapt to near full-width for optimal viewing. On desktop,
each size provides a different maximum width to suit various content needs.
>
)}
))}
);
}
```
### Checkbox Animation Improvements
Faster animation and increased stroke width for better feedback on [Checkbox](/docs/components/checkbox).
```tsx
import {Checkbox, Label} from "@heroui/react";
export function Basic() {
return (
);
}
```
### Link Text Decoration
The [Link](/docs/components/link) component now uses Tailwind CSS classes for text decoration instead of built-in variants. This provides more flexibility and follows Tailwind conventions.
**Available Tailwind utilities:**
* `underline` - Always visible underline
* `no-underline` - Remove underline
* `hover:underline` - Underline appears on hover
* `decoration-primary`, `decoration-secondary`, etc. - Set underline color
* `decoration-1`, `decoration-2`, `decoration-4` - Control thickness
* `underline-offset-1`, `underline-offset-2`, etc. - Adjust spacing
```tsx
import {Link} from "@heroui/react";
export function LinkUnderlineAndOffset() {
return (
);
}
```
## ⚠️ Breaking Changes
### Link Component - Removed Underline Variants
The Link component's built-in `underline` and `underlineOffset` props have been removed. Use Tailwind CSS classes instead for text decoration.
**Before:**
```tsx
Link text
```
**After:**
```tsx
Link text
```
**Available Tailwind classes:**
* `underline`, `no-underline`, `hover:underline` - Decoration line
* `decoration-primary`, `decoration-muted`, etc. - Decoration color
* `decoration-solid`, `decoration-dashed`, `decoration-dotted` - Decoration style
* `decoration-1`, `decoration-2`, `decoration-4` - Decoration thickness
* `underline-offset-1`, `underline-offset-2`, `underline-offset-4` - Underline offset
For more details, see the [Link documentation](/docs/components/link).
### Form Components - Removed `isInSurface` Prop
The `isInSurface` prop and automatic surface detection have been removed from form-based components. Instead, use the `variant="secondary"` prop when placing form components inside Surface, Card, or other surface-based containers.
**Before:**
```tsx
{/* Input automatically detected surface context */}
```
**After:**
```tsx
{/* Use variant="secondary" for surface backgrounds */}
```
**Affected components:**
* Input
* InputGroup
* TextField
* TextArea
* SearchField
* NumberField
* DateField
* TimeField
* Select
* ComboBox
* Autocomplete
The `secondary` variant provides lower emphasis styling without shadow, which is appropriate for use on surface backgrounds.
## Style Fixes
* **Button**: Updated secondary button colors for improved visual consistency
* **Checkbox**: Optimized animation speed and increased stroke width for better feedback (see [Checkbox Animation Improvements](#checkbox-animation-improvements))
* **Link**: Updated decoration styles and transition timings
* **Focus Visible**: Added `:not(:focus)` to focus-visible selectors to prevent conflicts with hover states
* **Separator**: Fixed styles to only apply to horizontal separator
## Bug Fixes
* Fixed Link with Button variants styling
* Fixed Fieldset flexbox quirk in Safari with BEM styles
* Fixed SearchField empty state to properly disable clear button
* Fixed ButtonGroup context to only apply to direct children
* Fixed ButtonGroup `BUTTON_GROUP_CHILD` re-export for type declarations
## Dependencies
### Direct Exports from React Aria Components
HeroUI now provides direct exports from react-aria-components for easier access to primitives and utilities. These exports are particularly useful for [React Aria Framework setup](https://react-aria.adobe.com/frameworks).
**Providers:**
* `RouterProvider` - Configure React Aria links to use your client-side router
* `I18nProvider` - Set the locale used by React Aria components
**Hooks and Utilities:**
* `isRTL` - Check if a locale is right-to-left
* `useLocale` - Access the current locale and direction
* `useFilter` - Filter and sort collections
**Components:**
* `Collection` - Collection component for managing lists
* `ListBoxLoadMoreItem` - ListBox item for loading more items
**i18n Utilities:**
* `getLocalizationScript` - Get localization script for server-side rendering (from `react-aria-components/i18n`)
All of these can be imported directly from `@heroui/react`:
```tsx
import {
RouterProvider,
I18nProvider,
isRTL,
useLocale,
useFilter,
getLocalizationScript
} from "@heroui/react";
```
## Links
* [Theme Builder](/themes)
* [Component Documentation](/docs/react/components)
* [Design System - Figma Kit V3 (updated)](https://www.figma.com/community/file/1546526812159103429/heroui-figma-kit-v3)
* [GitHub Repository](https://github.com/heroui-inc/heroui)
* [GitHub PR #6121](https://github.com/heroui-inc/heroui/pull/6121)
## Contributors
Thanks to everyone who contributed to this release!
# v3.0.0-beta.6
**Category**: react
**URL**: https://v3.heroui.com/docs/react/releases/v3-0-0-beta-6
**Source**: https://raw.githubusercontent.com/heroui-inc/heroui/refs/heads/v3/apps/docs/content/docs/react/releases/v3-0-0-beta-6.mdx
> 6 new color components (ColorPicker, ColorArea, ColorSlider, ColorField, ColorSwatch, ColorSwatchPicker), toast improvements, and various style fixes.
February 6, 2026
This release introduces a comprehensive **Color System** with six new components for color selection and manipulation: [ColorPicker](/docs/components/color-picker), [ColorArea](/docs/components/color-area), [ColorSlider](/docs/components/color-slider), [ColorField](/docs/components/color-field), [ColorSwatch](/docs/components/color-swatch), and [ColorSwatchPicker](/docs/components/color-swatch-picker). Also includes [Separator](/docs/components/separator) variants and various style improvements.
## Installation
Update to the latest version:
```bash
npm i @heroui/styles@beta @heroui/react@beta
```
```bash
pnpm add @heroui/styles@beta @heroui/react@beta
```
```bash
yarn add @heroui/styles@beta @heroui/react@beta
```
```bash
bun add @heroui/styles@beta @heroui/react@beta
```
**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](/docs/ui-for-agents/mcp-server).
## What's New
### Color System
We're excited to introduce a comprehensive **Color System** - a complete suite of components for color selection, manipulation, and display. These components are built on React Aria's color primitives and work together seamlessly.
**Key features:**
* **Full Color Space Support**: Work with HSL, HSB, and RGB color spaces
* **Channel-based Editing**: Manipulate individual color channels (hue, saturation, lightness, brightness, red, green, blue, alpha)
* **Accessible by Default**: Full keyboard navigation and screen reader support
* **Composable Design**: Mix and match components to build custom color pickers
### New Components
This release introduces **6 new** color components:
* **[ColorPicker](#colorpicker)**: Complete color picker with trigger, popover, and composable internals. ([Documentation](/docs/components/color-picker))
* **[ColorArea](#colorarea)**: 2D gradient area for selecting two color channels simultaneously. ([Documentation](/docs/components/color-area))
* **[ColorSlider](#colorslider)**: Single-channel slider for precise color adjustments. ([Documentation](/docs/components/color-slider))
* **[ColorField](#colorfield)**: Text input for entering and editing color values. ([Documentation](/docs/components/color-field))
* **[ColorSwatch](#colorswatch)**: Visual color preview with support for transparency. ([Documentation](/docs/components/color-swatch))
* **[ColorSwatchPicker](#colorswatchpicker)**: Grid of selectable color swatches for quick color selection. ([Documentation](/docs/components/color-swatch-picker))
### ColorPicker
The ColorPicker is a compound component that combines all color components into a complete color selection experience.
```tsx
import {ColorArea, ColorPicker, ColorSlider, ColorSwatch, Label} from "@heroui/react";
export function Basic() {
return (
);
}
```
### ColorArea
A 2D gradient area for selecting two color channels at once, typically saturation and brightness.
```tsx
import {ColorArea} from "@heroui/react";
export function ColorAreaBasic() {
return (
);
}
```
### ColorSlider
A slider for adjusting individual color channels like hue, saturation, lightness, or alpha.
```tsx
import {ColorSlider, Label} from "@heroui/react";
export function Basic() {
return (
);
}
```
**With different channels:**
```tsx
"use client";
import {ColorSlider, ColorSwatch, Label} from "@heroui/react";
import {useState} from "react";
import {parseColor} from "react-aria-components";
export function Channels() {
const [color, setColor] = useState(parseColor("hsl(0, 100%, 50%)"));
return (
Current color: {color.toString("hsl")}
);
}
```
### ColorField
A text input field for entering color values directly. Supports various color formats.
```tsx
"use client";
import type {Color} from "@heroui/react";
import {ColorField, ColorSwatch, Label, parseColor} from "@heroui/react";
import {useState} from "react";
export function Basic() {
const [color, setColor] = useState(parseColor("#0485F7"));
return (
);
}
```
### ColorSwatch
A visual display of a color value with support for transparency patterns.
```tsx
import {ColorSwatch} from "@heroui/react";
export function ColorSwatchBasic() {
return (
);
}
```
### ColorSwatchPicker
A grid of color swatches for quick color selection from a predefined palette.
```tsx
import {ColorSwatchPicker} from "@heroui/react";
const colors = ["#F43F5E", "#D946EF", "#8B5CF6", "#3B82F6", "#06B6D4", "#10B981", "#84CC16"];
export function Basic() {
return (
{colors.map((color) => (
))}
);
}
```
## Component Improvements
### Toast Enhancements
The [Toast](/docs/components/toast) component has been significantly improved with new features and better stability (#6151):
**New Features:**
* **Loading State**: Added `isLoading` prop to show a spinner instead of the default indicator
* **Default Timeout**: Toasts now auto-dismiss after 4 seconds by default (configurable via `timeout` prop)
* **Width Control**: Added `width` prop to `Toast.Provider` for customizable toast width
* **Adaptive Height**: Toasts now adapt their height based on content
* **Better Stacking**: Fixed layout shifts when toasts stack using absolute positioning and height synchronization
* **Improved Close Handling**: Deferred `onClose` callback to prevent toast transition deadlock
* **Front-most Close Button**: Close button only appears on the front-most toast for cleaner UI
* **Enhanced Promise Support**: Improved `toast.promise()` with better loading states and error handling
**New Demos:**
* Promise & Loading states
* Callbacks and timeout handling
```tsx
"use client";
import {HardDrive, Persons} from "@gravity-ui/icons";
import {Button, toast} from "@heroui/react";
const noop = () => {};
export function Variants() {
return (
);
}
```
### Separator Variants
Added variants to the [Separator](/docs/components/separator) component for different visual styles.
### Chip Component - Label Slot
The [Chip](/docs/components/chip) component now supports a `Chip.Label` subcomponent for better visual alignment. When removing start or end content (like icons), the label text was too close to the chip edges. Plain text children are automatically wrapped in `` for backward compatibility.
**Usage:**
```tsx
import { Chip } from '@heroui/react';
// Automatic wrapping (backward compatible)
Label text
// Explicit label with custom styling
Custom Label
// Mixing icons and labels
With Icon
```
## Style Fixes
* **Overlay Content**: Fixed blur effect on overlay content (#6136)
* **Invalid Field**: Converted ring to outline for invalid field states (#6184)
* **Link with Button**: Fixed styling for Link components using button variants (#6138)
* **Toast Content**: Fixed vertical alignment of toast content (#6147)
* **Safari SVG**: Fixed SVG shifting issue in Safari (#6149)
* **Placeholder Color**: Aligned placeholder color with input text (#6139)
* **Tooltip**: Removed cursor style from tooltip trigger component
* **CSS Variables**: Made calculated variables depend only on root variables (#6154)
## Bug Fixes
* Fixed page interactivity during view transitions (#6128)
* Fixed markdown URL formatting (#6162)
* Fixed incorrect link to combo box page (#6164)
* Fixed autocomplete styles import order in index.css
* Fixed hyphenated format for CSS classes (#6191)
## ⚠️ Breaking Changes
### Toast Component - Container Renamed to Provider
The `Toast.Container` component has been renamed to `Toast.Provider` for better semantic clarity (#6151).
**Before:**
```tsx
```
**After:**
```tsx
```
**Additional Changes:**
* Default `gap` prop changed from `14` to `12` pixels
* Default `timeout` is now `4000` (4 seconds) instead of requiring explicit timeout
* `Toast.Action` has been renamed to `Toast.ActionButton` for consistency
### CSS Class Naming Convention
CSS classes have been renamed to use hyphenated format for consistency (#6141). This follows BEM conventions more closely and improves compatibility with Tailwind CSS.
**Important Note**: The `textarea` class was initially renamed to `text-area` but was rolled back to `textarea` in PR #6191 due to conflicts with Tailwind's native `textarea` class. No changes are needed for TextArea component classes.
#### Component Class Name Changes
The following CSS class names have been updated. If you have custom CSS targeting these classes directly, update your selectors:
| Component | Old Class Name | New Class Name | Notes |
| ------------------ | -------------------------- | --------------------------- | ------------------------------------------------------ |
| **ComboBox** | `.combobox` | `.combo-box` | All related classes updated |
| | `.combobox__input-group` | `.combo-box__input-group` | |
| | `.combobox__trigger` | `.combo-box__trigger` | |
| | `.combobox__popover` | `.combo-box__popover` | |
| | `.combobox--full-width` | `.combo-box--full-width` | |
| **ListBox** | `.listbox` | `.list-box` | All related classes updated |
| **ListBoxItem** | `.listbox-item` | `.list-box-item` | All related classes updated |
| | `.listbox-item__indicator` | `.list-box-item__indicator` | |
| | `.listbox-item--default` | `.list-box-item--default` | |
| | `.listbox-item--danger` | `.list-box-item--danger` | |
| **ListBoxSection** | `.listbox-section` | `.list-box-section` | All related classes updated |
| **TextArea** | `.textarea` | `.textarea` | **No change** - Rolled back to avoid Tailwind conflict |
#### Migration Guide
**Before:**
```css
/* Custom styles targeting old class names */
.combobox {
/* styles */
}
.listbox-item {
/* styles */
}
```
**After:**
```css
/* Update to new hyphenated class names */
.combo-box {
/* styles */
}
.list-box-item {
/* styles */
}
```
**JavaScript/TypeScript Updates:**
If you're using these class names in JavaScript or TypeScript code:
```tsx
// Before
// After
```
**Note**: Component props and TypeScript types remain unchanged. Only CSS class names have been updated.
### Removed CSS Variables
Several CSS variables have been removed as part of the surface color refactoring (#6204). These variables were either replaced with direct variable references or removed entirely.
#### Surface Color Variables
The following calculated surface color variables have been removed and replaced with direct variable references:
**Removed:**
* `--color-surface-secondary` (was calculated via `color-mix`)
* `--color-surface-tertiary` (was calculated via `color-mix`)
**Replacement:**
These variables now directly reference the base variables defined in `variables.css`:
* `--color-surface-secondary` → Uses `var(--surface-secondary)` directly
* `--color-surface-tertiary` → Uses `var(--surface-tertiary)` directly
The base variables `--surface-secondary` and `--surface-tertiary` are now defined directly in `variables.css` instead of being calculated in `theme.css`.
#### On Surface Color Variables
All `--color-on-surface-*` variables have been removed entirely:
**Removed:**
* `--color-on-surface`
* `--color-on-surface-foreground`
* `--color-on-surface-hover`
* `--color-on-surface-focus`
* `--color-on-surface-secondary`
* `--color-on-surface-secondary-foreground`
* `--color-on-surface-secondary-hover`
* `--color-on-surface-secondary-focus`
* `--color-on-surface-tertiary`
* `--color-on-surface-tertiary-foreground`
* `--color-on-surface-tertiary-hover`
* `--color-on-surface-tertiary-focus`
**Migration:**
If you were using these variables, update your code to use the appropriate surface variables directly:
```css
/* Before */
.element {
background: var(--color-on-surface);
color: var(--color-on-surface-foreground);
}
.element:hover {
background: var(--color-on-surface-hover);
}
/* After */
.element {
background: var(--surface-secondary);
color: var(--surface-secondary-foreground);
}
.element:hover {
background: color-mix(in oklab, var(--surface-secondary) 92%, var(--surface-secondary-foreground) 8%);
}
```
Or use the Tailwind utilities:
```tsx
// Before
// After
```
**Related PR:** [#6204](https://github.com/heroui-inc/heroui/pull/6204)
## Links
* [Component Documentation](/docs/react/components)
* [Design System - Figma Kit V3](https://www.figma.com/community/file/1546526812159103429/heroui-figma-kit-v3)
* [GitHub Repository](https://github.com/heroui-inc/heroui)
* [GitHub PR #6201](https://github.com/heroui-inc/heroui/pull/6201)
## Contributors
Thanks to everyone who contributed to this release!
# v3.0.0-beta.7
**Category**: react
**URL**: https://v3.heroui.com/docs/react/releases/v3-0-0-beta-7
**Source**: https://raw.githubusercontent.com/heroui-inc/heroui/refs/heads/v3/apps/docs/content/docs/react/releases/v3-0-0-beta-7.mdx
> 4 new components (Calendar, RangeCalendar, DatePicker, DateRangePicker) and APIs improvements.
February 19, 2026
This release adds 4 new components: [Calendar](/docs/components/calendar), [RangeCalendar](/docs/components/range-calendar), [DatePicker](/docs/components/date-picker), and [DateRangePicker](/docs/components/date-range-picker). Also new: [Switch.Content](#switchcontent) for grouping label and description, and [Tabs.Separator](#tabsseparator) for opt-in separator lines between tabs.
⚠️ **Breaking changes**: `hideSeparator` removed from Tabs; `DateInputGroup` and `ColorInputGroup` moved under `DateField.Group`, `TimeField.Group`, and `ColorField.Group`.
## Installation
Update to the latest version:
```bash
npm i @heroui/styles@beta @heroui/react@beta
```
```bash
pnpm add @heroui/styles@beta @heroui/react@beta
```
```bash
yarn add @heroui/styles@beta @heroui/react@beta
```
```bash
bun add @heroui/styles@beta @heroui/react@beta
```
**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](/docs/ui-for-agents/mcp-server).
## What's New
### Date & Time System
**Date & Time** — Calendar, DatePicker, RangeCalendar, and DateRangePicker built on React Aria date primitives. Supports i18n, time zones, and full keyboard/ARIA accessibility.
**Key features:**
* **Calendar systems**: Gregorian, Buddhist, Persian, and others
* **Year picker**: Overlay for quick year navigation
* **Cell indicators**: Events, availability, or status dots on cells
* **Range selection**: Date ranges with visual highlighting
* **Accessible**: Keyboard nav, screen readers, ARIA
All date values use [`@internationalized/date`](https://react-aria.adobe.com/internationalized/date/) types (`CalendarDate`, `CalendarDateTime`, `ZonedDateTime`). Wrap with [`I18nProvider`](https://react-aria.adobe.com/I18nProvider) to override locale; read it with [`useLocale`](https://react-aria.adobe.com/useLocale).
### New Components
* **[Calendar](#calendar)**: Single date selection, year picker, indicators, multi-month. ([Docs](/docs/components/calendar))
* **[RangeCalendar](#rangecalendar)**: Date ranges with range highlighting and multi-month. ([Docs](/docs/components/range-calendar))
* **[DatePicker](#datepicker)**: Date field + popover calendar. ([Docs](/docs/components/date-picker))
* **[DateRangePicker](#daterangepicker)**: Two date fields + popover range calendar. ([Docs](/docs/components/date-range-picker))
### Calendar
Single-date calendar with year picker, cell indicators, multi-month view, and i18n calendars.
```tsx
"use client";
import {Calendar} from "@heroui/react";
export function Basic() {
return (
{(day) => {day}}
{(date) => }
);
}
```
**Year Picker:**
```tsx
"use client";
import {Calendar} from "@heroui/react";
export function YearPicker() {
return (
{(day) => {day}}
{(date) => }
{({year}) => }
);
}
```
**International Calendars:**
```tsx
"use client";
import {Calendar} from "@heroui/react";
import {getLocalTimeZone, today} from "@internationalized/date";
import {I18nProvider} from "react-aria-components";
export function InternationalCalendar() {
return (
{(day) => {day}}
{(date) => }
{({year}) => }
);
}
```
### RangeCalendar
Date range selection with range highlighting and multi-month views.
```tsx
"use client";
import {RangeCalendar} from "@heroui/react";
export function Basic() {
return (
{(day) => {day}}
{(date) => }
);
}
```
**Multiple Months:**
```tsx
"use client";
import {RangeCalendar} from "@heroui/react";
import {getLocalTimeZone} from "@internationalized/date";
import React from "react";
import {RangeCalendarStateContext, useLocale} from "react-aria-components";
function RangeCalendarMonthHeading({offset = 0}: {offset?: number}) {
const state = React.useContext(RangeCalendarStateContext)!;
const {locale} = useLocale();
const startDate = state.visibleRange.start;
const monthDate = startDate.add({months: offset});
const dateObj = monthDate.toDate(getLocalTimeZone());
const monthYear = new Intl.DateTimeFormat(locale, {month: "long", year: "numeric"}).format(
dateObj,
);
return {monthYear};
}
export function MultipleMonths() {
return (
state.setTimeValue(v as TimeValue)}
>
{(segment) => }
)}
>
)}
);
}
```
### DateRangePicker
Two date fields + popover range calendar.
```tsx
"use client";
import {DateField, DateRangePicker, Label, RangeCalendar} from "@heroui/react";
export function Basic() {
return (
{(segment) => }
{(segment) => }
{(day) => {day}}
{(date) => }
{({year}) => }
);
}
```
## API Improvements
### Switch.Content
`Switch.Content` groups label and description next to the switch control ([#6240](https://github.com/heroui-inc/heroui/pull/6240)).
**Before:**
```tsx
import { Switch, Label, Description } from '@heroui/react';
Get notified when someone mentions you
```
### Tabs.Separator
The [Tabs](/docs/components/tabs) component now includes an explicit `Tabs.Separator` sub-component for adding visual separator lines between tabs. This replaces the previous automatic CSS pseudo-element separator and the `hideSeparator` prop ([#6243](https://github.com/heroui-inc/heroui/pull/6243)).
Separators are now **opt-in** — add `` inside each `` where you want a separator line.
### Field Sub-Component Consolidation
`DateField`, `TimeField`, and `ColorField` now expose their input group sub-components directly, removing the need to import `DateInputGroup` or `ColorInputGroup` separately. See [Breaking Changes](#-breaking-changes) for migration details.
### Breadcrumbs Fix
Props passed to `Breadcrumbs.Item` are now forwarded to the underlying `Link` ([#6233](https://github.com/heroui-inc/heroui/pull/6233)).
## Style Fixes
* **ListBox Item**: Adjusted hover background color from `bg-default-hover` to `bg-default` for consistency
* **Date Input Group**: Changed segment text from `tabular-nums` to `text-nowrap` for better layout
* **Date Input Group**: Improved focus-within styles to exclude date picker trigger from field focus highlighting
## Dependencies
* **React Aria Components**: Updated from `1.14.0` to `1.15.0` — adds a new [`render` prop](https://react-aria.adobe.com/customization#dom-elements) for customizing the DOM element rendered by any React Aria component (useful for router links, animation libraries like Motion, etc.)
* **@react-aria/utils**: Updated from `3.32.0` to `3.33.0`
* **@react-types/shared**: Updated from `3.32.1` to `3.33.0`
* **@internationalized/date**: Updated from `3.10.1` to `3.11.0` — date fields now constrain on blur instead of as you type
* Added `@react-aria/i18n` and `@react-stately/utils` for calendar i18n
## ⚠️ Breaking Changes
### Tabs — `hideSeparator` Prop Removed
The `hideSeparator` prop has been removed from the Tabs component. Separators are now **opt-in** using the new `` sub-component instead of being automatically generated via CSS pseudo-elements ([#6243](https://github.com/heroui-inc/heroui/pull/6243)).
**Before:**
```tsx
{/* Separators shown by default, hidden via prop */}
Tab 1Tab 2
```
**After:**
```tsx
{/* No separators by default — explicitly add them where needed */}
Tab 1Tab 2
```
**CSS Changes:**
* Tab separator styles moved from pseudo-element (`.tabs__tab:not(:first-child):before`) to a dedicated `.tabs__separator` class
* The `[data-hide-separator]` data attribute has been removed
### Field Sub-Component API Changes
`DateInputGroup` and `ColorInputGroup` are no longer exported directly from `@heroui/react`. Their sub-components have been consolidated under their respective field components (`DateField`, `TimeField`, `ColorField`).
#### DateField Changes
**Before:**
```tsx
import {DateField, Label, DateInputGroup, Description} from '@heroui/react';
...
{(segment) => }
...Pick a date
```
**After:**
```tsx
import {DateField, Label, Description} from '@heroui/react';
...
{(segment) => }
...Pick a date
```
#### TimeField Changes
Same pattern as DateField:
| Before | After |
| ------------------------ | ------------------- |
| `DateInputGroup` | `TimeField.Group` |
| `DateInputGroup.Input` | `TimeField.Input` |
| `DateInputGroup.Segment` | `TimeField.Segment` |
| `DateInputGroup.Prefix` | `TimeField.Prefix` |
| `DateInputGroup.Suffix` | `TimeField.Suffix` |
#### ColorField Changes
| Before | After |
| ------------------------ | ------------------- |
| `ColorInputGroup` | `ColorField.Group` |
| `ColorInputGroup.Input` | `ColorField.Input` |
| `ColorInputGroup.Prefix` | `ColorField.Prefix` |
| `ColorInputGroup.Suffix` | `ColorField.Suffix` |
**Usage:**
```tsx
import {ColorField, Label, ColorInputGroup, ColorSwatch} from '@heroui/react';
```
**After:**
```tsx
import {ColorField, Label, ColorSwatch} from '@heroui/react';
```
> **Note:** The underlying CSS classes (`.date-input-group`, `.color-input-group`, etc.) remain unchanged. Only the JavaScript import paths and component names have changed.
## Links
* [Component Documentation](/docs/react/components)
* [Design System - Figma Kit V3](https://www.figma.com/community/file/1546526812159103429/heroui-figma-kit-v3)
* [GitHub Repository](https://github.com/heroui-inc/heroui)
* [GitHub PR #6237](https://github.com/heroui-inc/heroui/pull/6237)
## Contributors
Thanks to everyone who contributed to this release!
# v3.0.0-beta.8
**Category**: react
**URL**: https://v3.heroui.com/docs/react/releases/v3-0-0-beta-8
**Source**: https://raw.githubusercontent.com/heroui-inc/heroui/refs/heads/v3/apps/docs/content/docs/react/releases/v3-0-0-beta-8.mdx
> 3 new components (Badge, Pagination, Table), DateField improvements, and key API/style fixes.
March 2, 2026
This release adds three new components: [Badge](/docs/components/badge), [Pagination](/docs/components/pagination), and [Table](/docs/components/table), plus new `InputContainer` composition APIs for [DateField](/docs/components/date-field) and [TimeField](/docs/components/time-field).
⚠️ **Breaking changes**: TextField CSS classes were renamed from `.text-field` to `.textfield`.
## Installation
Update to the latest version:
```bash
npm i @heroui/styles@beta @heroui/react@beta
```
```bash
pnpm add @heroui/styles@beta @heroui/react@beta
```
```bash
yarn add @heroui/styles@beta @heroui/react@beta
```
```bash
bun add @heroui/styles@beta @heroui/react@beta
```
**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](/docs/ui-for-agents/mcp-server).
## What's New
### New Components
* **[Badge](#badge)**: Compact status + count indicator with color, variant, placement, and size options. ([Docs](/docs/components/badge))
* **[Pagination](#pagination)**: Compound pagination primitives with summary, ellipsis, and previous/next controls. ([Docs](/docs/components/pagination))
* **[Table](#table)**: Data table primitives with sorting, selection, resizing, async loading, and footer composition. ([Docs](/docs/components/table))
### Badge
New badge primitives for counters, labels, and anchored overlays with `Badge.Anchor` and `Badge.Label`.
```tsx
import {Avatar, Badge} from "@heroui/react";
const GREEN_AVATAR_URL = "https://heroui-assets.nyc3.cdn.digitaloceanspaces.com/avatars/green.jpg";
const ORANGE_AVATAR_URL =
"https://heroui-assets.nyc3.cdn.digitaloceanspaces.com/avatars/orange.jpg";
const BLUE_AVATAR_URL = "https://heroui-assets.nyc3.cdn.digitaloceanspaces.com/avatars/blue.jpg";
export function BadgeBasic() {
return (
JD
5
AB
New
CD
);
}
```
### Pagination
New navigation component built with composable parts (`Root`, `Content`, `Item`, `Link`, `Previous`, `Next`, `Summary`, `Ellipsis`).
```tsx
"use client";
import {Pagination} from "@heroui/react";
import {useState} from "react";
export function PaginationWithEllipsis() {
const [page, setPage] = useState(1);
const totalPages = 12;
const getPageNumbers = () => {
const pages: (number | "ellipsis")[] = [];
pages.push(1);
if (page > 3) {
pages.push("ellipsis");
}
const start = Math.max(2, page - 1);
const end = Math.min(totalPages - 1, page + 1);
for (let i = start; i <= end; i++) {
pages.push(i);
}
if (page < totalPages - 2) {
pages.push("ellipsis");
}
pages.push(totalPages);
return pages;
};
return (
setPage((p) => p - 1)}>
Previous
{getPageNumbers().map((p, i) =>
p === "ellipsis" ? (
) : (
setPage(p)}>
{p}
),
)}
setPage((p) => p + 1)}>
Next
);
}
```
### Table
Compound data table on React Aria with sortable columns, row selection, custom cells, load-more sentinel rows, and resizable columns.
```tsx
import {Table} from "@heroui/react";
export function Basic() {
return (
Seven new components: [Drawer](/docs/components/drawer), [ToggleButton](/docs/components/toggle-button), [ToggleButtonGroup](/docs/components/toggle-button-group), [Meter](/docs/components/meter), [ProgressBar](/docs/components/progress-bar), [ProgressCircle](/docs/components/progress-circle), and [Toolbar](/docs/components/toolbar). Table and ListBox gain virtualization, ButtonGroup gets a `Separator` sub-component + vertical orientation, and React Aria Components is bumped to v1.16.0.
## Installation
Update to the latest version:
```bash
npm i @heroui/styles@rc @heroui/react@rc
```
```bash
pnpm add @heroui/styles@rc @heroui/react@rc
```
```bash
yarn add @heroui/styles@rc @heroui/react@rc
```
```bash
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](/docs/ui-for-agents/mcp-server).
## What's New
### New Components
* **[Drawer](#drawer)**: Slide-out panel with drag-to-dismiss, 4 placements, backdrop variants, scrollable body ([Docs](/docs/components/drawer))
* **[ToggleButton](#toggle-button)**: Selected/unselected toggle with all button variants + icon-only mode ([Docs](/docs/components/toggle-button))
* **[ToggleButtonGroup](#toggle-button-group)**: Single or multi-select toggle group, attached/detached layouts, orientation ([Docs](/docs/components/toggle-button-group))
* **[Meter](#meter)**: Value within a known range — disk usage, password strength, quotas ([Docs](/docs/components/meter))
* **[ProgressBar](#progress-bar)**: Linear progress, determinate + indeterminate, colors, custom formatting ([Docs](/docs/components/progress-bar))
* **[ProgressCircle](#progress-circle)**: Circular SVG progress with customizable track + fill circles ([Docs](/docs/components/progress-circle))
* **[Toolbar](#toolbar)**: Groups buttons, toggles, and separators with horizontal or vertical orientation ([Docs](/docs/components/toolbar))
### 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`.
```tsx
import {Button, Drawer} from "@heroui/react";
export function Basic() {
return (
Drawer Title
This is a bottom drawer built with React Aria's Modal component. It slides up from
the bottom of the screen with a smooth CSS transition.
);
}
```
**Placements:**
```tsx
import {Button, Drawer} from "@heroui/react";
export function Placements() {
const placements = ["bottom", "top", "left", "right"] as const;
return (
This drawer slides in from the {placement} edge of the screen.
{placement === "top" && }
))}
);
}
```
**With Form:**
```tsx
import {Button, Drawer, Input, Label, TextField} from "@heroui/react";
export function WithForm() {
return (
Edit Profile
);
}
```
### Toggle Button
Stateful toggle between selected and unselected. All button variants and sizes, icon-only mode, controlled or uncontrolled.
```tsx
import {Heart} from "@gravity-ui/icons";
import {ToggleButton} from "@heroui/react";
export function Basic() {
return (
Like
);
}
```
**Variants:**
```tsx
import {Heart} from "@gravity-ui/icons";
import {ToggleButton} from "@heroui/react";
export function Variants() {
return (
Default
Ghost
);
}
```
### Toggle Button Group
Single or multi-select toggle group. Attached (connected) and detached layouts, vertical orientation, full-width, and a `Separator` sub-component.
```tsx
import {Bold, Italic, Strikethrough, Underline} from "@gravity-ui/icons";
import {ToggleButton, ToggleButtonGroup} from "@heroui/react";
export function Basic() {
return (
);
}
```
**Selection Mode:**
```tsx
import {
Bold,
Italic,
Strikethrough,
TextAlignCenter,
TextAlignLeft,
TextAlignRight,
Underline,
} from "@gravity-ui/icons";
import {ToggleButton, ToggleButtonGroup} from "@heroui/react";
export function SelectionMode() {
return (
Single selection
Left
Center
Right
Multiple selection
);
}
```
**Attached Mode:**
```tsx
import {Bold, Italic, Strikethrough, Underline} from "@gravity-ui/icons";
import {ToggleButton, ToggleButtonGroup} from "@heroui/react";
export function Attached() {
return (
Attached (default)
Detached
);
}
```
### Meter
Value within a known range — disk usage, password strength, quotas. Compound parts: `Root`, `Output`, `Track`, `Fill`.
```tsx
import {Label, Meter} from "@heroui/react";
export function Basic() {
return (
);
}
```
**Colors:**
```tsx
import {Label, Meter} from "@heroui/react";
export function Colors() {
return (
);
}
```
### Progress Bar
Linear progress indicator with determinate + indeterminate states, color variants, sizes, and custom value display. Compound parts: `Root`, `Output`, `Track`, `Fill`.
```tsx
import {Label, ProgressBar} from "@heroui/react";
export function Basic() {
return (
);
}
```
**Indeterminate:**
```tsx
import {Label, ProgressBar} from "@heroui/react";
export function Indeterminate() {
return (
);
}
```
### Progress Circle
Circular SVG progress with `TrackCircle` and `FillCircle` sub-components for direct SVG control. Determinate + indeterminate states.
```tsx
import {ProgressCircle} from "@heroui/react";
export function Basic() {
return (
);
}
```
**Custom SVG:**
```tsx
import {ProgressCircle} from "@heroui/react";
export function CustomSvg() {
return (
);
}
```
### Toolbar
Groups buttons, toggle buttons, and separators into an accessible toolbar. Horizontal or vertical orientation, composes with `ButtonGroup` and `ToggleButtonGroup`.
```tsx
import {Bold, Copy, Italic, Scissors, Underline} from "@gravity-ui/icons";
import {
Button,
ButtonGroup,
Separator,
ToggleButton,
ToggleButtonGroup,
Toolbar,
} from "@heroui/react";
export function Basic() {
return (
);
}
```
**With Button Group:**
```tsx
import {
ArrowUturnCcwLeft,
ArrowUturnCwRight,
Bold,
Italic,
TextAlignCenter,
TextAlignLeft,
TextAlignRight,
Underline,
} from "@gravity-ui/icons";
import {
Button,
ButtonGroup,
Separator,
ToggleButton,
ToggleButtonGroup,
Toolbar,
} from "@heroui/react";
export function WithButtonGroup() {
return (
);
}
```
## Component Improvements
### ButtonGroup Enhancements
New `ButtonGroup.Separator` sub-component adds an explicit visual divider between buttons. Works in both horizontal and vertical orientations.
```tsx
import {
ChevronDown,
ChevronLeft,
ChevronRight,
CodeFork,
Ellipsis,
Picture,
Pin,
QrCode,
Star,
TextAlignCenter,
TextAlignJustify,
TextAlignLeft,
TextAlignRight,
ThumbsDown,
ThumbsUp,
Video,
} from "@gravity-ui/icons";
import {Button, ButtonGroup, Chip, Description, Dropdown, Label} from "@heroui/react";
export function Basic() {
return (
{/* Single button with dropdown */}
All commits from this branch will be added to the base branch
The 14 commits from this branch will be combined into one commit in the base
branch
The 14 commits from this branch will be rebased and added to the base branch
Name
Role
Email
{(user) => (
{user.name}{user.role}{user.email}
)}
);
}
```
### 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 `
` to React Aria's `Group` for proper `role="group"` semantics.
```tsx
import {TextAlignCenter, TextAlignJustify, TextAlignLeft, TextAlignRight} from "@gravity-ui/icons";
import {Button, ButtonGroup} from "@heroui/react";
export function Orientation() {
return (
Horizontal
Vertical
);
}
```
### 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](https://github.com/heroui-inc/heroui/pull/6301)):
```tsx
// 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:
| Package | Old | New |
| ------------------------- | ------- | ------- |
| `react-aria-components` | 1.15.1 | 1.16.0 |
| `@react-aria/i18n` | 3.12.15 | 3.12.16 |
| `@react-aria/utils` | 3.33.0 | 3.33.1 |
| `@react-types/shared` | 3.33.0 | 3.33.1 |
| `@react-types/color` | 3.1.3 | 3.1.4 |
| `@internationalized/date` | 3.11.0 | 3.12.0 |
| `@react-stately/data` | 3.15.1 | 3.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](https://github.com/heroui-inc/heroui/pull/6274))
* **Avatar**: Fallback element inherits `border-radius` from the parent instead of hardcoding `rounded-full`, so `className` overrides apply correctly ([#6300](https://github.com/heroui-inc/heroui/pull/6300))
* **Modal & AlertDialog**: Backdrop click events no longer propagate through portals to parent elements ([#6297](https://github.com/heroui-inc/heroui/pull/6297))
* **Table**: Fixed header rounding and background color bleeding in Firefox ([#6298](https://github.com/heroui-inc/heroui/pull/6298))
## Links
* [Component Docs](/docs/react/components)
* [Figma Kit V3](https://www.figma.com/community/file/1546526812159103429/heroui-figma-kit-v3)
* [GitHub Repository](https://github.com/heroui-inc/heroui)
* [GitHub PR #6285](https://github.com/heroui-inc/heroui/pull/6285)
## Contributors
Thanks to everyone who contributed to this release!
# Button
**Category**: native
**URL**: https://v3.heroui.com/docs/native/components/button
**Source**: https://raw.githubusercontent.com/heroui-inc/heroui/refs/heads/v3/apps/docs/content/docs/native/components/(buttons)/button.mdx
> Interactive component that triggers an action when pressed.
## Import
```tsx
import { Button } from 'heroui-native';
```
## Anatomy
```tsx
```
* **Button**: Main container that handles press interactions, animations, and variants. Renders string children as label or accepts compound components for custom layouts.
* **Button.Label**: Text content of the button. Inherits size and variant styling from parent Button context.
## Usage
### Basic Usage
The Button component accepts string children that automatically render as label.
```tsx
```
### With Compound Parts
Use Button.Label for explicit control over the label component.
```tsx
```
### With Icons
Combine icons with labels for enhanced visual communication.
```tsx
```
### Icon Only
Create square icon-only buttons using the isIconOnly prop.
```tsx
```
### Sizes
Control button dimensions with three size options.
```tsx
```
### Variants
Choose from seven visual variants for different emphasis levels.
```tsx
```
### Feedback Variants
The `feedbackVariant` prop controls which press feedback effects are rendered:
* `'scale-highlight'` (default): Built-in scale + highlight overlay
* `'scale-ripple'`: Built-in scale + ripple overlay
* `'scale'`: Built-in scale only (no overlay)
* `'none'`: No feedback animations at all
```tsx
{/* Scale + Highlight (default) */}
{/* Scale + Ripple */}
{/* Scale only */}
{/* No feedback */}
```
### Custom Animation
The `animation` prop controls individual sub-animations. Its shape depends on the `feedbackVariant`.
```tsx
{/* Customize scale and highlight (default feedbackVariant) */}
{/* Customize scale and ripple */}
```
### Disable Individual Animations
Disable specific sub-animations by setting them to `false`:
```tsx
{/* Disable scale, keep highlight */}
{/* Disable highlight, keep scale */}
{/* Disable both */}
```
### Disable All Animations
Use `animation={false}` to disable all feedback, or `animation="disable-all"` for cascading disable:
```tsx
```
### Loading State with Spinner
Transform button to loading state with spinner animation.
```tsx
const themeColorAccentForeground = useThemeColor('accent-foreground');
;
```
### Custom Background with LinearGradient
Add gradient backgrounds using absolute positioned elements. Use `feedbackVariant="none"` to disable the default highlight overlay, or use `feedbackVariant="scale-ripple"` for a custom ripple effect.
```tsx
import { Button, PressableFeedback } from 'heroui-native';
import { LinearGradient } from 'expo-linear-gradient';
import { StyleSheet } from 'react-native';
{/* Gradient with no feedback overlay */}
{/* Gradient with custom ripple effect */}
```
## Example
```tsx
import { Button, useThemeColor } from 'heroui-native';
import { Ionicons } from '@expo/vector-icons';
import { View } from 'react-native';
export default function ButtonExample() {
const [
themeColorAccentForeground,
themeColorAccentSoftForeground,
themeColorDangerForeground,
themeColorDefaultForeground,
] = useThemeColor([
'accent-foreground',
'accent-soft-foreground',
'danger-foreground',
'default-foreground',
]);
return (
);
}
```
You can find more examples in the [GitHub repository](https://github.com/heroui-inc/heroui-native/blob/rc/example/src/app/\(home\)/components/button.tsx).
## API Reference
### Button
Button extends all props from [PressableFeedback](./pressable-feedback) (except `animation`, which is redefined) with additional button-specific props.
| prop | type | default | description |
| ----------------- | --------------------------------------------------------------------------------------------- | ------------------- | -------------------------------------------------------------- |
| `variant` | `'primary' \| 'secondary' \| 'tertiary' \| 'outline' \| 'ghost' \| 'danger' \| 'danger-soft'` | `'primary'` | Visual variant of the button |
| `size` | `'sm' \| 'md' \| 'lg'` | `'md'` | Size of the button |
| `isIconOnly` | `boolean` | `false` | Whether the button displays an icon only (square aspect ratio) |
| `feedbackVariant` | `'scale-highlight' \| 'scale-ripple' \| 'scale' \| 'none'` | `'scale-highlight'` | Determines which feedback effects are rendered |
| `animation` | `ButtonAnimation` | - | Animation configuration (shape depends on `feedbackVariant`) |
For inherited props including `isDisabled`, `className`, `children`, and all Pressable props, see [PressableFeedback API Reference](./pressable-feedback#api-reference).
#### ButtonAnimation
The `animation` prop is a discriminated union based on `feedbackVariant`. It follows the `AnimationRoot` control flow:
* `true` or `undefined`: Use default animations
* `false` or `"disabled"`: Disable all feedback animations
* `"disable-all"`: Cascade-disable all animations including child compound parts
* `object`: Custom configuration with sub-animation keys (see below)
**When `feedbackVariant="scale-highlight"` (default):**
| prop | type | default | description |
| ----------- | ---------------------------------------- | ------- | ------------------------------------------------------------- |
| `scale` | `PressableFeedbackScaleAnimation` | - | Scale animation config (`false` to disable) |
| `highlight` | `PressableFeedbackHighlightAnimation` | - | Highlight overlay config (`false` to disable) |
| `state` | `'disabled' \| 'disable-all' \| boolean` | - | Control animation state while keeping config (runtime toggle) |
**When `feedbackVariant="scale-ripple"`:**
| prop | type | default | description |
| -------- | ---------------------------------------- | ------- | ------------------------------------------------------------- |
| `scale` | `PressableFeedbackScaleAnimation` | - | Scale animation config (`false` to disable) |
| `ripple` | `PressableFeedbackRippleAnimation` | - | Ripple overlay config (`false` to disable) |
| `state` | `'disabled' \| 'disable-all' \| boolean` | - | Control animation state while keeping config (runtime toggle) |
**When `feedbackVariant="scale"`:**
| prop | type | default | description |
| ------- | ---------------------------------------- | ------- | ------------------------------------------------------------- |
| `scale` | `PressableFeedbackScaleAnimation` | - | Scale animation config (`false` to disable) |
| `state` | `'disabled' \| 'disable-all' \| boolean` | - | Control animation state while keeping config (runtime toggle) |
**When `feedbackVariant="none"`:**
Only `'disable-all'` is accepted as a string value. All feedback effects are disabled.
For detailed animation sub-types (`PressableFeedbackScaleAnimation`, `PressableFeedbackHighlightAnimation`, `PressableFeedbackRippleAnimation`), see [PressableFeedback API Reference](./pressable-feedback#api-reference).
### Button.Label
| prop | type | default | description |
| -------------- | ----------------- | ------- | ------------------------------------- |
| `children` | `React.ReactNode` | - | Content to be rendered as label |
| `className` | `string` | - | Additional CSS classes |
| `...TextProps` | `TextProps` | - | All standard Text props are supported |
## Hooks
### useButton
Hook to access the Button context values. Returns the button's size, variant, and disabled state.
```tsx
import { useButton } from 'heroui-native';
const { size, variant, isDisabled } = useButton();
```
#### Return Value
| property | type | description |
| ------------ | --------------------------------------------------------------------------------------------- | ------------------------------ |
| `size` | `'sm' \| 'md' \| 'lg'` | Size of the button |
| `variant` | `'primary' \| 'secondary' \| 'tertiary' \| 'outline' \| 'ghost' \| 'danger' \| 'danger-soft'` | Visual variant of the button |
| `isDisabled` | `boolean` | Whether the button is disabled |
**Note:** This hook must be used within a `Button` component. It will throw an error if called outside of the button context.
# CloseButton
**Category**: native
**URL**: https://v3.heroui.com/docs/native/components/close-button
**Source**: https://raw.githubusercontent.com/heroui-inc/heroui/refs/heads/v3/apps/docs/content/docs/native/components/(buttons)/close-button.mdx
> Button component for closing dialogs, modals, or dismissing content.
## Import
```tsx
import { CloseButton } from 'heroui-native';
```
## Usage
### Basic Usage
The CloseButton component renders a close icon button with default styling.
```tsx
```
### Custom Icon Color
Customize the icon color using the `iconProps` prop.
```tsx
```
### Custom Icon Size
Adjust the icon size using the `iconProps` prop.
```tsx
```
### Custom Children
Replace the default close icon with custom content.
```tsx
```
### Disabled State
Disable the button to prevent interactions.
```tsx
```
## Example
```tsx
import { CloseButton, useThemeColor } from 'heroui-native';
import { Ionicons } from '@expo/vector-icons';
import { View } from 'react-native';
import { withUniwind } from 'uniwind';
const StyledIonicons = withUniwind(Ionicons);
export default function CloseButtonExample() {
const themeColorForeground = useThemeColor('foreground');
const themeColorDanger = useThemeColor('danger');
return (
);
}
```
You can find more examples in the [GitHub repository](https://github.com/heroui-inc/heroui-native/blob/rc/example/src/app/\(home\)/components/close-button.tsx).
## API Reference
### CloseButton
CloseButton extends all props from [Button](./button) component. It defaults to `variant='tertiary'`, `size='sm'`, and `isIconOnly=true`.
| prop | type | default | description |
| ----------- | ---------------------- | ------- | ------------------------------------------------ |
| `iconProps` | `CloseButtonIconProps` | - | Props for customizing the close icon |
| `children` | `React.ReactNode` | - | Custom content to replace the default close icon |
For inherited props including `isDisabled`, `className`, `animation`, `feedbackVariant` and all Pressable props, see [Button API Reference](./button#api-reference).
#### CloseButtonIconProps
| prop | type | default | description |
| ------- | -------- | ---------------------- | ----------------- |
| `size` | `number` | `20` | Size of the icon |
| `color` | `string` | Uses theme muted color | Color of the icon |
# Menu
**Category**: native
**URL**: https://v3.heroui.com/docs/native/components/menu
**Source**: https://raw.githubusercontent.com/heroui-inc/heroui/refs/heads/v3/apps/docs/content/docs/native/components/(collections)/menu.mdx
> A floating context menu with positioning, selection groups, and multiple presentation modes.
## Import
```tsx
import { Menu, SubMenu } from 'heroui-native';
```
## Anatomy
```tsx
```
* **Menu**: Main container that manages open/close state, positioning, and provides context to child components.
* **Menu.Trigger**: Clickable element that toggles the menu visibility.
* **Menu.Portal**: Renders menu content in a portal layer above other content.
* **Menu.Overlay**: Optional background overlay to capture outside clicks and close the menu.
* **Menu.Content**: Container for menu content with two presentation modes: floating popover with positioning and collision detection, or bottom sheet modal.
* **Menu.Close**: Close button that dismisses the menu when pressed.
* **Menu.Label**: Non-interactive section heading text within the menu.
* **Menu.Group**: Groups menu items with optional selection state (none, single, multiple).
* **Menu.Item**: Pressable menu item with animated press feedback. Standalone or within a Group for selection.
* **Menu.ItemTitle**: Primary label text for a menu item.
* **Menu.ItemDescription**: Secondary description text for a menu item.
* **Menu.ItemIndicator**: Visual selection indicator (checkmark or dot) for a menu item.
* **SubMenu**: Root container that manages the expand/collapse state and provides animation context to children.
* **SubMenu.Trigger**: Pressable row that toggles the submenu open/closed. Styled like a regular menu item.
* **SubMenu.TriggerIndicator**: Animated chevron icon (default: chevron-right) that rotates when the submenu opens/closes. Place inside `SubMenu.Trigger`.
* **SubMenu.Content**: Absolutely positioned container that animates its height when the submenu opens/closes. Place `Menu.Item` elements inside.
## Usage
### Basic Usage
The Menu component uses compound parts to create a floating context menu.
```tsx
```
### With Item Descriptions
Add secondary description text to menu items alongside titles.
```tsx
```
### Single Selection
Use `Menu.Group` with `selectionMode="single"` to allow one selected item at a time.
```tsx
const [theme, setTheme] = useState>(() => new Set(['system']));
;
```
### Multiple Selection
Use `selectionMode="multiple"` to allow selecting multiple items simultaneously.
```tsx
const [textStyles, setTextStyles] = useState>(
() => new Set(['bold', 'italic'])
);
;
```
### With SubMenu
Nest a `SubMenu` inside `Menu.Content` to reveal additional items on press.
```tsx
```
### Danger Variant
Use `variant="danger"` on a menu item for destructive actions.
```tsx
```
### Placements
Control where the menu appears relative to the trigger.
```tsx
```
### Bottom Sheet Presentation
Use `presentation="bottom-sheet"` to display menu content as a bottom sheet modal.
```tsx
```
### Dot Indicator
Use `variant="dot"` on `Menu.ItemIndicator` to show a filled circle instead of a checkmark.
```tsx
```
## Example
```tsx
import type { MenuKey } from 'heroui-native';
import { Button, Menu, Separator } from 'heroui-native';
import { useState } from 'react';
import { Text, View } from 'react-native';
export default function MenuExample() {
const [textStyles, setTextStyles] = useState>(
() => new Set(['bold', 'italic'])
);
const [alignment, setAlignment] = useState>(
() => new Set(['left'])
);
return (
);
}
```
You can find more examples in the [GitHub repository](https://github.com/heroui-inc/heroui-native/blob/rc/example/src/app/\(home\)/components/menu.tsx).
## API Reference
### Menu
| prop | type | default | description |
| --------------- | ----------------------------- | ----------- | -------------------------------------------------- |
| `children` | `React.ReactNode` | - | The content of the menu |
| `presentation` | `'popover' \| 'bottom-sheet'` | `'popover'` | Presentation mode for the menu content |
| `isOpen` | `boolean` | - | Controlled open state of the menu |
| `isDefaultOpen` | `boolean` | - | Open state when initially rendered (uncontrolled) |
| `isDisabled` | `boolean` | - | Whether the menu is disabled |
| `animation` | `MenuRootAnimation` | - | Animation configuration for menu root |
| `onOpenChange` | `(open: boolean) => void` | - | Callback fired when the menu open state changes |
| `...ViewProps` | `ViewProps` | - | All standard React Native View props are supported |
#### MenuRootAnimation
Animation configuration for menu root component. Can be:
* `"disable-all"`: Disable all animations including children
* `true` or `undefined`: Use default animations
### Menu.Trigger
| prop | type | default | description |
| ------------------- | ----------------- | ------- | ------------------------------------------------------- |
| `children` | `React.ReactNode` | - | The trigger element content |
| `className` | `string` | - | Additional CSS class for the trigger |
| `isDisabled` | `boolean` | `false` | Whether the trigger is disabled |
| `asChild` | `boolean` | - | Render as child element using Slot pattern |
| `...PressableProps` | `PressableProps` | - | All standard React Native Pressable props are supported |
### Menu.Portal
| prop | type | default | description |
| -------------------------- | ----------------- | ------- | ------------------------------------------------------ |
| `children` | `React.ReactNode` | - | The portal content |
| `className` | `string` | - | Additional CSS class for the portal container |
| `disableFullWindowOverlay` | `boolean` | `false` | Use a regular View instead of FullWindowOverlay on iOS |
| `hostName` | `string` | - | Optional name of the host element for the portal |
| `forceMount` | `boolean` | - | Force mount the portal regardless of open state |
### Menu.Overlay
| prop | type | default | description |
| ----------------------- | ---------------------- | ------- | ------------------------------------------------------------ |
| `className` | `string` | - | Additional CSS class for the overlay |
| `closeOnPress` | `boolean` | `true` | Whether to close the menu when the overlay is pressed |
| `animation` | `MenuOverlayAnimation` | - | Animation configuration for overlay |
| `isAnimatedStyleActive` | `boolean` | `true` | Whether animated styles (react-native-reanimated) are active |
| `forceMount` | `boolean` | - | Force mount the overlay regardless of open state |
| `...PressableProps` | `PressableProps` | - | All standard React Native Pressable props are supported |
#### MenuOverlayAnimation
Animation configuration for menu overlay component. Can be:
* `false` or `"disabled"`: Disable all animations
* `true` or `undefined`: Use default animations
* `object`: Custom animation configuration
| prop | type | default | description |
| ------------------------ | ----------------------- | ----------------------- | ----------------------------------------------- |
| `state` | `'disabled' \| boolean` | - | Disable animations while customizing properties |
| `opacity.entering.value` | `EntryOrExitLayoutType` | `FadeIn.duration(200)` | Custom entering animation for overlay |
| `opacity.exiting.value` | `EntryOrExitLayoutType` | `FadeOut.duration(150)` | Custom exiting animation for overlay |
### Menu.Content (Popover)
Props when `presentation="popover"`.
| prop | type | default | description |
| ----------------- | ------------------------------------------------ | --------------- | -------------------------------------------------- |
| `children` | `React.ReactNode` | - | The menu content |
| `presentation` | `'popover'` | - | Presentation mode (must match Menu root) |
| `placement` | `'top' \| 'bottom' \| 'left' \| 'right'` | `'bottom'` | Where the menu appears relative to the trigger |
| `align` | `'start' \| 'center' \| 'end'` | `'center'` | Alignment of the menu relative to the trigger |
| `avoidCollisions` | `boolean` | `true` | Whether to reposition to avoid screen edges |
| `offset` | `number` | `9` | Distance from the trigger element in pixels |
| `alignOffset` | `number` | `0` | Offset along the alignment axis in pixels |
| `width` | `'content-fit' \| 'trigger' \| 'full' \| number` | `'content-fit'` | Content width sizing strategy |
| `className` | `string` | - | Additional CSS class for the content container |
| `animation` | `MenuContentAnimation` | - | Animation configuration for content |
| `...ViewProps` | `ViewProps` | - | All standard React Native View props are supported |
#### MenuContentAnimation
Animation configuration for menu popover content component. Can be:
* `false` or `"disabled"`: Disable all animations
* `true` or `undefined`: Use default animations
* `object`: Custom animation configuration
| prop | type | default | description |
| ---------------- | ----------------------- | ------------------------------- | ----------------------------------------------- |
| `state` | `'disabled' \| boolean` | - | Disable animations while customizing properties |
| `entering.value` | `EntryOrExitLayoutType` | Scale + fade entering animation | Custom entering animation for content |
| `exiting.value` | `EntryOrExitLayoutType` | Scale + fade exiting animation | Custom exiting animation for content |
### Menu.Content (Bottom Sheet)
Props when `presentation="bottom-sheet"`. Extends `@gorhom/bottom-sheet` BottomSheet props.
| prop | type | default | description |
| --------------------------- | ---------------------------------------- | ------- | ---------------------------------------------------- |
| `children` | `React.ReactNode` | - | The bottom sheet content |
| `presentation` | `'bottom-sheet'` | - | Presentation mode (must match Menu root) |
| `className` | `string` | - | Additional CSS class for the bottom sheet |
| `backgroundClassName` | `string` | - | Additional CSS class for the background |
| `handleIndicatorClassName` | `string` | - | Additional CSS class for the handle indicator |
| `contentContainerClassName` | `string` | - | Additional CSS class for the content container |
| `contentContainerProps` | `Omit` | - | Props for the content container |
| `animation` | `AnimationDisabled` | - | Set to `false` or `"disabled"` to disable animations |
| `...BottomSheetProps` | `Partial` | - | All `@gorhom/bottom-sheet` props are supported |
### Menu.Close
Extends `CloseButtonProps`. Automatically closes the menu when pressed.
| prop | type | default | description |
| ---------------- | ---------------------- | ------- | ------------------------------------ |
| `iconProps` | `CloseButtonIconProps` | - | Props for customizing the close icon |
| `...ButtonProps` | `ButtonRootProps` | - | All Button root props are supported |
### Menu.Group
| prop | type | default | description |
| --------------------- | ---------------------------------- | -------- | -------------------------------------------------- |
| `children` | `React.ReactNode` | - | The group content (Menu.Item elements) |
| `selectionMode` | `'none' \| 'single' \| 'multiple'` | `'none'` | The type of selection allowed in the group |
| `selectedKeys` | `Iterable` | - | Currently selected keys (controlled) |
| `defaultSelectedKeys` | `Iterable` | - | Initially selected keys (uncontrolled) |
| `isDisabled` | `boolean` | `false` | Whether the entire group is disabled |
| `disabledKeys` | `Iterable` | - | Keys of items that should be disabled |
| `shouldCloseOnSelect` | `boolean` | - | Whether selecting an item should close the menu |
| `className` | `string` | - | Additional CSS class for the group container |
| `onSelectionChange` | `(keys: Set) => void` | - | Callback fired when the selection changes |
| `...ViewProps` | `ViewProps` | - | All standard React Native View props are supported |
### Menu.Label
| prop | type | default | description |
| -------------- | ----------------- | ------- | -------------------------------------------------- |
| `children` | `React.ReactNode` | - | The label text content |
| `className` | `string` | - | Additional CSS class for the label |
| `...TextProps` | `TextProps` | - | All standard React Native Text props are supported |
### Menu.Item
| prop | type | default | description |
| ----------------------- | ---------------------------------------------------------------- | ----------- | ------------------------------------------------------------ |
| `children` | `React.ReactNode \| ((props: MenuItemRenderProps) => ReactNode)` | - | Child elements or a render function |
| `id` | `MenuKey` | - | Unique identifier, required when inside a Menu.Group |
| `variant` | `'default' \| 'danger'` | `'default'` | Visual variant of the menu item |
| `isDisabled` | `boolean` | `false` | Whether the item is disabled |
| `isSelected` | `boolean` | - | Controlled selected state for standalone items |
| `shouldCloseOnSelect` | `boolean` | `true` | Whether pressing this item should close the menu |
| `className` | `string` | - | Additional CSS class for the item |
| `animation` | `MenuItemAnimation` | - | Animation configuration for press feedback |
| `isAnimatedStyleActive` | `boolean` | `true` | Whether animated styles (react-native-reanimated) are active |
| `onSelectedChange` | `(selected: boolean) => void` | - | Callback when standalone item's selected state changes |
| `...PressableProps` | `PressableProps` | - | All standard React Native Pressable props are supported |
#### MenuItemRenderProps
Props passed to the render function when `children` is a function.
| prop | type | description |
| ------------ | ----------------------- | --------------------------------------- |
| `isSelected` | `boolean` | Whether this item is currently selected |
| `isDisabled` | `boolean` | Whether the item is disabled |
| `isPressed` | `SharedValue` | Whether the item is currently pressed |
| `variant` | `'default' \| 'danger'` | Visual variant of the item |
#### MenuItemAnimation
Animation configuration for menu item press feedback. Can be:
* `false` or `"disabled"`: Disable all item animations
* `true` or `undefined`: Use default animations
* `object`: Custom animation configuration
| prop | type | default | description |
| ------------------------------ | ------------------ | -------------------------- | ---------------------------------------- |
| `scale.value` | `number` | `0.98` | Scale value when pressed |
| `scale.timingConfig` | `WithTimingConfig` | `{ duration: 150 }` | Spring animation configuration for scale |
| `backgroundColor.value` | `string` | `useThemeColor('default')` | Background color shown while pressed |
| `backgroundColor.timingConfig` | `WithTimingConfig` | `{ duration: 150 }` | Animation timing for background color |
### Menu.ItemTitle
| prop | type | default | description |
| -------------- | ----------------- | ------- | -------------------------------------------------- |
| `children` | `React.ReactNode` | - | The title text content |
| `className` | `string` | - | Additional CSS class for the item title |
| `...TextProps` | `TextProps` | - | All standard React Native Text props are supported |
### Menu.ItemDescription
| prop | type | default | description |
| -------------- | ----------------- | ------- | -------------------------------------------------- |
| `children` | `React.ReactNode` | - | The description text content |
| `className` | `string` | - | Additional CSS class for the item description |
| `...TextProps` | `TextProps` | - | All standard React Native Text props are supported |
### Menu.ItemIndicator
| prop | type | default | description |
| -------------- | ---------------------------- | ------------- | ------------------------------------------------------ |
| `children` | `React.ReactNode` | - | Custom indicator content, defaults to checkmark or dot |
| `variant` | `'checkmark' \| 'dot'` | `'checkmark'` | Visual variant of the indicator |
| `iconProps` | `MenuItemIndicatorIconProps` | - | Icon configuration (checkmark variant) |
| `forceMount` | `boolean` | `true` | Force mount the indicator regardless of selected state |
| `className` | `string` | - | Additional CSS class for the item indicator |
| `...ViewProps` | `ViewProps` | - | All standard React Native View props are supported |
#### MenuItemIndicatorIconProps
| prop | type | default | description |
| ------- | -------- | ------- | ---------------------------------------------- |
| `size` | `number` | `16` | Size of the indicator icon (8 for dot variant) |
| `color` | `string` | `muted` | Color of the indicator icon |
### SubMenu
| prop | type | default | description |
| --------------- | ------------------------- | ------- | -------------------------------------------------------- |
| `children` | `React.ReactNode` | - | The sub-menu content (trigger, content, and other items) |
| `isOpen` | `boolean` | - | Controlled open state of the sub-menu |
| `isDefaultOpen` | `boolean` | - | Open state when initially rendered (uncontrolled) |
| `isDisabled` | `boolean` | `false` | Whether the sub-menu is disabled |
| `className` | `string` | - | Additional CSS class for the root container |
| `animation` | `SubMenuRootAnimation` | - | Animation configuration for the sub-menu |
| `onOpenChange` | `(open: boolean) => void` | - | Callback fired when the sub-menu open state changes |
| `...ViewProps` | `ViewProps` | - | All standard React Native View props are supported |
##### SubMenuRootAnimation
Animation configuration for the SubMenu root component. Can be:
* `"disable-all"`: Disable all animations including children
* `false` or `"disabled"`: Disable only root animations
* `true` or `undefined`: Use default animations
* `object`: Custom animation configuration
| prop | type | default | description |
| ------------------------------- | ----------------------- | ------------------------------------------- | ----------------------------------------------- |
| `state` | `'disabled' \| boolean` | - | Disable animations while customizing properties |
| `rootContent.marginHorizontal` | `number` | `-16` | Margin horizontal when sub-menu is open |
| `rootContent.marginVertical` | `number` | `-16` | Margin vertical when sub-menu is open |
| `rootContent.paddingHorizontal` | `number` | `6` | Padding horizontal when sub-menu is open |
| `rootContent.paddingTop` | `number` | `12` | Padding top when sub-menu is open |
| `rootContent.springConfig` | `WithSpringConfig` | `{ damping: 100, stiffness: 950, mass: 3 }` | Spring configuration for expand/collapse |
#### SubMenu.Trigger
| prop | type | default | description |
| ------------------- | ----------------- | ------- | ------------------------------------------------------- |
| `children` | `React.ReactNode` | - | The trigger content (title, icons, indicator, etc.) |
| `textValue` | `string` | - | Accessible text value announced by screen readers |
| `className` | `string` | - | Additional CSS class for the trigger |
| `isDisabled` | `boolean` | `false` | Whether the trigger is disabled |
| `asChild` | `boolean` | - | Render as child element using Slot pattern |
| `...PressableProps` | `PressableProps` | - | All standard React Native Pressable props are supported |
#### SubMenu.TriggerIndicator
Animated indicator icon that rotates when the submenu opens/closes. Defaults to a chevron-right icon.
| prop | type | default | description |
| ----------------------- | ---------------------------------- | ------- | ------------------------------------------------------------ |
| `children` | `React.ReactNode` | - | Custom indicator content (replaces default chevron) |
| `className` | `string` | - | Additional CSS class for the indicator |
| `iconProps` | `SubMenuTriggerIndicatorIconProps` | - | Icon configuration for the default chevron |
| `animation` | `SubMenuTriggerIndicatorAnimation` | - | Animation configuration for indicator rotation |
| `isAnimatedStyleActive` | `boolean` | `true` | Whether animated styles (react-native-reanimated) are active |
| `...ViewProps` | `ViewProps` | - | All standard React Native View props are supported |
##### SubMenuTriggerIndicatorIconProps
| prop | type | default | description |
| ------- | -------- | ------- | --------------------------- |
| `size` | `number` | `14` | Size of the indicator icon |
| `color` | `string` | `muted` | Color of the indicator icon |
##### SubMenuTriggerIndicatorAnimation
Animation configuration for the trigger indicator rotation. Can be:
* `false` or `"disabled"`: Disable all animations
* `true` or `undefined`: Use default animations
* `object`: Custom animation configuration
| prop | type | default | description |
| ----------------------- | ----------------------- | -------------------------------------------- | ------------------------------------------------- |
| `state` | `'disabled' \| boolean` | - | Disable animations while customizing properties |
| `rotation.value` | `[number, number]` | `[0, 90]` | Rotation values \[collapsed, expanded] in degrees |
| `rotation.springConfig` | `WithSpringConfig` | `{ damping: 140, stiffness: 1000, mass: 4 }` | Spring configuration for rotation |
#### SubMenu.Content
| prop | type | default | description |
| ------------------- | ----------------- | ------- | ------------------------------------------------------- |
| `children` | `React.ReactNode` | - | The submenu items (Menu.Item, Menu.Group, etc.) |
| `className` | `string` | - | Additional CSS class for the content container |
| `...PressableProps` | `PressableProps` | - | All standard React Native Pressable props are supported |
## Hooks
### useMenu
Hook to access the menu root context. Must be used within a `Menu` component.
```tsx
import { useMenu } from 'heroui-native';
const { isOpen, onOpenChange, presentation, isDisabled } = useMenu();
```
#### Returns
| property | type | description |
| -------------- | ----------------------------- | --------------------------------------- |
| `isOpen` | `boolean` | Whether the menu is currently open |
| `onOpenChange` | `(open: boolean) => void` | Callback to change the open state |
| `presentation` | `'popover' \| 'bottom-sheet'` | Current presentation mode |
| `isDisabled` | `boolean \| undefined` | Whether the menu is disabled |
| `nativeID` | `string` | Unique identifier for the menu instance |
### useMenuItem
Hook to access the menu item context. Must be used within a `Menu.Item` component.
```tsx
import { useMenuItem } from 'heroui-native';
const { id, isSelected, isDisabled, variant } = useMenuItem();
```
#### Returns
| property | type | description |
| ------------ | ----------------------- | -------------------------------------- |
| `id` | `MenuKey \| undefined` | Item identifier |
| `isSelected` | `boolean` | Whether the item is currently selected |
| `isDisabled` | `boolean` | Whether the item is disabled |
| `variant` | `'default' \| 'danger'` | Visual variant of the item |
### useMenuAnimation
Hook to access the menu animation context. Must be used within a `Menu` component.
```tsx
import { useMenuAnimation } from 'heroui-native';
const { progress, isDragging } = useMenuAnimation();
```
#### Returns
| property | type | description |
| ------------ | ---------------------- | --------------------------------------------------------- |
| `progress` | `SharedValue` | Animation progress shared value (0=idle, 1=open, 2=close) |
| `isDragging` | `SharedValue` | Whether the bottom sheet is currently being dragged |
### useSubMenu
Hook to access the sub-menu context. Must be used within a `SubMenu` component.
```tsx
import { useSubMenu } from 'heroui-native';
const { isOpen, onOpenChange, isDisabled } = useSubMenu();
```
#### Returns
| property | type | description |
| -------------- | ------------------------- | ------------------------------------------- |
| `isOpen` | `boolean` | Whether the sub-menu is currently open |
| `onOpenChange` | `(open: boolean) => void` | Callback to change the open state |
| `isDisabled` | `boolean` | Whether the sub-menu is disabled |
| `nativeID` | `string` | Unique identifier for the sub-menu instance |
# TagGroup
**Category**: native
**URL**: https://v3.heroui.com/docs/native/components/tag-group
**Source**: https://raw.githubusercontent.com/heroui-inc/heroui/refs/heads/v3/apps/docs/content/docs/native/components/(collections)/tag-group.mdx
> A compound component for displaying and managing selectable tags with optional removal.
## Import
```tsx
import { TagGroup } from 'heroui-native';
```
## Anatomy
```tsx
...
```
* **TagGroup**: Main container that manages tag selection state, disabled keys, and remove functionality. Provides size and variant context to all child components.
* **TagGroup.List**: Container for rendering the list of tags with optional empty state rendering.
* **TagGroup.Item**: Individual tag within the group. Supports string children (auto-wrapped in TagGroup.ItemLabel), render function children, or custom layouts.
* **TagGroup.ItemLabel**: Text label for the tag. Automatically rendered when string children are provided, or can be used explicitly.
* **TagGroup.ItemRemoveButton**: Remove button for the tag. Must be placed explicitly when removal is needed. Only functional when `onRemove` is provided to TagGroup.
## Usage
### Basic Usage
Display a simple tag group with selectable items.
```tsx
NewsTravelGaming
```
### Single Selection Mode
Allow only one tag to be selected at a time.
```tsx
NewsTravelGaming
```
### Multiple Selection Mode
Allow multiple tags to be selected simultaneously.
```tsx
NewsTravelGaming
```
### Controlled Selection
Control selection state with `selectedKeys` and `onSelectionChange`.
```tsx
const [selected, setSelected] = useState(new Set(['news']));
NewsTravelGaming;
```
### Variants
Apply different visual variants to the tags.
```tsx
NewsTravelNewsTravel
```
### Sizes
Control the size of all tags in the group.
```tsx
NewsNewsNews
```
### With Remove Button
Add remove buttons to tags by providing `onRemove` and placing `TagGroup.ItemRemoveButton` in each item.
```tsx
const [tags, setTags] = useState([
{ id: 'news', name: 'News' },
{ id: 'travel', name: 'Travel' },
]);
const onRemove = (keys) => {
setTags((prev) => prev.filter((tag) => !keys.has(tag.id)));
};
{tags.map((tag) => (
{tag.name}
))}
;
```
### Render Function Children
Use a render function to access `isSelected` and `isDisabled` for custom layouts.
```tsx
{({ isSelected }) => (
<>
News
>
)}
```
### Empty State
Render custom content when the list has no tags.
```tsx
(
No categories found
)}
>
{tags.map((tag) => (
{tag.name}
))}
```
### Disabled Tags
Disable individual tags or the entire group.
```tsx
NewsTravel
Gaming
```
## Example
```tsx
import { TagGroup, Label, Description, FieldError } from 'heroui-native';
import { useState, useMemo } from 'react';
import { View } from 'react-native';
export default function TagGroupExample() {
const [selected, setSelected] = useState(new Set());
const isInvalid = useMemo(
() => Array.from(selected).length === 0,
[selected]
);
return (
LaundryFitness centerParkingSwimming poolBreakfast
{`Selected: ${Array.from(selected).join(', ')}`}
Please select at least one category
);
}
```
You can find more examples in the [GitHub repository](https://github.com/heroui-inc/heroui-native/blob/rc/example/src/app/\(home\)/components/tag-group.tsx).
## API Reference
### TagGroup
| prop | type | default | description |
| --------------------- | ---------------------------------- | ----------- | ---------------------------------------------------------------- |
| `children` | `React.ReactNode` | - | Child elements to render inside the tag group |
| `size` | `'sm' \| 'md' \| 'lg'` | `'md'` | Size of all tags in the group |
| `variant` | `'default' \| 'surface'` | `'default'` | Visual variant of all tags in the group |
| `selectionMode` | `'none' \| 'single' \| 'multiple'` | `'none'` | The type of selection allowed in the tag group |
| `selectedKeys` | `Iterable` | - | The currently selected keys (controlled) |
| `defaultSelectedKeys` | `Iterable` | - | The initial selected keys (uncontrolled) |
| `disabledKeys` | `Iterable` | - | Keys of tags that should be disabled |
| `isDisabled` | `boolean` | `false` | Whether the entire tag group is disabled |
| `isInvalid` | `boolean` | `false` | Whether the tag group is in an invalid state |
| `isRequired` | `boolean` | `false` | Whether the tag group is required |
| `className` | `string` | - | Additional CSS classes for the tag group container |
| `style` | `StyleProp` | - | Additional styles for the tag group container |
| `animation` | `"disable-all" \| undefined` | - | Use `"disable-all"` to disable all animations including children |
| `onSelectionChange` | `(keys: Set) => void` | - | Handler called when the selection changes |
| `onRemove` | `(keys: Set) => void` | - | Handler called when tags are removed |
| `...ViewProps` | `ViewProps` | - | All standard React Native View props are supported |
#### TagKey
`string | number` — Key type for identifying tags within a TagGroup.
#### Animation
Use `animation="disable-all"` to disable all animations including children. Omit or use `undefined` for default animations.
### TagGroup.List
| prop | type | default | description |
| ------------------ | ----------------------- | ------- | -------------------------------------------------- |
| `children` | `React.ReactNode` | - | Child elements to render inside the list |
| `className` | `string` | - | Additional CSS classes for the list container |
| `style` | `StyleProp` | - | Additional styles for the list container |
| `renderEmptyState` | `() => React.ReactNode` | - | Function to render when the list has no tags |
| `...ViewProps` | `ViewProps` | - | All standard React Native View props are supported |
### TagGroup.Item
| prop | type | default | description |
| ------------------- | ----------------------------------------------------------------------- | ------- | ---------------------------------------------------------------------------- |
| `children` | `React.ReactNode \| ((renderProps: TagRenderProps) => React.ReactNode)` | - | Tag content: string, elements, or a render function receiving TagRenderProps |
| `id` | `TagKey` | - | Unique identifier for this tag |
| `isDisabled` | `boolean` | - | Whether this specific tag is disabled |
| `className` | `string` | - | Additional CSS classes for the tag |
| `style` | `StyleProp` | - | Additional styles for the tag |
| `...PressableProps` | `PressableProps` | - | All standard React Native Pressable props are supported |
#### TagRenderProps
| prop | type | description |
| ------------ | --------- | --------------------------------------------------------------------------- |
| `isSelected` | `boolean` | Whether the tag is currently selected |
| `isDisabled` | `boolean` | Whether the tag is disabled (merged from root, disabledKeys, and item prop) |
### TagGroup.ItemLabel
| prop | type | default | description |
| -------------- | ----------------- | ------- | -------------------------------------------------- |
| `children` | `React.ReactNode` | - | Text content to render |
| `className` | `string` | - | Additional CSS classes for the label |
| `...TextProps` | `TextProps` | - | All standard React Native Text props are supported |
### TagGroup.ItemRemoveButton
| prop | type | default | description |
| ------------------- | -------------------------- | ------- | ---------------------------------------------------------------------------------------- |
| `children` | `React.ReactNode` | - | Custom icon or content for the remove button. Defaults to close icon when omitted |
| `className` | `string` | - | Additional CSS classes for the remove button |
| `iconProps` | `TagRemoveButtonIconProps` | - | Props for customizing the default close icon. Only applies when no children are provided |
| `hitSlop` | `number` | `8` | Extends the touchable area |
| `...PressableProps` | `PressableProps` | - | All standard React Native Pressable props are supported |
#### TagRemoveButtonIconProps
| prop | type | default | description |
| ------- | -------- | ------- | ----------------- |
| `size` | `number` | `12` | Size of the icon |
| `color` | `string` | - | Color of the icon |
## Hooks
### useTagGroup
Hook to access the tag group root context. Must be used within a `TagGroup` component.
```tsx
import { useTagGroup } from 'heroui-native';
const {
selectedKeys,
disabledKeys,
selectionMode,
onSelectionChange,
onRemove,
isDisabled,
isInvalid,
isRequired,
} = useTagGroup();
```
#### Returns
| property | type | description |
| ------------------- | -------------------------------------------- | ---------------------------------------------- |
| `selectionMode` | `'none' \| 'single' \| 'multiple'` | The type of selection allowed in the tag group |
| `selectedKeys` | `Set` | Currently selected tag keys |
| `disabledKeys` | `Set` | Keys of disabled tags |
| `onSelectionChange` | `(keys: Set) => void` | Callback when selection changes |
| `onRemove` | `((keys: Set) => void) \| undefined` | Callback when tags are removed |
| `isDisabled` | `boolean` | Whether the entire tag group is disabled |
| `isInvalid` | `boolean` | Whether the tag group is in an invalid state |
| `isRequired` | `boolean` | Whether the tag group is required |
### useTagGroupItem
Hook to access the tag item context. Must be used within a `TagGroup.Item` component.
```tsx
import { useTagGroupItem } from 'heroui-native';
const { id, isSelected, isDisabled, allowsRemoving } = useTagGroupItem();
```
#### Returns
| property | type | description |
| ---------------- | --------- | --------------------------------------------------------------------------- |
| `id` | `TagKey` | Unique identifier for this tag |
| `isSelected` | `boolean` | Whether the tag is currently selected |
| `isDisabled` | `boolean` | Whether the tag is disabled |
| `allowsRemoving` | `boolean` | Whether the tag can be removed (true when onRemove is provided to TagGroup) |
# Slider
**Category**: native
**URL**: https://v3.heroui.com/docs/native/components/slider
**Source**: https://raw.githubusercontent.com/heroui-inc/heroui/refs/heads/v3/apps/docs/content/docs/native/components/(controls)/slider.mdx
> A draggable input for selecting a value or range within a bounded interval.
## Import
```tsx
import { Slider } from 'heroui-native';
```
## Anatomy
```tsx
```
* **Slider**: Main container that manages slider value state, orientation, and provides context to all sub-components. Supports single value and range modes.
* **Slider.Output**: Optional display of the current value(s). Supports render functions for custom formatting. Shows a formatted value label by default.
* **Slider.Track**: Sizing container for Fill and Thumb elements. Reports its layout size for position calculations. Supports tap-to-position and render-function children for dynamic content (e.g. multiple thumbs for range sliders).
* **Slider.Fill**: Responsive fill bar that stretches the full cross-axis of the Track. Only the main-axis position and size are computed.
* **Slider.Thumb**: Draggable thumb element using react-native-gesture-handler. Centered on the cross-axis by the Track layout. Animates scale on press via react-native-reanimated. Each thumb gets `role="slider"` with full `accessibilityValue`.
## Usage
### Basic Usage
The Slider component uses compound parts to create a draggable value input.
```tsx
```
### With Label and Output
Display a label alongside the current value output.
```tsx
```
### Vertical Orientation
Render the slider vertically by setting `orientation` to `"vertical"`.
```tsx
```
### Range Slider
Pass an array as the value and use a render function on `Slider.Track` to create multiple thumbs.
```tsx
{({ state }) => (
<>
{state.values.map((_, i) => (
))}
>
)}
```
### Controlled Value
Use `value` and `onChange` for controlled mode. The `onChangeEnd` callback fires when a drag or tap interaction completes.
```tsx
const [volume, setVolume] = useState(50);
save(v)}>
;
```
### Custom Styling
Apply custom styles using `className`, `classNames`, or `styles` on the thumb and other sub-components.
```tsx
```
### Disabled
Disable the entire slider to prevent interaction.
```tsx
```
## Example
```tsx
import { Label, Slider } from 'heroui-native';
import { useState } from 'react';
import { View, Text } from 'react-native';
export default function SliderExample() {
const [price, setPrice] = useState([200, 800]);
return (
{({ state }) => (
<>
{state.values.map((_, i) => (
))}
>
)}
);
}
```
You can find more examples in the [GitHub repository](https://github.com/heroui-inc/heroui-native/blob/rc/example/src/app/\(home\)/components/slider.tsx).
## API Reference
### Slider
| prop | type | default | description |
| --------------- | ------------------------------------- | -------------- | --------------------------------------------------------------- |
| `children` | `React.ReactNode` | - | Children elements to be rendered inside the slider |
| `value` | `number \| number[]` | - | Current slider value (controlled mode) |
| `defaultValue` | `number \| number[]` | `0` | Default slider value (uncontrolled mode) |
| `minValue` | `number` | `0` | Minimum value of the slider |
| `maxValue` | `number` | `100` | Maximum value of the slider |
| `step` | `number` | `1` | Step increment for the slider |
| `formatOptions` | `Intl.NumberFormatOptions` | - | Number format options for value label formatting |
| `orientation` | `'horizontal' \| 'vertical'` | `'horizontal'` | Orientation of the slider |
| `isDisabled` | `boolean` | `false` | Whether the slider is disabled |
| `className` | `string` | - | Additional CSS classes |
| `animation` | `AnimationRootDisableAll` | - | Animation configuration for the slider |
| `onChange` | `(value: number \| number[]) => void` | - | Callback fired when the slider value changes during interaction |
| `onChangeEnd` | `(value: number \| number[]) => void` | - | Callback fired when an interaction completes (drag end or tap) |
| `...ViewProps` | `ViewProps` | - | All standard React Native View props are supported |
#### AnimationRootDisableAll
Animation configuration for the slider root component. Can be:
* `"disable-all"`: Disable all animations including children
* `undefined`: Use default animations
### Slider.Output
| prop | type | default | description |
| -------------- | -------------------------------------------------------------------- | ------- | ------------------------------------------------------------------------------------------- |
| `children` | `React.ReactNode \| ((props: SliderRenderProps) => React.ReactNode)` | - | Custom content or render function receiving slider state. Defaults to formatted value label |
| `className` | `string` | - | Additional CSS classes |
| `...ViewProps` | `ViewProps` | - | All standard React Native View props are supported |
#### SliderRenderProps
| prop | type | description |
| ------------- | ------------------- | ------------------------------ |
| `state` | `SliderState` | Current slider state |
| `orientation` | `SliderOrientation` | Orientation of the slider |
| `isDisabled` | `boolean` | Whether the slider is disabled |
#### SliderState
| prop | type | description |
| -------------------- | --------------------------- | ---------------------------------------------- |
| `values` | `number[]` | Current slider value(s) by thumb index |
| `getThumbValueLabel` | `(index: number) => string` | Returns the formatted string label for a thumb |
### Slider.Track
| prop | type | default | description |
| -------------- | -------------------------------------------------------------------- | ------- | ----------------------------------------------------------------------------- |
| `children` | `React.ReactNode \| ((props: SliderRenderProps) => React.ReactNode)` | - | Content or render function receiving slider state for dynamic thumb rendering |
| `className` | `string` | - | Additional CSS classes |
| `hitSlop` | `number` | `8` | Extra touch area around the track |
| `...ViewProps` | `ViewProps` | - | All standard React Native View props are supported |
### Slider.Fill
| prop | type | default | description |
| -------------- | ----------- | ------- | -------------------------------------------------- |
| `className` | `string` | - | Additional CSS classes |
| `...ViewProps` | `ViewProps` | - | All standard React Native View props are supported |
### Slider.Thumb
| prop | type | default | description |
| -------------- | ---------------------------------------- | ------- | -------------------------------------------------- |
| `children` | `React.ReactNode` | - | Custom thumb content. Defaults to an animated knob |
| `index` | `number` | `0` | Index of this thumb within the slider |
| `isDisabled` | `boolean` | - | Whether this individual thumb is disabled |
| `className` | `string` | - | Additional CSS classes for the thumb container |
| `classNames` | `ElementSlots` | - | Additional CSS classes for thumb slots |
| `styles` | `Partial>` | - | Inline styles for thumb slots |
| `hitSlop` | `number` | `12` | Extra touch area around the thumb |
| `animation` | `SliderThumbAnimation` | - | Animation configuration for the thumb knob |
| `...ViewProps` | `ViewProps` | - | All standard React Native View props are supported |
#### ElementSlots\
| prop | type | description |
| ---------------- | -------- | ----------------------------------------------- |
| `thumbContainer` | `string` | Custom class name for the outer thumb container |
| `thumbKnob` | `string` | Custom class name for the inner thumb knob |
#### styles
| prop | type | description |
| ---------------- | ----------- | ------------------------------------ |
| `thumbContainer` | `ViewStyle` | Styles for the outer thumb container |
| `thumbKnob` | `ViewStyle` | Styles for the inner thumb knob |
#### SliderThumbAnimation
Animation configuration for the thumb knob scale effect. Can be:
* `false` or `"disabled"`: Disable thumb animation
* `undefined`: Use default animations
* `object`: Custom scale animation configuration
| prop | type | default | description |
| -------------------- | ------------------ | -------------------------------------------- | ----------------------------------------------- |
| `scale.value` | `[number, number]` | `[1, 0.9]` | Scale values \[idle, dragging] |
| `scale.springConfig` | `WithSpringConfig` | `{ damping: 15, stiffness: 200, mass: 0.5 }` | Spring animation configuration for scale effect |
## Hooks
### useSlider
Hook to access the slider context. Must be used within a `Slider` component.
```tsx
import { useSlider } from 'heroui-native';
const { values, orientation, isDisabled, getThumbValueLabel } = useSlider();
```
#### Returns
| property | type | description |
| -------------------- | -------------------------------------------- | -------------------------------------------------------------- |
| `values` | `number[]` | Current slider values (one per thumb) |
| `minValue` | `number` | Minimum value of the slider |
| `maxValue` | `number` | Maximum value of the slider |
| `step` | `number` | Step increment |
| `orientation` | `'horizontal' \| 'vertical'` | Current orientation |
| `isDisabled` | `boolean` | Whether the slider is disabled |
| `formatOptions` | `Intl.NumberFormatOptions \| undefined` | Number format options for labels |
| `getThumbPercent` | `(index: number) => number` | Returns the percentage position (0–1) for a given thumb index |
| `getThumbValueLabel` | `(index: number) => string` | Returns the formatted label for a given thumb index |
| `getThumbMinValue` | `(index: number) => number` | Returns the minimum allowed value for a thumb |
| `getThumbMaxValue` | `(index: number) => number` | Returns the maximum allowed value for a thumb |
| `updateValue` | `(index: number, newValue: number) => void` | Updates a thumb value by index |
| `isThumbDragging` | `(index: number) => boolean` | Returns whether a given thumb is currently being dragged |
| `setThumbDragging` | `(index: number, dragging: boolean) => void` | Sets the dragging state of a thumb |
| `trackSize` | `number` | Track layout width (horizontal) or height (vertical) in pixels |
| `thumbSize` | `number` | Measured thumb size (main-axis dimension) in pixels |
# Switch
**Category**: native
**URL**: https://v3.heroui.com/docs/native/components/switch
**Source**: https://raw.githubusercontent.com/heroui-inc/heroui/refs/heads/v3/apps/docs/content/docs/native/components/(controls)/switch.mdx
> A toggle control that allows users to switch between on and off states.
## Import
```tsx
import { Switch } from 'heroui-native';
```
## Anatomy
```tsx
.........
```
* **Switch**: Main container that handles toggle state and user interaction. Renders default thumb if no children provided. Animates scale (on press) and background color based on selection state. Acts as a pressable area for toggling.
* **Switch.Thumb**: Optional sliding thumb element that moves between positions. Uses spring animation for smooth transitions. Can contain custom content like icons or be customized with different styles and animations.
* **Switch.StartContent**: Optional content displayed on the left side of the switch. Typically used for icons or text that appear when switch is off. Positioned absolutely within the switch container.
* **Switch.EndContent**: Optional content displayed on the right side of the switch. Typically used for icons or text that appear when switch is on. Positioned absolutely within the switch container.
## Usage
### Basic Usage
The Switch component renders with default thumb if no children provided.
```tsx
```
### With Custom Thumb
Replace the default thumb with custom content using the Thumb component.
```tsx
...
```
### With Start and End Content
Add icons or text that appear on each side of the switch.
```tsx
......
```
### With Render Function
Use render functions for dynamic content based on switch state.
```tsx
{({ isSelected, isDisabled }) => (
<>
{({ isSelected }) => (isSelected ? : )}
>
)}
```
### With Custom Animations
Customize animations for the switch root and thumb components.
```tsx
```
### Disable Animations
Disable animations entirely or only for specific components.
```tsx
{
/* Disable all animations including children */
}
;
{
/* Disable only root animations, thumb can still animate */
}
;
```
## Example
```tsx
import { Switch } from 'heroui-native';
import { Ionicons } from '@expo/vector-icons';
import React from 'react';
import { View } from 'react-native';
import Animated, { ZoomIn } from 'react-native-reanimated';
export default function SwitchExample() {
const [darkMode, setDarkMode] = React.useState(false);
return (
{darkMode && (
)}
{!darkMode && (
)}
);
}
```
You can find more examples in the [GitHub repository](https://github.com/heroui-inc/heroui-native/blob/rc/example/src/app/\(home\)/components/switch.tsx).
## API Reference
### Switch
| prop | type | default | description |
| --------------------------- | -------------------------------------------------------------------- | ----------- | ------------------------------------------------------------ |
| `children` | `React.ReactNode \| ((props: SwitchRenderProps) => React.ReactNode)` | `undefined` | Content to render inside the switch, or a render function |
| `isSelected` | `boolean` | `undefined` | Whether the switch is currently selected |
| `isDisabled` | `boolean` | `false` | Whether the switch is disabled and cannot be interacted with |
| `className` | `string` | `undefined` | Custom class name for the switch |
| `animation` | `SwitchRootAnimation` | - | Animation configuration |
| `isAnimatedStyleActive` | `boolean` | `true` | Whether animated styles (react-native-reanimated) are active |
| `onSelectedChange` | `(isSelected: boolean) => void` | - | Callback fired when the switch selection state changes |
| `...AnimatedPressableProps` | `AnimatedProps` | - | All React Native Reanimated Pressable props are supported |
#### SwitchRenderProps
| prop | type | description |
| ------------ | --------- | ------------------------------ |
| `isSelected` | `boolean` | Whether the switch is selected |
| `isDisabled` | `boolean` | Whether the switch is disabled |
#### SwitchRootAnimation
Animation configuration for Switch component. Can be:
* `false` or `"disabled"`: Disable only root animations
* `"disable-all"`: Disable all animations including children
* `true` or `undefined`: Use default animations
* `object`: Custom animation configuration
| prop | type | default | description |
| ------------------------------ | ---------------------------------------- | -------------------------------------------------------------- | ----------------------------------------------- |
| `state` | `'disabled' \| 'disable-all' \| boolean` | - | Disable animations while customizing properties |
| `scale.value` | `[number, number]` | `[1, 0.96]` | Scale values \[unpressed, pressed] |
| `scale.timingConfig` | `WithTimingConfig` | `{ duration: 150 }` | Animation timing configuration |
| `backgroundColor.value` | `[string, string]` | Uses theme colors | Background color values \[unselected, selected] |
| `backgroundColor.timingConfig` | `WithTimingConfig` | `{ duration: 175, easing: Easing.bezier(0.25, 0.1, 0.25, 1) }` | Animation timing configuration |
### Switch.Thumb
| prop | type | default | description |
| ----------------------- | -------------------------------------------------------------------- | ----------- | ------------------------------------------------------------ |
| `children` | `React.ReactNode \| ((props: SwitchRenderProps) => React.ReactNode)` | `undefined` | Content to render inside the thumb, or a render function |
| `className` | `string` | `undefined` | Custom class name for the thumb element |
| `animation` | `SwitchThumbAnimation` | - | Animation configuration |
| `isAnimatedStyleActive` | `boolean` | `true` | Whether animated styles (react-native-reanimated) are active |
| `...ViewProps` | `ViewProps` | - | All standard React Native View props are supported |
#### SwitchThumbAnimation
Animation configuration for Switch.Thumb component. Can be:
* `false` or `"disabled"`: Disable all animations
* `true` or `undefined`: Use default animations
* `object`: Custom animation configuration
| prop | type | default | description |
| ------------------------------ | ----------------------- | -------------------------------------------------------------- | ----------------------------------------------------------------------- |
| `state` | `'disabled' \| boolean` | - | Disable animations while customizing properties |
| `left.value` | `number` | `2` | Offset value from the edges (left when unselected, right when selected) |
| `left.springConfig` | `WithSpringConfig` | `{ damping: 120, stiffness: 1600, mass: 2 }` | Spring animation configuration for thumb position |
| `backgroundColor.value` | `[string, string]` | `['white', theme accent-foreground color]` | Background color values \[unselected, selected] |
| `backgroundColor.timingConfig` | `WithTimingConfig` | `{ duration: 175, easing: Easing.bezier(0.25, 0.1, 0.25, 1) }` | Animation timing configuration |
### Switch.StartContent
| prop | type | default | description |
| -------------- | ----------------- | ----------- | -------------------------------------------------- |
| `children` | `React.ReactNode` | `undefined` | Content to render inside the switch content |
| `className` | `string` | `undefined` | Custom class name for the content element |
| `...ViewProps` | `ViewProps` | - | All standard React Native View props are supported |
### Switch.EndContent
| prop | type | default | description |
| -------------- | ----------------- | ----------- | -------------------------------------------------- |
| `children` | `React.ReactNode` | `undefined` | Content to render inside the switch content |
| `className` | `string` | `undefined` | Custom class name for the content element |
| `...ViewProps` | `ViewProps` | - | All standard React Native View props are supported |
## Hooks
### useSwitch
A hook that provides access to the Switch context. This is useful when building custom switch components or when you need to access switch state in child components.
**Returns:**
| Property | Type | Description |
| ------------ | --------- | ------------------------------ |
| `isSelected` | `boolean` | Whether the switch is selected |
| `isDisabled` | `boolean` | Whether the switch is disabled |
**Example:**
```tsx
import { useSwitch } from 'heroui-native';
function CustomSwitchContent() {
const { isSelected, isDisabled } = useSwitch();
return (
Status: {isSelected ? 'On' : 'Off'}
{isDisabled && Disabled}
);
}
// Usage
;
```
## Special Notes
### Border Styling
If you need to apply a border to the switch root, use the `outline` style properties instead of `border`. This ensures the border doesn't affect the internal layout calculations for the thumb position:
```tsx
```
Using `outline` keeps the border visual without impacting the switch's internal width calculations, ensuring the thumb animates correctly.
### Integration with ControlField
The Switch component integrates seamlessly with ControlField for press state sharing:
```tsx
import { Description, ControlField, Label } from 'heroui-native';
Receive push notifications
```
When wrapped in ControlField, the Switch will automatically respond to press events on the entire ControlField container, creating a larger touch target and better user experience.
# Chip
**Category**: native
**URL**: https://v3.heroui.com/docs/native/components/chip
**Source**: https://raw.githubusercontent.com/heroui-inc/heroui/refs/heads/v3/apps/docs/content/docs/native/components/(data-display)/chip.mdx
> Displays a compact element in a capsule shape.
## Import
```tsx
import { Chip } from 'heroui-native';
```
## Anatomy
```tsx
...
```
* **Chip**: Main container that displays a compact element
* **Chip.Label**: Text content of the chip
## Usage
### Basic Usage
The Chip component displays text or custom content in a capsule shape.
```tsx
Basic Chip
```
### Sizes
Control the chip size with the `size` prop.
```tsx
SmallMediumLarge
```
### Variants
Choose between different visual styles with the `variant` prop.
```tsx
PrimarySecondaryTertiarySoft
```
### Colors
Apply different color themes with the `color` prop.
```tsx
AccentDefaultSuccessWarningDanger
```
### With Icons
Add icons or custom content alongside text using compound components.
```tsx
FeaturedClose
```
### Custom Styling
Apply custom styles using className or style props.
```tsx
Custom
```
### Disable All Animations
Disable all animations including children by using the `"disable-all"` value for the `animation` prop.
```tsx
{
/* Disable all animations including children */
}
No Animations;
```
## Example
```tsx
import { Chip } from 'heroui-native';
import { View, Text } from 'react-native';
import { Ionicons } from '@expo/vector-icons';
export default function ChipExample() {
return (
SmallMediumLarge
Primary
SuccessPremiumRemoveCustom
);
}
```
You can find more examples in the [GitHub repository](https://github.com/heroui-inc/heroui-native/blob/rc/example/src/app/\(home\)/components/chip.tsx).
## API Reference
### Chip
| prop | type | default | description |
| ------------------- | ------------------------------------------------------------- | ----------- | ----------------------------------------------------------------------------------------- |
| `children` | `React.ReactNode` | - | Content to render inside the chip |
| `size` | `'sm' \| 'md' \| 'lg'` | `'md'` | Size of the chip |
| `variant` | `'primary' \| 'secondary' \| 'tertiary' \| 'soft'` | `'primary'` | Visual variant of the chip |
| `color` | `'accent' \| 'default' \| 'success' \| 'warning' \| 'danger'` | `'accent'` | Color theme of the chip |
| `className` | `string` | - | Additional CSS classes to apply |
| `animation` | `"disable-all" \| undefined` | `undefined` | Animation configuration. Use `"disable-all"` to disable all animations including children |
| `...PressableProps` | `PressableProps` | - | All Pressable props are supported |
### Chip.Label
| prop | type | default | description |
| -------------- | ----------------- | ------- | -------------------------------------- |
| `children` | `React.ReactNode` | - | Text or content to render as the label |
| `className` | `string` | - | Additional CSS classes to apply |
| `...TextProps` | `TextProps` | - | All standard Text props are supported |
## Hooks
### useChip
Hook to access the Chip context values. Returns the chip's size, variant, and color.
```tsx
import { useChip } from 'heroui-native';
const { size, variant, color } = useChip();
```
#### Return Value
| property | type | description |
| --------- | ------------------------------------------------------------- | -------------------------- |
| `size` | `'sm' \| 'md' \| 'lg'` | Size of the chip |
| `variant` | `'primary' \| 'secondary' \| 'tertiary' \| 'soft'` | Visual variant of the chip |
| `color` | `'accent' \| 'default' \| 'success' \| 'warning' \| 'danger'` | Color theme of the chip |
**Note:** This hook must be used within a `Chip` component. It will throw an error if called outside of the chip context.
# Alert
**Category**: native
**URL**: https://v3.heroui.com/docs/native/components/alert
**Source**: https://raw.githubusercontent.com/heroui-inc/heroui/refs/heads/v3/apps/docs/content/docs/native/components/(feedback)/alert.mdx
> Displays important messages and notifications to users with status indicators.
## Import
```tsx
import { Alert } from 'heroui-native';
```
## Anatomy
```tsx
......
```
* **Alert**: Main container with `role="alert"` and status-based styling. Provides status context to sub-components via a primitive context.
* **Alert.Indicator**: Renders a status-appropriate icon by default. Accepts custom children to override the default icon. Supports `iconProps` for customising size and color.
* **Alert.Content**: Wrapper for the title and description. Provides layout structure for text content.
* **Alert.Title**: Heading text with status-based color. Connected to root via `aria-labelledby`.
* **Alert.Description**: Body text rendered with muted color. Connected to root via `aria-describedby`.
## Usage
### Basic Usage
The Alert component uses compound parts to display a notification with an icon, title, and description.
```tsx
New features available
Check out our latest updates including dark mode support and improved
accessibility features.
```
### Status Variants
Set the `status` prop to control the icon and title color. Available statuses are `default`, `accent`, `success`, `warning`, and `danger`.
```tsx
Success...Scheduled maintenance...Unable to connect...
```
### Title Only
Omit `Alert.Description` for a compact single-line alert.
```tsx
Profile updated successfully
```
### With Action Buttons
Place additional elements like buttons alongside the content.
```tsx
Update available
A new version of the application is available.
```
### Custom Indicator
Replace the default status icon by passing custom children to `Alert.Indicator`.
```tsx
Processing your requestPlease wait while we sync your data.
```
### Custom Styling
Apply custom styles using the `className` prop on the root and compound parts.
```tsx
......
```
## Example
```tsx
import { Alert, Button, CloseButton } from 'heroui-native';
import { View } from 'react-native';
export default function AlertExample() {
return (
Update available
A new version of the application is available. Please refresh to get
the latest features and bug fixes.
Unable to connect to server
Unable to connect to the server. Check your internet connection and
try again.
Profile updated successfully
);
}
```
You can find more examples in the [GitHub repository](https://github.com/heroui-inc/heroui-native/blob/rc/example/src/app/\(home\)/components/alert.tsx).
## API Reference
### Alert
| prop | type | default | description |
| -------------- | ------------------------------------------------------------- | ----------- | ----------------------------------------------------------------- |
| `children` | `React.ReactNode` | - | Children elements to render inside the alert |
| `status` | `'default' \| 'accent' \| 'success' \| 'warning' \| 'danger'` | `'default'` | Status controlling the icon and color treatment |
| `id` | `string \| number` | - | Unique identifier for the alert. Auto-generated when not provided |
| `className` | `string` | - | Additional CSS classes |
| `style` | `ViewStyle` | - | Additional styles applied to the root container |
| `...ViewProps` | `ViewProps` | - | All standard React Native View props are supported |
### Alert.Indicator
| prop | type | default | description |
| -------------- | ----------------- | ------- | ------------------------------------------------------------------ |
| `children` | `React.ReactNode` | - | Custom children to render instead of the default status icon |
| `className` | `string` | - | Additional CSS classes |
| `iconProps` | `AlertIconProps` | - | Props passed to the default status icon (size and color overrides) |
| `...ViewProps` | `ViewProps` | - | All standard React Native View props are supported |
#### AlertIconProps
| prop | type | default | description |
| ------- | -------- | ------------ | ---------------------- |
| `size` | `number` | `18` | Icon size in pixels |
| `color` | `string` | status color | Icon color as a string |
### Alert.Content
| prop | type | default | description |
| -------------- | ----------------- | ------- | --------------------------------------------------------------- |
| `children` | `React.ReactNode` | - | Children elements (typically Alert.Title and Alert.Description) |
| `className` | `string` | - | Additional CSS classes |
| `...ViewProps` | `ViewProps` | - | All standard React Native View props are supported |
### Alert.Title
| prop | type | default | description |
| -------------- | ----------------- | ------- | -------------------------------------------------- |
| `children` | `React.ReactNode` | - | Title text content |
| `className` | `string` | - | Additional CSS classes |
| `...TextProps` | `TextProps` | - | All standard React Native Text props are supported |
### Alert.Description
| prop | type | default | description |
| -------------- | ----------------- | ------- | -------------------------------------------------- |
| `children` | `React.ReactNode` | - | Description text content |
| `className` | `string` | - | Additional CSS classes |
| `...TextProps` | `TextProps` | - | All standard React Native Text props are supported |
## Hooks
### useAlert
Hook to access the alert root context. Must be used within an `Alert` component.
```tsx
import { useAlert } from 'heroui-native';
const { status, nativeID } = useAlert();
```
#### Returns
| property | type | description |
| ---------- | ------------------------------------------------------------- | ------------------------------------------------------------ |
| `status` | `'default' \| 'accent' \| 'success' \| 'warning' \| 'danger'` | Current alert status for sub-component styling |
| `nativeID` | `string` | Unique identifier used for accessibility and ARIA attributes |
# SkeletonGroup
**Category**: native
**URL**: https://v3.heroui.com/docs/native/components/skeleton-group
**Source**: https://raw.githubusercontent.com/heroui-inc/heroui/refs/heads/v3/apps/docs/content/docs/native/components/(feedback)/skeleton-group.mdx
> Coordinates multiple skeleton loading placeholders with centralized animation control.
## Import
```tsx
import { SkeletonGroup } from 'heroui-native';
```
## Anatomy
```tsx
```
* **SkeletonGroup**: Root container that provides centralized control for all skeleton items
* **SkeletonGroup.Item**: Individual skeleton item that inherits props from the parent group
## Usage
### Basic Usage
The SkeletonGroup component manages multiple skeleton items with shared loading state and animation.
```tsx
```
### With Container Layout
Use className on the group to control layout of skeleton items.
```tsx
```
### With isSkeletonOnly for Pure Skeleton Layouts
Use `isSkeletonOnly` when the group contains only skeleton placeholders with layout wrappers (like View) that have no content to render in the loaded state. This prop hides the entire group when `isLoading` is false, preventing empty containers from affecting your layout.
```tsx
{/* This View is only for layout, no content */}
```
### With Animation Variants
Control animation style for all items in the group.
```tsx
```
### With Custom Animation Configuration
Configure shimmer or pulse animations for the entire group.
```tsx
```
### With Enter/Exit Animations
Apply Reanimated transitions when the group appears or disappears.
```tsx
```
## Example
```tsx
import { Card, SkeletonGroup, Avatar } from 'heroui-native';
import { useState } from 'react';
import { Text, View, Image } from 'react-native';
export default function SkeletonGroupExample() {
const [isLoading, setIsLoading] = useState(true);
return (
John Doe@johndoe
This is the first line of the post content.
Second line with more interesting content to read.
Last line is shorter.
);
}
```
You can find more examples in the [GitHub repository](https://github.com/heroui-inc/heroui-native/blob/rc/example/src/app/\(home\)/components/skeleton-group.tsx).
## API Reference
### SkeletonGroup
| prop | type | default | description |
| ----------------------- | -------------------------------- | ----------- | ---------------------------------------------------------------------- |
| `children` | `React.ReactNode` | - | SkeletonGroup.Item components and layout elements |
| `isLoading` | `boolean` | `true` | Whether the skeleton items are currently loading |
| `isSkeletonOnly` | `boolean` | `false` | Hides entire group when isLoading is false (for skeleton-only layouts) |
| `variant` | `'shimmer' \| 'pulse' \| 'none'` | `'shimmer'` | Animation variant for all items in the group |
| `animation` | `SkeletonRootAnimation` | - | Animation configuration |
| `className` | `string` | - | Additional CSS classes for the group container |
| `style` | `StyleProp` | - | Custom styles for the group container |
| `...Animated.ViewProps` | `AnimatedProps` | - | All Reanimated Animated.View props are supported |
#### SkeletonRootAnimation
Animation configuration for SkeletonGroup component. Can be:
* `false` or `"disabled"`: Disable only root animations
* `"disable-all"`: Disable all animations including children
* `true` or `undefined`: Use default animations
* `object`: Custom animation configuration
| prop | type | default | description |
| ------------------------ | ---------------------------------------- | --------------------------- | ----------------------------------------------- |
| `state` | `'disabled' \| 'disable-all' \| boolean` | - | Disable animations while customizing properties |
| `entering.value` | `EntryOrExitLayoutType` | `FadeIn` | Custom entering animation |
| `exiting.value` | `EntryOrExitLayoutType` | `FadeOut` | Custom exiting animation |
| `shimmer.duration` | `number` | `1500` | Animation duration in milliseconds |
| `shimmer.speed` | `number` | `1` | Speed multiplier for the animation |
| `shimmer.highlightColor` | `string` | - | Highlight color for the shimmer effect |
| `shimmer.easing` | `EasingFunction` | `Easing.linear` | Easing function for the animation |
| `pulse.duration` | `number` | `1000` | Animation duration in milliseconds |
| `pulse.minOpacity` | `number` | `0.5` | Minimum opacity value |
| `pulse.maxOpacity` | `number` | `1` | Maximum opacity value |
| `pulse.easing` | `EasingFunction` | `Easing.inOut(Easing.ease)` | Easing function for the animation |
### SkeletonGroup.Item
| prop | type | default | description |
| ----------------------- | -------------------------------- | --------- | ------------------------------------------------------------------- |
| `children` | `React.ReactNode` | - | Content to show when not loading |
| `isLoading` | `boolean` | inherited | Whether the skeleton is currently loading (overrides group setting) |
| `variant` | `'shimmer' \| 'pulse' \| 'none'` | inherited | Animation variant (overrides group setting) |
| `animation` | `SkeletonRootAnimation` | inherited | Animation configuration (overrides group setting) |
| `className` | `string` | - | Additional CSS classes for styling the item |
| `...Animated.ViewProps` | `AnimatedProps` | - | All Reanimated Animated.View props are supported |
## Special Notes
### Props Inheritance
SkeletonGroup.Item components inherit all animation-related props from their parent SkeletonGroup:
* `isLoading`
* `variant`
* `animation`
Individual items can override any inherited prop by providing their own value.
# Skeleton
**Category**: native
**URL**: https://v3.heroui.com/docs/native/components/skeleton
**Source**: https://raw.githubusercontent.com/heroui-inc/heroui/refs/heads/v3/apps/docs/content/docs/native/components/(feedback)/skeleton.mdx
> Displays a loading placeholder with shimmer or pulse animation effects.
## Import
```tsx
import { Skeleton } from 'heroui-native';
```
## Anatomy
The Skeleton component is a simple wrapper that renders a placeholder for content that is loading. It does not have any child components.
```tsx
```
## Usage
### Basic Usage
The Skeleton component creates an animated placeholder while content is loading.
```tsx
```
### With Content
Show skeleton while loading, then display content when ready.
```tsx
Loaded Content
```
### Animation Variants
Control the animation style with the `variant` prop.
```tsx
```
### Custom Shimmer Configuration
Customize the shimmer effect with duration, speed, and highlight color.
```tsx
...
```
### Custom Pulse Configuration
Configure pulse animation with duration and opacity range.
```tsx
...
```
### Shape Variations
Create different skeleton shapes using className for styling.
```tsx
```
### Custom Enter/Exit Animations
Apply custom Reanimated transitions when skeleton appears or disappears.
```tsx
...
```
## Example
```tsx
import { Avatar, Card, Skeleton } from 'heroui-native';
import { useState } from 'react';
import { Image, Text, View } from 'react-native';
export default function SkeletonExample() {
const [isLoading, setIsLoading] = useState(true);
return (
John Doe@johndoe
);
}
```
You can find more examples in the [GitHub repository](https://github.com/heroui-inc/heroui-native/blob/rc/example/src/app/\(home\)/components/skeleton.tsx).
## API Reference
### Skeleton
| prop | type | default | description |
| ----------------------- | -------------------------------- | ----------- | ------------------------------------------------------------ |
| `children` | `React.ReactNode` | - | Content to show when not loading |
| `isLoading` | `boolean` | `true` | Whether the skeleton is currently loading |
| `variant` | `'shimmer' \| 'pulse' \| 'none'` | `'shimmer'` | Animation variant |
| `animation` | `SkeletonRootAnimation` | - | Animation configuration |
| `isAnimatedStyleActive` | `boolean` | `true` | Whether animated styles (react-native-reanimated) are active |
| `className` | `string` | - | Additional CSS classes for styling |
| `...Animated.ViewProps` | `AnimatedProps` | - | All Reanimated Animated.View props are supported |
#### SkeletonRootAnimation
Animation configuration for Skeleton component. Can be:
* `false` or `"disabled"`: Disable only root animations
* `"disable-all"`: Disable all animations including children
* `true` or `undefined`: Use default animations
* `object`: Custom animation configuration
| prop | type | default | description |
| ------------------------ | ---------------------------------------- | --------------------------- | ----------------------------------------------- |
| `state` | `'disabled' \| 'disable-all' \| boolean` | - | Disable animations while customizing properties |
| `entering.value` | `EntryOrExitLayoutType` | `FadeIn` | Custom entering animation |
| `exiting.value` | `EntryOrExitLayoutType` | `FadeOut` | Custom exiting animation |
| `shimmer.duration` | `number` | `1500` | Animation duration in milliseconds |
| `shimmer.speed` | `number` | `1` | Speed multiplier for the animation |
| `shimmer.highlightColor` | `string` | - | Highlight color for the shimmer effect |
| `shimmer.easing` | `EasingFunction` | `Easing.linear` | Easing function for the animation |
| `pulse.duration` | `number` | `1000` | Animation duration in milliseconds |
| `pulse.minOpacity` | `number` | `0.5` | Minimum opacity value |
| `pulse.maxOpacity` | `number` | `1` | Maximum opacity value |
| `pulse.easing` | `EasingFunction` | `Easing.inOut(Easing.ease)` | Easing function for the animation |
# Spinner
**Category**: native
**URL**: https://v3.heroui.com/docs/native/components/spinner
**Source**: https://raw.githubusercontent.com/heroui-inc/heroui/refs/heads/v3/apps/docs/content/docs/native/components/(feedback)/spinner.mdx
> Displays an animated loading indicator.
## Import
```tsx
import { Spinner } from 'heroui-native';
```
## Anatomy
```tsx
...
```
* **Spinner**: Main container that controls loading state, size, and color. Renders a default animated indicator if no children provided.
* **Spinner.Indicator**: Optional sub-component for customizing animation configuration and icon appearance. Accepts custom children to replace the default icon.
## Usage
### Basic Usage
The Spinner component displays a rotating loading indicator.
```tsx
```
### Sizes
Control the spinner size with the `size` prop.
```tsx
```
### Colors
Use predefined color variants or custom colors.
```tsx
```
### Loading State
Control the visibility of the spinner with the `isLoading` prop.
```tsx
```
### Animation Speed
Customize the rotation speed using the `animation` prop on the Indicator component.
```tsx
```
### Custom Icon
Replace the default spinner icon with custom content.
```tsx
const themeColorForeground = useThemeColor('foreground')
⏳
```
## Example
```tsx
import { Spinner } from 'heroui-native';
import { Ionicons } from '@expo/vector-icons';
import React from 'react';
import { Text, TouchableOpacity, View } from 'react-native';
export default function SpinnerExample() {
const [isLoading, setIsLoading] = React.useState(true);
return (
Loading content...Processing... setIsLoading(!isLoading)}>
{isLoading ? 'Tap to stop' : 'Tap to start'}
);
}
```
You can find more examples in the [GitHub repository](https://github.com/heroui-inc/heroui-native/blob/rc/example/src/app/\(home\)/components/spinner.tsx).
## API Reference
### Spinner
| prop | type | default | description |
| -------------- | ----------------------------------------------------------- | ----------- | -------------------------------------------------- |
| `children` | `React.ReactNode` | `undefined` | Content to render inside the spinner |
| `size` | `'sm' \| 'md' \| 'lg'` | `'md'` | Size of the spinner |
| `color` | `'default' \| 'success' \| 'warning' \| 'danger' \| string` | `'default'` | Color theme of the spinner |
| `isLoading` | `boolean` | `true` | Whether the spinner is loading |
| `className` | `string` | `undefined` | Custom class name for the spinner |
| `animation` | `SpinnerRootAnimation` | - | Animation configuration |
| `...ViewProps` | `ViewProps` | - | All standard React Native View props are supported |
#### SpinnerRootAnimation
Animation configuration for Spinner component. Can be:
* `false` or `"disabled"`: Disable only root animations
* `"disable-all"`: Disable all animations including children
* `true` or `undefined`: Use default animations
* `object`: Custom animation configuration
| prop | type | default | description |
| ---------------- | ---------------------------------------- | ---------------------------------------------------------------------- | ----------------------------------------------- |
| `state` | `'disabled' \| 'disable-all' \| boolean` | - | Disable animations while customizing properties |
| `entering.value` | `EntryOrExitLayoutType` | `FadeIn` `.duration(200)` `.easing(Easing.out(Easing.ease))` | Custom entering animation |
| `exiting.value` | `EntryOrExitLayoutType` | `FadeOut` `.duration(100)` | Custom exiting animation |
### Spinner.Indicator
| prop | type | default | description |
| ----------------------- | --------------------------- | ----------- | ------------------------------------------------------------ |
| `children` | `React.ReactNode` | `undefined` | Content to render inside the indicator |
| `iconProps` | `SpinnerIconProps` | `undefined` | Props for the default icon |
| `className` | `string` | `undefined` | Custom class name for the indicator element |
| `animation` | `SpinnerIndicatorAnimation` | - | Animation configuration |
| `isAnimatedStyleActive` | `boolean` | `true` | Whether animated styles (react-native-reanimated) are active |
| `...Animated.ViewProps` | `Animated.ViewProps` | - | All Reanimated Animated.View props are supported |
#### SpinnerIndicatorAnimation
Animation configuration for Spinner.Indicator component. Can be:
* `false` or `"disabled"`: Disable all animations
* `true` or `undefined`: Use default animations
* `object`: Custom animation configuration
| prop | type | default | description |
| ----------------- | ---------------------------- | --------------- | ----------------------------------------------- |
| `state` | `'disabled' \| boolean` | - | Disable animations while customizing properties |
| `rotation.speed` | `number` | `1.1` | Rotation speed multiplier |
| `rotation.easing` | `WithTimingConfig['easing']` | `Easing.linear` | Animation easing configuration |
### SpinnerIconProps
| prop | type | default | description |
| -------- | ------------------ | ---------------- | ------------------ |
| `width` | `number \| string` | `24` | Width of the icon |
| `height` | `number \| string` | `24` | Height of the icon |
| `color` | `string` | `'currentColor'` | Color of the icon |
# Checkbox
**Category**: native
**URL**: https://v3.heroui.com/docs/native/components/checkbox
**Source**: https://raw.githubusercontent.com/heroui-inc/heroui/refs/heads/v3/apps/docs/content/docs/native/components/(forms)/checkbox.mdx
> A selectable control that allows users to toggle between checked and unchecked states.
## Import
```tsx
import { Checkbox } from 'heroui-native';
```
## Anatomy
```tsx
...
```
* **Checkbox**: Main container that handles selection state and user interaction. Renders default indicator with animated checkmark if no children provided. Automatically detects surface context for proper styling. Features press scale animation that can be customized or disabled. Supports render function children to access state (`isSelected`, `isInvalid`, `isDisabled`).
* **Checkbox.Indicator**: Optional checkmark container with default slide, scale, opacity, and border radius animations when selected. Renders animated check icon with SVG path drawing animation if no children provided. All animations can be individually customized or disabled. Supports render function children to access state.
## Usage
### Basic Usage
The Checkbox component renders with a default animated indicator if no children are provided. It automatically detects whether it's on a surface background for proper styling.
```tsx
```
### With Custom Indicator
Use a render function in the Indicator to show/hide custom icons based on state.
```tsx
{({ isSelected }) => (isSelected ? : null)}
```
### Invalid State
Show validation errors with the `isInvalid` prop, which applies danger color styling.
```tsx
```
### Custom Animations
Customize or disable animations for both the root checkbox and indicator.
```tsx
{
/* Disable all animations (root and indicator) */
}
;
{
/* Disable only root animation */
}
;
{
/* Disable only indicator animation */
}
;
{
/* Custom animation configuration */
}
;
```
## Example
```tsx
import {
Checkbox,
Description,
ControlField,
Label,
Separator,
Surface,
} from "heroui-native";
import React from 'react';
import { View, Text } from 'react-native';
interface CheckboxFieldProps {
isSelected: boolean;
onSelectedChange: (value: boolean) => void;
title: string;
description: string;
}
const CheckboxField: React.FC = ({
isSelected,
onSelectedChange,
title,
description,
}) => {
return (
{description}
);
};
export default function BasicUsage() {
const [fields, setFields] = React.useState({
newsletter: true,
marketing: false,
terms: false,
});
const fieldConfigs: Record<
keyof typeof fields,
{ title: string; description: string }
> = {
newsletter: {
title: 'Subscribe to newsletter',
description: 'Get weekly updates about new features and tips',
},
marketing: {
title: 'Marketing communications',
description: 'Receive promotional emails and special offers',
},
terms: {
title: 'Accept terms and conditions',
description: 'Agree to our Terms of Service and Privacy Policy',
},
};
const handleFieldChange = (key: keyof typeof fields) => (value: boolean) => {
setFields((prev) => ({ ...prev, [key]: value }));
};
const fieldKeys = Object.keys(fields) as Array;
return (
{fieldKeys.map((key, index) => (
{index > 0 && }
))}
);
}
```
You can find more examples in the [GitHub repository](https://github.com/heroui-inc/heroui-native/blob/rc/example/src/app/\(home\)/components/checkbox.tsx).
## API Reference
### Checkbox
| prop | type | default | description |
| ----------------------- | ---------------------------------------------------------------------- | ----------- | ------------------------------------------------------------------------- |
| `children` | `React.ReactNode \| ((props: CheckboxRenderProps) => React.ReactNode)` | `undefined` | Child elements or render function to customize the checkbox |
| `isSelected` | `boolean` | `undefined` | Whether the checkbox is currently selected |
| `onSelectedChange` | `(isSelected: boolean) => void` | `undefined` | Callback fired when the checkbox selection state changes |
| `isDisabled` | `boolean` | `false` | Whether the checkbox is disabled and cannot be interacted with |
| `isInvalid` | `boolean` | `false` | Whether the checkbox is invalid (shows danger color) |
| `variant` | `'primary' \| 'secondary'` | `'primary'` | Variant style for the checkbox |
| `hitSlop` | `number` | `6` | Hit slop for the pressable area |
| `animation` | `CheckboxRootAnimation` | - | Animation configuration |
| `isAnimatedStyleActive` | `boolean` | `true` | Whether animated styles (react-native-reanimated) are active |
| `className` | `string` | `undefined` | Additional CSS classes to apply |
| `...PressableProps` | `PressableProps` | - | All standard React Native Pressable props are supported (except disabled) |
#### CheckboxRenderProps
| prop | type | description |
| ------------ | --------- | -------------------------------- |
| `isSelected` | `boolean` | Whether the checkbox is selected |
| `isInvalid` | `boolean` | Whether the checkbox is invalid |
| `isDisabled` | `boolean` | Whether the checkbox is disabled |
#### CheckboxRootAnimation
Animation configuration for checkbox root component. Can be:
* `false` or `"disabled"`: Disable only root animations
* `"disable-all"`: Disable all animations including children
* `true` or `undefined`: Use default animations
* `object`: Custom animation configuration
| prop | type | default | description |
| -------------------- | ---------------------------------------- | ------------------- | ----------------------------------------------- |
| `state` | `'disabled' \| 'disable-all' \| boolean` | - | Disable animations while customizing properties |
| `scale.value` | `[number, number]` | `[1, 0.96]` | Scale values \[unpressed, pressed] |
| `scale.timingConfig` | `WithTimingConfig` | `{ duration: 150 }` | Animation timing configuration |
### Checkbox.Indicator
| prop | type | default | description |
| ----------------------- | ---------------------------------------------------------------------- | ----------- | ------------------------------------------------------------ |
| `children` | `React.ReactNode \| ((props: CheckboxRenderProps) => React.ReactNode)` | `undefined` | Content or render function for the checkbox indicator |
| `className` | `string` | `undefined` | Additional CSS classes for the indicator |
| `iconProps` | `CheckboxIndicatorIconProps` | `undefined` | Custom props for the default animated check icon |
| `animation` | `CheckboxIndicatorAnimation` | - | Animation configuration |
| `isAnimatedStyleActive` | `boolean` | `true` | Whether animated styles (react-native-reanimated) are active |
| `...AnimatedViewProps` | `AnimatedProps` | - | All standard React Native Animated View props are supported |
#### CheckboxIndicatorIconProps
Props for customizing the default animated check icon.
| prop | type | description |
| --------------- | -------- | ------------------------------------------------ |
| `size` | `number` | Icon size |
| `strokeWidth` | `number` | Icon stroke width |
| `color` | `string` | Icon color (defaults to theme accent-foreground) |
| `enterDuration` | `number` | Duration of enter animation (check appearing) |
| `exitDuration` | `number` | Duration of exit animation (check disappearing) |
#### CheckboxIndicatorAnimation
Animation configuration for checkbox indicator component. Can be:
* `false` or `"disabled"`: Disable all animations
* `true` or `undefined`: Use default animations
* `object`: Custom animation configuration
| prop | type | default | description |
| --------------------------- | ----------------------- | ------------------- | ----------------------------------------------- |
| `state` | `'disabled' \| boolean` | - | Disable animations while customizing properties |
| `opacity.value` | `[number, number]` | `[0, 1]` | Opacity values \[unselected, selected] |
| `opacity.timingConfig` | `WithTimingConfig` | `{ duration: 100 }` | Animation timing configuration |
| `borderRadius.value` | `[number, number]` | `[8, 0]` | Border radius values \[unselected, selected] |
| `borderRadius.timingConfig` | `WithTimingConfig` | `{ duration: 50 }` | Animation timing configuration |
| `translateX.value` | `[number, number]` | `[-4, 0]` | TranslateX values \[unselected, selected] |
| `translateX.timingConfig` | `WithTimingConfig` | `{ duration: 100 }` | Animation timing configuration |
| `scale.value` | `[number, number]` | `[0.8, 1]` | Scale values \[unselected, selected] |
| `scale.timingConfig` | `WithTimingConfig` | `{ duration: 100 }` | Animation timing configuration |
## Hooks
### useCheckbox
Hook to access checkbox context values within custom components or compound components.
```tsx
import { useCheckbox } from 'heroui-native';
const CustomIndicator = () => {
const { isSelected, isInvalid, isDisabled } = useCheckbox();
// ... your implementation
};
```
**Returns:** `UseCheckboxReturn`
| property | type | description |
| ------------------ | ---------------------------------------------- | -------------------------------------------------------------- |
| `isSelected` | `boolean \| undefined` | Whether the checkbox is currently selected |
| `onSelectedChange` | `((isSelected: boolean) => void) \| undefined` | Callback function to change the checkbox selection state |
| `isDisabled` | `boolean` | Whether the checkbox is disabled and cannot be interacted with |
| `isInvalid` | `boolean` | Whether the checkbox is invalid (shows danger color) |
| `nativeID` | `string \| undefined` | Native ID for the checkbox element |
**Note:** This hook must be used within a `Checkbox` component. It will throw an error if called outside of the checkbox context.
# ControlField
**Category**: native
**URL**: https://v3.heroui.com/docs/native/components/control-field
**Source**: https://raw.githubusercontent.com/heroui-inc/heroui/refs/heads/v3/apps/docs/content/docs/native/components/(forms)/control-field.mdx
> A field component that combines a label, description (or other content), and a control component (Switch or Checkbox) into a single pressable area.
## Import
```tsx
import { ControlField } from 'heroui-native';
```
## Anatomy
```tsx
.........
```
* **ControlField**: Root container that manages layout and state propagation
* **Label**: Primary text label for the control (from [Label](./label) component)
* **Description**: Secondary descriptive helper text (from [Description](./description) component)
* **ControlField.Indicator**: Container for the form control component ([Switch](./switch), [Checkbox](./checkbox), [Radio](./radio))
* **FieldError**: Validation error message display (from [FieldError](./field-error) component)
## Usage
### Basic Usage
ControlField wraps form controls to provide consistent layout and state management.
```tsx
```
### With Description
Add helper text below the label using the Description component.
```tsx
Receive push notifications about your account activity
```
### With Error Message
Display validation errors using the ErrorMessage component.
```tsx
By checking this box, you agree to our Terms of Service
This field is required
```
### Disabled State
Control interactivity with the disabled prop.
```tsx
This field is disabled
```
### Disabling All Animations
Disable all animations including children by using `"disable-all"`. This cascades down to all child components.
```tsx
Description text
```
## Example
```tsx
import {
Checkbox,
Description,
FieldError,
ControlField,
Label,
Switch,
} from 'heroui-native';
import React from 'react';
import { ScrollView, View } from 'react-native';
export default function ControlFieldExample() {
const [notifications, setNotifications] = React.useState(false);
const [terms, setTerms] = React.useState(false);
const [newsletter, setNewsletter] = React.useState(true);
return (
Receive push notifications about your account activity
By checking this box, you agree to our Terms of Service
This field is required
);
}
```
You can find more examples in the [GitHub repository](https://github.com/heroui-inc/heroui-native/blob/rc/example/src/app/\(home\)/components/control-field.tsx).
## API Reference
### ControlField
| prop | type | default | description |
| ----------------- | -------------------------------------------------------------------------- | ----------- | ----------------------------------------------------------------------------------------- |
| children | `React.ReactNode \| ((props: ControlFieldRenderProps) => React.ReactNode)` | - | Content to render inside the form control, or a render function |
| isSelected | `boolean` | `undefined` | Whether the control is selected/checked |
| isDisabled | `boolean` | `false` | Whether the form control is disabled |
| isInvalid | `boolean` | `false` | Whether the form control is invalid |
| isRequired | `boolean` | `false` | Whether the form control is required |
| className | `string` | - | Custom class name for the root element |
| onSelectedChange | `(isSelected: boolean) => void` | - | Callback when selection state changes |
| animation | `"disable-all" \| undefined` | `undefined` | Animation configuration. Use `"disable-all"` to disable all animations including children |
| ...PressableProps | `PressableProps` | - | All React Native Pressable props are supported |
### Label
The `Label` component automatically consumes form state (`isDisabled`, `isInvalid`) from the ControlField context.
**Note**: For complete prop documentation, see the [Label component documentation](./label).
### Description
The `Description` component automatically consumes form state (`isDisabled`, `isInvalid`) from the ControlField context.
**Note**: For complete prop documentation, see the [Description component documentation](./description).
### ControlField.Indicator
| prop | type | default | description |
| ------------ | ----------------------------------- | ---------- | ---------------------------------------------------------- |
| children | `React.ReactNode` | - | Control component to render (Switch, Checkbox, Radio) |
| variant | `'checkbox' \| 'radio' \| 'switch'` | `'switch'` | Variant of the control to render when no children provided |
| className | `string` | - | Custom class name for the indicator element |
| ...ViewProps | `ViewProps` | - | All React Native View props are supported |
**Note**: When children are provided, the component automatically passes down `isSelected`, `onSelectedChange`, `isDisabled`, and `isInvalid` props from the ControlField context if they are not already present on the child component. When using the `radio` variant, the Radio component renders in standalone mode (outside of a RadioGroup).
### FieldError
The `FieldError` component automatically consumes form state (`isInvalid`) from the ControlField context.
**Note**: For complete prop documentation, see the [FieldError component documentation](./field-error). The error message visibility is controlled by the `isInvalid` state of the parent ControlField.
## Hooks
### useControlField
**Returns:**
| property | type | description |
| ------------------ | ---------------------------------------------- | ---------------------------------------------- |
| `isSelected` | `boolean \| undefined` | Whether the control is selected/checked |
| `onSelectedChange` | `((isSelected: boolean) => void) \| undefined` | Callback when selection state changes |
| `isDisabled` | `boolean` | Whether the form control is disabled |
| `isInvalid` | `boolean` | Whether the form control is invalid |
| `isPressed` | `SharedValue` | Reanimated shared value indicating press state |
# Description
**Category**: native
**URL**: https://v3.heroui.com/docs/native/components/description
**Source**: https://raw.githubusercontent.com/heroui-inc/heroui/refs/heads/v3/apps/docs/content/docs/native/components/(forms)/description.mdx
> Text component for providing accessible descriptions and helper text for form fields and other UI elements.
## Import
```tsx
import { Description } from 'heroui-native';
```
## Anatomy
```tsx
...
```
* **Description**: Text component that displays description or helper text with muted styling. Can be linked to form fields via `nativeID` for accessibility support.
## Usage
### Basic Usage
Display description text with default muted styling.
```tsx
This is a helpful description.
```
### With Form Fields
Provide accessible descriptions for form fields using the `nativeID` prop.
```tsx
We'll never share your email with anyone else.
```
### Accessibility Linking
Link descriptions to form fields for screen reader support by using `nativeID` and `aria-describedby`.
```tsx
Use at least 8 characters with a mix of letters, numbers, and symbols.
```
### Hiding on Invalid State
Control whether the description should be hidden when the form field is invalid using the `hideOnInvalid` prop.
```tsx
We'll never share your email with anyone else.
Please enter a valid email address
```
When `hideOnInvalid` is `true`, the description will be hidden when the field is invalid. When `false` (default), the description remains visible even when invalid.
## Example
```tsx
import { Description, TextField } from 'heroui-native';
import { View } from 'react-native';
export default function DescriptionExample() {
return (
We'll never share your email with anyone else.
Use at least 8 characters with a mix of letters, numbers, and symbols.
);
}
```
You can find more examples in the [GitHub repository](https://github.com/heroui-inc/heroui-native/blob/rc/example/src/app/\(home\)/components/description.tsx).
## API Reference
### Description
| prop | type | default | description |
| --------------- | ----------------------------------- | ------- | ------------------------------------------------------------------------------------------ |
| `children` | `React.ReactNode` | - | Description text content |
| `className` | `string` | - | Additional CSS classes to apply |
| `nativeID` | `string` | - | Native ID for accessibility. Used to link description to form fields via aria-describedby. |
| `isInvalid` | `boolean` | - | Whether the description is in an invalid state (overrides context) |
| `isDisabled` | `boolean` | - | Whether the description is disabled (overrides context) |
| `hideOnInvalid` | `boolean` | `false` | Whether to hide the description when invalid |
| `animation` | `DescriptionAnimation \| undefined` | - | Animation configuration for description transitions |
| `...TextProps` | `TextProps` | - | All standard React Native Text props are supported |
# FieldError
**Category**: native
**URL**: https://v3.heroui.com/docs/native/components/field-error
**Source**: https://raw.githubusercontent.com/heroui-inc/heroui/refs/heads/v3/apps/docs/content/docs/native/components/(forms)/field-error.mdx
> Displays validation error message content with smooth animations.
## Import
```tsx
import { FieldError } from 'heroui-native';
```
## Anatomy
```tsx
Error message content
```
* **FieldError**: Main container that displays error messages with smooth animations. Accepts string children which are automatically wrapped with Text component, or custom React components for more complex layouts. Controls visibility through the `isInvalid` prop and supports custom entering/exiting animations.
## Usage
### Basic Usage
The FieldError component displays error messages when validation fails.
```tsx
This field is required
```
### Controlled Visibility
Control when the error appears using the `isInvalid` prop. When used inside a form field component (like TextField), FieldError automatically consumes the form-item-state context.
```tsx
const [isInvalid, setIsInvalid] = useState(false);
Please enter a valid email address;
```
### With Form Fields
FieldError automatically consumes form state from TextField via the form-item-state context.
```tsx
import { FieldError, Label, TextField } from 'heroui-native';
Please enter a valid email address
```
### Custom Content
Pass custom React components as children instead of strings.
```tsx
Invalid input
```
### Custom Animations
Override default entering and exiting animations using the `animation` prop.
```tsx
import { SlideInDown, SlideOutUp } from 'react-native-reanimated';
Field validation failed
;
```
Disable animations entirely:
```tsx
Field validation failed
```
### Custom Styling
Apply custom styles to the container and text elements.
```tsx
Password must be at least 8 characters
```
### Custom Text Props
Pass additional props to the Text component when children is a string.
```tsx
This is a very long error message that might need to be truncated
```
## Example
```tsx
import { Description, FieldError, Label, TextField } from 'heroui-native';
import { useState } from 'react';
import { View } from 'react-native';
export default function FieldErrorExample() {
const [email, setEmail] = useState('');
const [isInvalid, setIsInvalid] = useState(false);
const isValidEmail = /^[^\s@]+@[^\s@]+\.[^\s@]+$/.test(email);
const handleBlur = () => {
setIsInvalid(email !== '' && !isValidEmail);
};
return (
We'll use this to contact you
Please enter a valid email address
);
}
```
You can find more examples in the [GitHub repository](https://github.com/heroui-inc/heroui-native/blob/rc/example/src/app/\(home\)/components/field-error.tsx).
## API Reference
### FieldError
| prop | type | default | description |
| ---------------------- | --------------------------------------------- | ----------- | --------------------------------------------------------------------------------------------------------------------------------------------- |
| `children` | `React.ReactNode` | `undefined` | The content of the error field. String children are wrapped with Text |
| `isInvalid` | `boolean` | `undefined` | Controls the visibility of the error field (overrides form-item-state context). When used inside TextField, automatically consumes form state |
| `animation` | `FieldErrorRootAnimation` | - | Animation configuration |
| `className` | `string` | `undefined` | Additional CSS classes for the container |
| `classNames` | `ElementSlots` | `undefined` | Additional CSS classes for different parts of the component |
| `styles` | `{ container?: ViewStyle; text?: TextStyle }` | `undefined` | Styles for different parts of the field error |
| `textProps` | `TextProps` | `undefined` | Additional props to pass to the Text component when children is a string |
| `...AnimatedViewProps` | `AnimatedProps` | - | All Reanimated Animated.View props are supported |
**classNames prop:** `ElementSlots` provides type-safe CSS classes for different parts of the field error component. Available slots: `container`, `text`.
#### `styles`
| prop | type | description |
| ----------- | ----------- | --------------------------- |
| `container` | `ViewStyle` | Styles for the container |
| `text` | `TextStyle` | Styles for the text content |
#### FieldErrorRootAnimation
Animation configuration for field error root component. Can be:
* `false` or `"disabled"`: Disable only root animations
* `"disable-all"`: Disable all animations including children
* `true` or `undefined`: Use default animations
* `object`: Custom animation configuration
| prop | type | default | description |
| ---------------- | ---------------------------------------- | ----------------------------------------------------------------------- | ----------------------------------------------- |
| `state` | `'disabled' \| 'disable-all' \| boolean` | - | Disable animations while customizing properties |
| `entering.value` | `EntryOrExitLayoutType` | `FadeIn` `.duration(150)` `.easing(Easing.out(Easing.ease))` | Custom entering animation for field error |
| `exiting.value` | `EntryOrExitLayoutType` | `FadeOut` `.duration(100)` `.easing(Easing.out(Easing.ease))` | Custom exiting animation for field error |
# InputGroup
**Category**: native
**URL**: https://v3.heroui.com/docs/native/components/input-group
**Source**: https://raw.githubusercontent.com/heroui-inc/heroui/refs/heads/v3/apps/docs/content/docs/native/components/(forms)/input-group.mdx
> A compound layout component that groups an input with optional prefix and suffix decorators.
## Import
```tsx
import { InputGroup } from 'heroui-native';
```
## Anatomy
```tsx
......
```
* **InputGroup**: Layout container that wraps Prefix, Input, and Suffix. Provides animation settings and a measurement context so Prefix/Suffix widths are automatically applied as padding on the Input.
* **InputGroup.Prefix**: Absolutely positioned View anchored to the left side of the Input. Its measured width is applied as `paddingLeft` on InputGroup.Input automatically.
* **InputGroup.Suffix**: Absolutely positioned View anchored to the right side of the Input. Its measured width is applied as `paddingRight` on InputGroup.Input automatically.
* **InputGroup.Input**: Pass-through to the Input component. Accepts all Input props directly. Automatically receives paddingLeft/paddingRight from measured Prefix/Suffix.
## Usage
### Basic Usage
The InputGroup component uses compound parts to attach prefix and suffix content to an input.
```tsx
......
```
### With Prefix Only
Attach leading content such as icons to the input.
```tsx
```
### With Suffix Only
Attach trailing content such as icons to the input.
```tsx
```
### Decorative vs Interactive
Set `isDecorative` on Prefix or Suffix to make touches pass through to the Input and hide the content from screen readers. Omit it when the decorator contains interactive elements.
```tsx
```
### Disabled State
Disable the entire input group. The disabled state cascades to all child components.
```tsx
```
### With TextField Integration
Combine with TextField, Label, and Description for full form field support.
```tsx
We'll never share your email
```
## Example
```tsx
import { InputGroup } from 'heroui-native';
import { Ionicons } from '@expo/vector-icons';
import { useState } from 'react';
import { Pressable, View } from 'react-native';
export default function InputGroupExample() {
const [value, setValue] = useState('');
const [isPasswordVisible, setIsPasswordVisible] = useState(false);
return (
setIsPasswordVisible(!isPasswordVisible)}
hitSlop={20}
>
);
}
```
You can find more examples in the [GitHub repository](https://github.com/heroui-inc/heroui-native/blob/rc/example/src/app/\(home\)/components/input-group.tsx).
## API Reference
### InputGroup
| prop | type | default | description |
| -------------- | ------------------------- | ------- | ------------------------------------------------------------ |
| `children` | `React.ReactNode` | - | Children elements to be rendered inside the input group |
| `className` | `string` | - | Additional CSS classes |
| `isDisabled` | `boolean` | `false` | Whether the entire input group and its children are disabled |
| `animation` | `AnimationRootDisableAll` | - | Animation configuration for input group |
| `...ViewProps` | `ViewProps` | - | All standard React Native View props are supported |
#### AnimationRootDisableAll
Animation configuration for the InputGroup root component. Can be:
* `"disable-all"`: Disable all animations including children (cascades down)
* `undefined`: Use default animations
### InputGroup.Prefix
| prop | type | default | description |
| -------------- | ----------------- | ------- | -------------------------------------------------------------------------------------- |
| `children` | `React.ReactNode` | - | Content to render inside the prefix |
| `className` | `string` | - | Additional CSS classes |
| `isDecorative` | `boolean` | `false` | When true, touches pass through to the Input and content is hidden from screen readers |
| `...ViewProps` | `ViewProps` | - | All standard React Native View props are supported |
### InputGroup.Suffix
| prop | type | default | description |
| -------------- | ----------------- | ------- | -------------------------------------------------------------------------------------- |
| `children` | `React.ReactNode` | - | Content to render inside the suffix |
| `className` | `string` | - | Additional CSS classes |
| `isDecorative` | `boolean` | `false` | When true, touches pass through to the Input and content is hidden from screen readers |
| `...ViewProps` | `ViewProps` | - | All standard React Native View props are supported |
### InputGroup.Input
Pass-through to the [Input](./input) component. Accepts all Input props directly.
# InputOTP
**Category**: native
**URL**: https://v3.heroui.com/docs/native/components/input-otp
**Source**: https://raw.githubusercontent.com/heroui-inc/heroui/refs/heads/v3/apps/docs/content/docs/native/components/(forms)/input-otp.mdx
> Input component for entering one-time passwords (OTP) with individual character slots, animations, and validation support.
## Import
```tsx
import { InputOTP } from 'heroui-native';
```
## Anatomy
```tsx
```
* **InputOTP**: Main container that manages OTP input state, handles text changes, and provides context to child components. Manages focus, validation, and character input.
* **InputOTP.Group**: Container for grouping multiple slots together. Use this to visually group related slots (e.g., groups of 3 digits).
* **InputOTP.Slot**: Individual slot that displays a single character or placeholder. Each slot must have a unique index matching its position in the OTP sequence. When no children are provided, automatically renders SlotPlaceholder, SlotValue, and SlotCaret.
* **InputOTP.SlotPlaceholder**: Text component that displays the placeholder character for a slot when it's empty. Used by default in Slot if no children provided.
* **InputOTP.SlotValue**: Text component that displays the actual character value for a slot with animations. Used by default in Slot if no children provided.
* **InputOTP.SlotCaret**: Animated caret indicator that shows the current input position. Place this inside a Slot to show where the user is currently typing.
* **InputOTP.Separator**: Visual separator between groups of slots. Use this to visually separate different groups of OTP digits.
## Usage
### Basic Usage
Create a 6-digit OTP input with grouped slots and separator.
```tsx
console.log(code)}>
```
### Four Digits
Create a simple 4-digit PIN input.
```tsx
console.log(code)}>
```
### With Placeholder
Provide custom placeholder characters for each slot position.
```tsx
console.log(code)}
>
{({ slots }) => (
<>
{slots.map((slot) => (
))}
>
)}
```
### Controlled Value
Control the OTP value programmatically.
```tsx
const [value, setValue] = useState('');
;
```
### With Validation
Display validation errors when the OTP is invalid.
```tsx
```
### With Pattern
Restrict input to specific character patterns using regex. Three predefined patterns are available: `REGEXP_ONLY_DIGITS` (matches digits 0-9), `REGEXP_ONLY_CHARS` (matches alphabetic characters a-z, A-Z), and `REGEXP_ONLY_DIGITS_AND_CHARS` (matches both digits and alphabetic characters).
```tsx
import { InputOTP, REGEXP_ONLY_CHARS } from 'heroui-native';
console.log(code)}
>
;
```
### Custom Layout
Use render props in Group to create custom slot layouts.
```tsx
{({ slots, isFocused, isInvalid }) => (
<>
{slots.map((slot) => (
))}
>
)}
```
## Example
```tsx
import { InputOTP, Label, Description, type InputOTPRef } from 'heroui-native';
import { View } from 'react-native';
import { useRef } from 'react';
export default function InputOTPExample() {
const ref = useRef(null);
const onComplete = (code: string) => {
console.log('OTP completed:', code);
setTimeout(() => {
ref.current?.clear();
}, 1000);
};
return (
We've sent a code to a****@gmail.com
);
}
```
You can find more examples in the [GitHub repository](https://github.com/heroui-inc/heroui-native/blob/rc/example/src/app/\(home\)/components/input-otp.tsx).
## API Reference
### InputOTP
| prop | type | default | description |
| -------------------------- | ----------------------------- | ----------- | ----------------------------------------------------------------------------------------------------------------------- |
| `maxLength` | `number` | - | Maximum length of the OTP (required) |
| `value` | `string` | - | Controlled value for the OTP input |
| `defaultValue` | `string` | - | Default value for uncontrolled usage |
| `onChange` | `(value: string) => void` | - | Callback when value changes |
| `onComplete` | `(value: string) => void` | - | Handler called when all slots are filled |
| `isDisabled` | `boolean` | `false` | Whether the input is disabled |
| `isInvalid` | `boolean` | `false` | Whether the input is in an invalid state |
| `pattern` | `string` | - | Regex pattern for allowed characters (e.g., REGEXP\_ONLY\_DIGITS, REGEXP\_ONLY\_CHARS) |
| `inputMode` | `TextInputProps['inputMode']` | `'numeric'` | Input mode for the input |
| `placeholder` | `string` | - | Placeholder text for the input. Each character corresponds to a slot position |
| `placeholderTextColor` | `string` | - | Placeholder text color for all slots |
| `placeholderTextClassName` | `string` | - | Placeholder text class name for all slots |
| `pasteTransformer` | `(text: string) => string` | - | Transform pasted text (e.g., remove hyphens). Defaults to removing non-matching characters |
| `onFocus` | `(e: FocusEvent) => void` | - | Handler for focus events |
| `onBlur` | `(e: BlurEvent) => void` | - | Handler for blur events |
| `textInputProps` | `Omit` | - | Additional props to pass to the underlying TextInput component |
| `children` | `React.ReactNode` | - | Children elements to be rendered inside the InputOTP |
| `className` | `string` | - | Additional CSS classes to apply |
| `style` | `PressableProps['style']` | - | Style to pass to the container Pressable component |
| `isBottomSheetAware` | `boolean` | `true` | Whether the InputOTP automatically handles keyboard state when rendered inside a BottomSheet. Set to `false` to disable |
| `animation` | `"disable-all" \| undefined` | `undefined` | Animation configuration. Use `"disable-all"` to disable all animations including children |
### InputOTP.Group
| prop | type | default | description |
| -------------- | --------------------------------------------------------------------------- | ------- | ------------------------------------------------------------------------------------------------------------------------ |
| `children` | `React.ReactNode \| ((props: InputOTPGroupRenderProps) => React.ReactNode)` | - | Children elements to be rendered inside the group, or a render function that receives slot data and other context values |
| `className` | `string` | - | Additional CSS classes to apply |
| `...ViewProps` | `ViewProps` | - | All standard React Native View props are supported |
#### InputOTPGroupRenderProps
| prop | type | description |
| ------------ | ------------ | ---------------------------------------- |
| `slots` | `SlotData[]` | Array of slot data for each position |
| `maxLength` | `number` | Maximum length of the OTP |
| `value` | `string` | Current OTP value |
| `isFocused` | `boolean` | Whether the input is currently focused |
| `isDisabled` | `boolean` | Whether the input is disabled |
| `isInvalid` | `boolean` | Whether the input is in an invalid state |
### InputOTP.Slot
| prop | type | default | description |
| -------------- | ----------------- | ------- | ------------------------------------------------------------------------------------------- |
| `index` | `number` | - | Zero-based index of the slot (required). Must be between 0 and maxLength - 1 |
| `children` | `React.ReactNode` | - | Custom slot content. If not provided, defaults to SlotPlaceholder, SlotValue, and SlotCaret |
| `className` | `string` | - | Additional CSS classes to apply |
| `style` | `ViewStyle` | - | Additional styles to apply |
| `...ViewProps` | `ViewProps` | - | All standard React Native View props are supported |
### InputOTP.SlotPlaceholder
| prop | type | default | description |
| -------------- | ----------- | ------- | -------------------------------------------------------------------- |
| `children` | `string` | - | Text content to display (optional, defaults to slot.placeholderChar) |
| `className` | `string` | - | Additional CSS classes to apply |
| `style` | `TextStyle` | - | Additional styles to apply |
| `...TextProps` | `TextProps` | - | All standard React Native Text props are supported |
### InputOTP.SlotValue
| prop | type | default | description |
| -------------- | ---------------------------- | ------- | --------------------------------------------------------- |
| `children` | `string` | - | Text content to display (optional, defaults to slot.char) |
| `className` | `string` | - | Additional CSS classes to apply |
| `animation` | `InputOTPSlotValueAnimation` | - | Animation configuration for SlotValue |
| `...TextProps` | `TextProps` | - | All standard React Native Text props are supported |
#### InputOTPSlotValueAnimation
Animation configuration for InputOTP.SlotValue component. Can be:
* `false` or `"disabled"`: Disable all animations
* `true` or `undefined`: Use default animations
* `object`: Custom animation configuration
| prop | type | default | description |
| ------------------ | ----------------------- | ---------------------------------------- | ----------------------------------------------- |
| `state` | `'disabled' \| boolean` | - | Disable animations while customizing properties |
| `wrapper.entering` | `EntryOrExitLayoutType` | `FadeIn.duration(250)` | Entering animation for wrapper |
| `wrapper.exiting` | `EntryOrExitLayoutType` | `FadeOut.duration(100)` | Exiting animation for wrapper |
| `text.entering` | `EntryOrExitLayoutType` | `FlipInXDown.duration(250).easing(...)` | Entering animation for text |
| `text.exiting` | `EntryOrExitLayoutType` | `FlipOutXDown.duration(250).easing(...)` | Exiting animation for text |
### InputOTP.SlotCaret
| prop | type | default | description |
| ----------------------- | ---------------------------- | -------- | -------------------------------------------------------------------------------------------------------------------------------------------- |
| `className` | `string` | - | Additional CSS classes to apply |
| `style` | `ViewStyle` | - | Additional styles to apply |
| `animation` | `InputOTPSlotCaretAnimation` | - | Animation configuration for SlotCaret |
| `isAnimatedStyleActive` | `boolean` | `true` | Whether animated styles (react-native-reanimated) are active. When `false`, the animated style is removed and you can implement custom logic |
| `pointerEvents` | `'none' \| 'auto' \| ...` | `'none'` | Pointer events configuration |
| `...ViewProps` | `ViewProps` | - | All standard React Native View props are supported |
#### InputOTPSlotCaretAnimation
Animation configuration for InputOTP.SlotCaret component. Can be:
* `false` or `"disabled"`: Disable all animations
* `true` or `undefined`: Use default animations
* `object`: Custom animation configuration
| prop | type | default | description |
| ------------------ | ----------------------- | ---------- | ----------------------------------------------- |
| `state` | `'disabled' \| boolean` | - | Disable animations while customizing properties |
| `opacity.value` | `[number, number]` | `[0, 1]` | Opacity values \[min, max] |
| `opacity.duration` | `number` | `500` | Animation duration in milliseconds |
| `height.value` | `[number, number]` | `[16, 18]` | Height values \[min, max] in pixels |
| `height.duration` | `number` | `500` | Animation duration in milliseconds |
### InputOTP.Separator
| prop | type | default | description |
| -------------- | ----------- | ------- | -------------------------------------------------- |
| `className` | `string` | - | Additional CSS classes to apply |
| `...ViewProps` | `ViewProps` | - | All standard React Native View props are supported |
## Hooks
### useInputOTP
Hook to access the InputOTP root context. Must be used within an `InputOTP` component.
```tsx
const { value, maxLength, isFocused, isDisabled, isInvalid, slots } =
useInputOTP();
```
### useInputOTPSlot
Hook to access the InputOTP.Slot context. Must be used within an `InputOTP.Slot` component.
```tsx
const { slot, isActive, isCaretVisible } = useInputOTPSlot();
```
# Input
**Category**: native
**URL**: https://v3.heroui.com/docs/native/components/input
**Source**: https://raw.githubusercontent.com/heroui-inc/heroui/refs/heads/v3/apps/docs/content/docs/native/components/(forms)/input.mdx
> A text input component with styled border and background for collecting user input.
## Import
```tsx
import { Input } from 'heroui-native';
```
## Usage
### Basic Usage
Input can be used standalone or within a TextField component.
```tsx
import { Input } from 'heroui-native';
;
```
### Within TextField
Input works seamlessly with TextField for complete form structure.
```tsx
import { Input, Label, TextField } from 'heroui-native';
;
```
### With Validation
Display error state when the input is invalid.
```tsx
import { FieldError, Input, Label, TextField } from 'heroui-native';
Please enter a valid email;
```
### With Local Invalid State Override
Override the context's invalid state for the input.
```tsx
import { FieldError, Input, Label, TextField } from 'heroui-native';
Email format is incorrect;
```
### Disabled State
Disable the input to prevent interaction.
```tsx
import { Input, Label, TextField } from 'heroui-native';
;
```
### With Variant
Use different variants to style the input based on context.
```tsx
import { Input, Label, TextField } from 'heroui-native';
```
### Custom Styling
Customize the input appearance using className.
```tsx
import { Input, Label, TextField } from 'heroui-native';
;
```
## Example
```tsx
import { Ionicons } from '@expo/vector-icons';
import { Description, Input, Label, TextField } from 'heroui-native';
import { useState } from 'react';
import { Pressable, View } from 'react-native';
import { withUniwind } from 'uniwind';
const StyledIonicons = withUniwind(Ionicons);
export const TextInputContent = () => {
const [email, setEmail] = useState('');
const [password, setPassword] = useState('');
const [isPasswordVisible, setIsPasswordVisible] = useState(false);
return (
We'll never share your email with anyone else.
setIsPasswordVisible(!isPasswordVisible)}
>
Password must be at least 6 characters
);
};
```
You can find more examples in the [GitHub repository](https://github.com/heroui-inc/heroui-native/blob/rc/example/src/app/\(home\)/components/input.tsx).
## API Reference
### Input
| prop | type | default | description |
| ------------------------- | -------------------------- | --------------------- | -------------------------------------------------------------------------------------------------------------------- |
| isInvalid | `boolean` | `undefined` | Whether the input is in an invalid state (overrides context) |
| variant | `'primary' \| 'secondary'` | `'primary'` | Variant style for the input |
| className | `string` | - | Custom class name for the input |
| selectionColorClassName | `string` | `"accent-accent"` | Custom className for the selection color |
| placeholderColorClassName | `string` | `"field-placeholder"` | Custom className for the placeholder text color |
| isBottomSheetAware | `boolean` | `true` | Whether the input automatically handles keyboard state when rendered inside a BottomSheet. Set to `false` to disable |
| animation | `AnimationRoot` | `undefined` | Animation configuration for the input |
| ...TextInputProps | `TextInputProps` | - | All standard React Native TextInput props are supported |
> **Note**: When used within a TextField component, Input automatically consumes form state (isDisabled, isInvalid) from TextField via the form-item-state context.
# Label
**Category**: native
**URL**: https://v3.heroui.com/docs/native/components/label
**Source**: https://raw.githubusercontent.com/heroui-inc/heroui/refs/heads/v3/apps/docs/content/docs/native/components/(forms)/label.mdx
> Text component for labeling form fields and other UI elements with support for required indicators and validation states.
## Import
```tsx
import { Label } from 'heroui-native';
```
## Anatomy
```tsx
```
* **Label**: Root container that manages label state and provides context to child components. When string children are provided, automatically renders as Label.Text. Supports disabled, required, and invalid states.
* **Label.Text**: Text content of the label. Displays the label text and automatically shows an asterisk when the label is required. Changes color when invalid or disabled.
## Usage
### Basic Usage
Display a label with text content. String children are automatically rendered as Label.Text.
```tsx
```
### With Form Fields
Use Label with form fields to provide accessible labels.
```tsx
```
### Required Fields
Show an asterisk indicator for required fields using the `isRequired` prop.
```tsx
```
### Invalid State
Display labels in an invalid state to indicate validation errors.
```tsx
import { FieldError, Label, TextField } from 'heroui-native';
Passwords do not match
```
### Disabled State
Disable labels to indicate non-interactive fields.
```tsx
```
### Custom Layout
Use compound components for custom label layouts.
```tsx
```
### Custom Styling
Apply custom styles using className, classNames, or styles props.
```tsx
```
## Example
```tsx
import { FieldError, Label, TextField } from 'heroui-native';
import { View } from 'react-native';
export default function LabelExample() {
return (
Passwords do not match
);
}
```
You can find more examples in the [GitHub repository](https://github.com/heroui-inc/heroui-native/blob/rc/example/src/app/\(home\)/components/label.tsx).
## API Reference
### Label
| prop | type | default | description |
| ------------------- | ---------------------------- | ----------- | ------------------------------------------------------------------------------------------------------------- |
| `children` | `React.ReactNode` | - | Label content. When string is provided, automatically renders as Label.Text. Otherwise renders children as-is |
| `isRequired` | `boolean` | `false` | Whether the label is required. Shows asterisk indicator when true |
| `isInvalid` | `boolean` | `false` | Whether the label is in an invalid state. Changes text color to danger |
| `isDisabled` | `boolean` | `false` | Whether the label is disabled. Applies disabled styling and prevents interaction |
| `className` | `string` | - | Additional CSS classes to apply |
| `animation` | `"disable-all" \| undefined` | `undefined` | Animation configuration. Use `"disable-all"` to disable all animations including children |
| `...PressableProps` | `PressableProps` | - | All standard React Native Pressable props are supported |
### Label.Text
| prop | type | default | description |
| -------------- | ---------------------------------------- | ------- | ---------------------------------------------------------------------------------- |
| `children` | `React.ReactNode` | - | Label text content |
| `className` | `string` | - | Additional CSS classes to apply to the text element |
| `classNames` | `ElementSlots` | - | Additional CSS classes for different parts of the label |
| `styles` | `Partial>` | - | Styles for different parts of the label |
| `nativeID` | `string` | - | Native ID for accessibility. Used to link label to form fields via aria-labelledby |
| `...TextProps` | `TextProps` | - | All standard React Native Text props are supported |
#### `ElementSlots`
| prop | type | description |
| ---------- | -------- | ------------------------------ |
| `text` | `string` | CSS classes for the label text |
| `asterisk` | `string` | CSS classes for the asterisk |
#### `styles`
| prop | type | description |
| ---------- | ----------- | ------------------------- |
| `text` | `TextStyle` | Styles for the label text |
| `asterisk` | `TextStyle` | Styles for the asterisk |
# RadioGroup
**Category**: native
**URL**: https://v3.heroui.com/docs/native/components/radio-group
**Source**: https://raw.githubusercontent.com/heroui-inc/heroui/refs/heads/v3/apps/docs/content/docs/native/components/(forms)/radio-group.mdx
> A set of radio buttons where only one option can be selected at a time.
## Import
```tsx
import { RadioGroup } from 'heroui-native';
```
## Anatomy
```tsx
......
```
* **RadioGroup**: Container that manages the selection state of radio items. Supports both horizontal and vertical orientations.
* **RadioGroup.Item**: Individual radio option within a RadioGroup. Must be used inside RadioGroup. Handles selection state and renders a default `` indicator when text children are provided. Supports render function children to access state (`isSelected`, `isInvalid`, `isDisabled`).
* **Label**: Optional clickable text label for the radio option. Linked to the radio for accessibility. Use the [Label](./label) component directly.
* **Description**: Optional secondary text below the label. Provides additional context about the radio option. Use the [Description](./description) component directly.
* **Radio**: The [Radio](./radio) component used inside `RadioGroup.Item` to render the radio indicator. Automatically detects the `RadioGroupItem` context and derives `isSelected`, `isDisabled`, `isInvalid`, and `variant` from it.
* **Radio.Indicator**: Optional container for the radio circle. Renders default thumb if no children provided. Manages the visual selection state. See [Radio](./radio) for full API.
* **Radio.IndicatorThumb**: Optional inner circle that appears when selected. Animates scale based on selection. Can be replaced with custom content. See [Radio](./radio) for full API.
* **FieldError**: Error message displayed when radio group is invalid. Shown with animation below the radio group content. Use the [FieldError](./field-error) component directly.
## Usage
### Basic Usage
RadioGroup with simple string children automatically renders title and indicator.
```tsx
Option 1Option 2Option 3
```
### With Descriptions
Add descriptive text below each radio option for additional context.
```tsx
import { RadioGroup, Radio, Label, Description } from 'heroui-native';
import { View } from 'react-native';
Delivered in 5-7 business daysDelivered in 2-3 business days;
```
### Custom Indicator
Replace the default indicator thumb with custom content using `Radio` sub-components.
```tsx
import { RadioGroup, Radio, Label } from 'heroui-native';
{({ isSelected }) => (
<>
{isSelected && (
)}
>
)}
;
```
### With Render Function
Use a render function on RadioGroup.Item to access state and customize the entire content.
```tsx
import { RadioGroup, Radio, Label } from 'heroui-native';
{({ isSelected, isInvalid, isDisabled }) => (
<>
{isSelected && }
>
)}
;
```
### With Error Message
Display validation errors below the radio group.
```tsx
import { RadioGroup, FieldError } from 'heroui-native';
function RadioGroupWithError() {
const [value, setValue] = React.useState(undefined);
return (
I agree to the termsI do not agree
Please select an option to continue
);
}
```
## Example
```tsx
import {
Description,
Label,
Radio,
RadioGroup,
Separator,
Surface,
} from 'heroui-native';
import React from 'react';
import { View } from 'react-native';
export default function RadioGroupExample() {
const [selection, setSelection] = React.useState('desc1');
return (
Delivered in 5-7 business daysDelivered in 2-3 business daysDelivered next business day
);
}
```
You can find more examples in the [GitHub repository](https://github.com/heroui-inc/heroui-native/blob/rc/example/src/app/\(home\)/components/radio-group.tsx).
## API Reference
### RadioGroup
| prop | type | default | description |
| --------------- | ---------------------------- | ----------- | ----------------------------------------------------------------------------------------- |
| `children` | `React.ReactNode` | `undefined` | Radio group content |
| `value` | `string \| undefined` | `undefined` | The currently selected value of the radio group |
| `onValueChange` | `(val: string) => void` | `undefined` | Callback fired when the selected value changes |
| `isDisabled` | `boolean` | `false` | Whether the entire radio group is disabled |
| `isInvalid` | `boolean` | `false` | Whether the radio group is invalid |
| `variant` | `'primary' \| 'secondary'` | `undefined` | Variant style for the radio group (inherited by items if not set on item) |
| `animation` | `"disable-all" \| undefined` | `undefined` | Animation configuration. Use `"disable-all"` to disable all animations including children |
| `className` | `string` | `undefined` | Custom class name |
| `...ViewProps` | `ViewProps` | - | All standard React Native View props are supported |
### RadioGroup.Item
| prop | type | default | description |
| ------------------- | ---------------------------------------------------------------------------- | ----------- | ------------------------------------------------------------------------- |
| `children` | `React.ReactNode \| ((props: RadioGroupItemRenderProps) => React.ReactNode)` | `undefined` | Radio item content or render function to customize the radio item |
| `value` | `string` | `undefined` | The value associated with this radio item |
| `isDisabled` | `boolean` | `false` | Whether this specific radio item is disabled |
| `isInvalid` | `boolean` | `false` | Whether the radio item is invalid |
| `variant` | `'primary' \| 'secondary'` | `'primary'` | Variant style for the radio item |
| `hitSlop` | `number` | `6` | Hit slop for the pressable area |
| `className` | `string` | `undefined` | Custom class name |
| `...PressableProps` | `PressableProps` | - | All standard React Native Pressable props are supported (except disabled) |
#### RadioGroupItemRenderProps
| prop | type | description |
| ------------ | --------- | ---------------------------------- |
| `isSelected` | `boolean` | Whether the radio item is selected |
| `isInvalid` | `boolean` | Whether the radio item is invalid |
| `isDisabled` | `boolean` | Whether the radio item is disabled |
### Radio (inside RadioGroup.Item)
The [Radio](./radio) component is used inside `RadioGroup.Item` to render the radio indicator. When placed inside a `RadioGroup.Item`, the Radio component automatically detects the `RadioGroupItem` context and derives `isSelected`, `isDisabled`, `isInvalid`, and `variant` from it — no manual prop passing is needed.
Use `` for the default indicator, or compose with `Radio.Indicator` and `Radio.IndicatorThumb` for custom styling.
**Note:** For complete Radio prop documentation (including `Radio.Indicator` and `Radio.IndicatorThumb`), see the [Radio component documentation](./radio).
**Note:** For labels, descriptions, and error messages, use the base components directly:
* Use [Label](./label) component for labels
* Use [Description](./description) component for descriptions
* Use [FieldError](./field-error) component for error messages
## Hooks
### useRadioGroup
**Returns:**
| Property | Type | Description |
| --------------- | -------------------------- | ---------------------------------------------- |
| `value` | `string \| undefined` | Currently selected value |
| `isDisabled` | `boolean` | Whether the radio group is disabled |
| `isInvalid` | `boolean` | Whether the radio group is in an invalid state |
| `variant` | `'primary' \| 'secondary'` | Variant style for the radio group |
| `onValueChange` | `(value: string) => void` | Function to change the selected value |
### useRadioGroupItem
**Returns:**
| Property | Type | Description |
| ------------------ | ---------------------------------------------- | ----------------------------------------------------------------------- |
| `isSelected` | `boolean` | Whether the radio item is selected |
| `isDisabled` | `boolean \| undefined` | Whether the radio item is disabled |
| `isInvalid` | `boolean \| undefined` | Whether the radio item is invalid |
| `variant` | `'primary' \| 'secondary' \| undefined` | Variant style for the radio item |
| `onSelectedChange` | `((isSelected: boolean) => void) \| undefined` | Callback to change the selection state (selects this item in the group) |
# SearchField
**Category**: native
**URL**: https://v3.heroui.com/docs/native/components/search-field
**Source**: https://raw.githubusercontent.com/heroui-inc/heroui/refs/heads/v3/apps/docs/content/docs/native/components/(forms)/search-field.mdx
> A compound search input for filtering and querying content.
## Import
```tsx
import { SearchField } from 'heroui-native';
```
## Anatomy
```tsx
```
* **SearchField**: Root container that accepts `value` and `onChange`, providing them to children via context. Also provides form field state (isDisabled, isInvalid, isRequired) and animation settings.
* **SearchField.Group**: Flex-row container that positions the search icon, input, and clear button horizontally.
* **SearchField.SearchIcon**: Magnifying glass icon positioned absolutely on the left side of the input. Supports custom children to replace the default icon.
* **SearchField.Input**: Wraps the Input component with search-specific defaults. Reads `value` and `onChangeText` from the SearchField context automatically.
* **SearchField.ClearButton**: Small icon-only button to clear the search input. Automatically hidden when value is empty. Calls `onChange("")` from context on press.
## Usage
### Basic Usage
The SearchField component uses compound parts to create a search input. Pass `value` and `onChange` to the root; the Input and ClearButton consume them via context.
```tsx
```
### With Label and Description
Add a Label and Description outside the Group to provide context for the search field.
```tsx
Search by name, category, or SKU
```
### With Validation
Use `isInvalid` and `isRequired` on the root to control validation state. Pair with FieldError to display error messages.
```tsx
Enter at least 3 characters to searchNo results found. Please try a different search term.
```
### Custom Search Icon
Replace the default magnifying glass icon by passing children to `SearchField.SearchIcon`.
```tsx
🔍
```
### Disabled
Set `isDisabled` on the root to disable all child components via context.
```tsx
Search is temporarily unavailable
```
## Example
```tsx
import { Description, Label, SearchField } from 'heroui-native';
import { useState } from 'react';
import { View } from 'react-native';
export default function SearchFieldExample() {
const [searchValue, setSearchValue] = useState('');
return (
Search by name, category, or SKU
);
}
```
You can find more examples in the [GitHub repository](https://github.com/heroui-inc/heroui-native/blob/rc/example/src/app/\(home\)/components/search-field.tsx).
## API Reference
### SearchField
| prop | type | default | description |
| -------------- | ------------------------- | ------- | -------------------------------------------------------- |
| `children` | `React.ReactNode` | - | Children elements to be rendered inside the search field |
| `value` | `string` | - | Controlled search text value |
| `onChange` | `(value: string) => void` | - | Callback fired when the search text changes |
| `isDisabled` | `boolean` | `false` | Whether the search field is disabled |
| `isInvalid` | `boolean` | `false` | Whether the search field is in an invalid state |
| `isRequired` | `boolean` | `false` | Whether the search field is required |
| `className` | `string` | - | Additional CSS classes |
| `animation` | `AnimationRootDisableAll` | - | Animation configuration for the search field |
| `...ViewProps` | `ViewProps` | - | All standard React Native View props are supported |
#### AnimationRootDisableAll
Animation configuration for the SearchField root component. Can be:
* `"disable-all"`: Disable all animations including children (cascades down)
* `undefined`: Use default animations
### SearchField.Group
| prop | type | default | description |
| -------------- | ----------------- | ------- | -------------------------------------------------- |
| `children` | `React.ReactNode` | - | Children elements to be rendered inside the group |
| `className` | `string` | - | Additional CSS classes |
| `...ViewProps` | `ViewProps` | - | All standard React Native View props are supported |
### SearchField.SearchIcon
| prop | type | default | description |
| -------------- | -------------------------------- | ------- | ---------------------------------------------------------------------------------- |
| `children` | `React.ReactNode` | - | Custom content to replace the default search icon |
| `className` | `string` | - | Additional CSS classes |
| `iconProps` | `SearchFieldSearchIconIconProps` | - | Props for customizing the default search icon (ignored when children are provided) |
| `...ViewProps` | `ViewProps` | - | All standard React Native View props are supported |
#### SearchFieldSearchIconIconProps
| prop | type | default | description |
| ------- | -------- | ------------------- | ----------------- |
| `size` | `number` | `16` | Size of the icon |
| `color` | `string` | Theme `muted` color | Color of the icon |
### SearchField.Input
Extends [Input](./input) props with search-specific defaults (`placeholder="Search..."`, `returnKeyType="search"`, `accessibilityRole="search"`). Omits `value` and `onChangeText` because they are provided by the SearchField context.
### SearchField.ClearButton
Automatically hidden when the controlled `value` is an empty string. Calls `onChange("")` from context on press. Additional `onPress` handlers passed via props are called after clearing.
| prop | type | default | description |
| ---------------- | --------------------------------- | ------- | ------------------------------------------------ |
| `children` | `React.ReactNode` | - | Custom content to replace the default close icon |
| `iconProps` | `SearchFieldClearButtonIconProps` | - | Props for customizing the clear button icon |
| `className` | `string` | - | Additional CSS classes |
| `...ButtonProps` | `ButtonRootProps` | - | All Button root props are supported |
#### SearchFieldClearButtonIconProps
| prop | type | default | description |
| ------- | -------- | ------------------- | ----------------- |
| `size` | `number` | `14` | Size of the icon |
| `color` | `string` | Theme `muted` color | Color of the icon |
## Hooks
### useSearchField
Hook to access the search field state from context. Must be used within a `SearchField` component.
```tsx
import { useSearchField } from 'heroui-native';
const { value, onChange, isDisabled, isInvalid, isRequired } = useSearchField();
```
#### Returns
| property | type | description |
| ------------ | ---------------------------------------- | ----------------------------------------------- |
| `value` | `string \| undefined` | Current controlled search text value |
| `onChange` | `((value: string) => void) \| undefined` | Callback to update the search text |
| `isDisabled` | `boolean` | Whether the search field is disabled |
| `isInvalid` | `boolean` | Whether the search field is in an invalid state |
| `isRequired` | `boolean` | Whether the search field is required |
# Select
**Category**: native
**URL**: https://v3.heroui.com/docs/native/components/select
**Source**: https://raw.githubusercontent.com/heroui-inc/heroui/refs/heads/v3/apps/docs/content/docs/native/components/(forms)/select.mdx
> Displays a list of options for the user to pick from — triggered by a button.
## Import
```tsx
import { Select } from 'heroui-native';
```
## Anatomy
```tsx
```
* **Select**: Main container that manages open/close state, value selection and provides context to child components.
* **Select.Trigger**: Clickable element that toggles the select visibility. Wraps any child element with press handlers. Supports `variant` prop (`'default'` or `'unstyled'`).
* **Select.Value**: Displays the selected value or placeholder text. Automatically updates when selection changes. Styling changes based on selection state.
* **Select.TriggerIndicator**: Optional visual indicator showing open/close state. Renders an animated chevron icon by default that rotates when the select opens/closes.
* **Select.Portal**: Renders select content in a portal layer above other content. Ensures proper stacking and positioning.
* **Select.Overlay**: Optional background overlay. Can be transparent or semi-transparent to capture outside clicks.
* **Select.Content**: Container for select content with three presentation modes: popover (floating with positioning), bottom sheet modal, or dialog modal.
* **Select.Close**: Close button for the select. Can accept custom children or uses default close icon.
* **Select.ListLabel**: Label for the list of items with pre-styled typography.
* **Select.Item**: Selectable option item. Handles selection state and press events.
* **Select.ItemLabel**: Displays the label text for an item.
* **Select.ItemDescription**: Optional description text for items with muted styling.
* **Select.ItemIndicator**: Optional indicator shown for selected items. Renders a check icon by default.
## Usage
### Basic Usage
The Select component uses compound parts to create dropdown selection interfaces.
```tsx
```
### With Value Display
Display the selected value in the trigger using the Value component.
```tsx
```
### Popover Presentation
Use popover presentation for floating content with automatic positioning.
```tsx
```
### Width Control
Control the width of the select content using the `width` prop. This only works with popover presentation.
```tsx
{
/* Fixed width in pixels */
}
;
{
/* Match trigger width */
}
;
{
/* Full width (100%) */
}
;
{
/* Auto-size to content (default) */
}
;
```
### Bottom Sheet Presentation
Use bottom sheet for mobile-optimized selection experience.
```tsx
```
### Dialog Presentation
Use dialog presentation for centered modal-style selection.
```tsx
```
### Custom Item Content
Customize item appearance with custom content and indicators.
```tsx
```
### With Render Function
Use a render function on `Select.Item` to access state and customize content based on selection.
```tsx
```
### With Item Description
Add descriptions to items for additional context.
```tsx
```
### With Trigger Indicator
Add a visual indicator to show the open/close state of the select. The indicator rotates when the select opens/closes.
```tsx
```
### Custom Trigger with Unstyled Variant
Use the `unstyled` variant when composing a custom trigger with other components like Button.
```tsx
```
### Controlled Mode
Control the select state programmatically.
```tsx
const [value, setValue] = useState();
const [isOpen, setIsOpen] = useState(false);
;
```
## Example
```tsx
import { Select, Separator } from 'heroui-native';
import React, { useState } from 'react';
type SelectOption = {
value: string;
label: string;
};
const US_STATES: SelectOption[] = [
{ value: 'CA', label: 'California' },
{ value: 'NY', label: 'New York' },
{ value: 'TX', label: 'Texas' },
{ value: 'FL', label: 'Florida' },
];
export default function SelectExample() {
const [value, setValue] = useState();
return (
);
}
```
You can find more examples in the [GitHub repository](https://github.com/heroui-inc/heroui-native/blob/rc/example/src/app/\(home\)/components/select.tsx).
## API Reference
### Select
| prop | type | default | description |
| --------------- | ------------------------------------------------- | ----------- | ---------------------------------------------------------------------- |
| `children` | `ReactNode` | - | The content of the select |
| `value` | `SelectOption \| SelectOption[]` | - | The selected value(s) (controlled mode) |
| `onValueChange` | `(value: SelectOption \| SelectOption[]) => void` | - | Callback when the value changes |
| `defaultValue` | `SelectOption \| SelectOption[]` | - | The default selected value(s) (uncontrolled mode) |
| `isOpen` | `boolean` | - | Whether the select is open (controlled mode) |
| `isDefaultOpen` | `boolean` | - | Whether the select is open when initially rendered (uncontrolled mode) |
| `onOpenChange` | `(isOpen: boolean) => void` | - | Callback when the select open state changes |
| `isDisabled` | `boolean` | `false` | Whether the select is disabled |
| `presentation` | `'popover' \| 'bottom-sheet' \| 'dialog'` | `'popover'` | Presentation mode for the select content |
| `animation` | `SelectRootAnimation` | - | Animation configuration |
| `asChild` | `boolean` | `false` | Whether to render as a child element |
| `...ViewProps` | `ViewProps` | - | All standard React Native View props are supported |
#### SelectRootAnimation
Animation configuration for Select component. Can be:
* `false` or `"disabled"`: Disable only root animations
* `"disable-all"`: Disable all animations including children
* `true` or `undefined`: Use default animations
* `object`: Custom animation configuration
| prop | type | default | description |
| ---------------- | ------------------------------------------------ | ------- | ----------------------------------------------- |
| `state` | `'disabled' \| 'disable-all' \| boolean` | - | Disable animations while customizing properties |
| `entering.value` | `SpringAnimationConfig \| TimingAnimationConfig` | - | Animation configuration for when select opens |
| `exiting.value` | `SpringAnimationConfig \| TimingAnimationConfig` | - | Animation configuration for when select closes |
#### SpringAnimationConfig
| prop | type | default | description |
| -------- | ------------------ | ------- | ----------------------------------------- |
| `type` | `'spring'` | - | Animation type (must be `'spring'`) |
| `config` | `WithSpringConfig` | - | Reanimated spring animation configuration |
#### TimingAnimationConfig
| prop | type | default | description |
| -------- | ------------------ | ------- | ----------------------------------------- |
| `type` | `'timing'` | - | Animation type (must be `'timing'`) |
| `config` | `WithTimingConfig` | - | Reanimated timing animation configuration |
### Select.Trigger
| prop | type | default | description |
| ------------------- | ------------------------- | ----------- | ----------------------------------------------------------------------------------------------------------------- |
| `variant` | `'default' \| 'unstyled'` | `'default'` | The variant of the trigger. `'default'` applies pre-styled container styles, `'unstyled'` removes default styling |
| `children` | `ReactNode` | - | The trigger element content |
| `className` | `string` | - | Additional CSS classes for the trigger |
| `asChild` | `boolean` | `true` | Whether to render as a child element |
| `isDisabled` | `boolean` | - | Whether the trigger is disabled |
| `...PressableProps` | `PressableProps` | - | All standard React Native Pressable props are supported |
### Select.Value
| prop | type | default | description |
| -------------- | ----------- | ------- | -------------------------------------------------- |
| `placeholder` | `string` | - | Placeholder text when no value is selected |
| `className` | `string` | - | Additional CSS classes for the value |
| `...TextProps` | `TextProps` | - | All standard React Native Text props are supported |
**Note:** The value component automatically applies different text colors based on selection state:
* When a value is selected: `text-foreground`
* When no value is selected (placeholder): `text-field-placeholder`
### Select.TriggerIndicator
| prop | type | default | description |
| ----------------------- | --------------------------------- | ------- | ------------------------------------------------------------ |
| `children` | `ReactNode` | - | Custom indicator content. Defaults to animated chevron icon |
| `className` | `string` | - | Additional CSS classes for the trigger indicator |
| `style` | `ViewStyle` | - | Custom styles for the trigger indicator |
| `iconProps` | `SelectTriggerIndicatorIconProps` | - | Chevron icon configuration |
| `animation` | `SelectTriggerIndicatorAnimation` | - | Animation configuration |
| `isAnimatedStyleActive` | `boolean` | `true` | Whether animated styles (react-native-reanimated) are active |
| `...ViewProps` | `ViewProps` | - | All standard React Native View props are supported |
**Note:** The following style properties are occupied by animations and cannot be set via className:
* `transform` (specifically `rotate`) - Animated for open/close rotation transitions
To customize this property, use the `animation` prop. To completely disable animated styles and use your own via className or style prop, set `isAnimatedStyleActive={false}`.
#### SelectTriggerIndicatorIconProps
| prop | type | default | description |
| ------- | -------- | ------- | ------------------------------------------------------ |
| `size` | `number` | `16` | Size of the icon |
| `color` | `string` | - | Color of the icon (defaults to foreground theme color) |
#### SelectTriggerIndicatorAnimation
Animation configuration for Select.TriggerIndicator component. Can be:
* `false` or `"disabled"`: Disable all animations
* `true` or `undefined`: Use default animations (rotation from 0° to -180°)
* `object`: Custom animation configuration
| prop | type | default | description |
| ----------------------- | ----------------------- | -------------------------------------------- | ----------------------------------------------- |
| `state` | `'disabled' \| boolean` | - | Disable animations while customizing properties |
| `rotation.value` | `[number, number]` | `[0, -180]` | Rotation values \[closed, open] in degrees |
| `rotation.springConfig` | `WithSpringConfig` | `{ damping: 140, stiffness: 1000, mass: 4 }` | Spring animation configuration for rotation |
### Select.Portal
| prop | type | default | description |
| -------------------------- | ----------- | ------- | ----------------------------------------------------------------------------------------------------------------------------- |
| `children` | `ReactNode` | - | The portal content (required) |
| `disableFullWindowOverlay` | `boolean` | `false` | When true on iOS, uses View instead of FullWindowOverlay. Enables element inspector; overlay won't appear above native modals |
| `className` | `string` | - | Additional CSS classes for the portal container |
| `hostName` | `string` | - | Optional name of the host element for the portal |
| `forceMount` | `boolean` | - | Whether to force mount the component in the DOM |
| `...ViewProps` | `ViewProps` | - | All standard React Native View props are supported |
### Select.Overlay
| prop | type | default | description |
| ----------------------- | ------------------------ | ------- | ------------------------------------------------------------ |
| `className` | `string` | - | Additional CSS classes for the overlay |
| `animation` | `SelectOverlayAnimation` | - | Animation configuration |
| `isAnimatedStyleActive` | `boolean` | `true` | Whether animated styles (react-native-reanimated) are active |
| `closeOnPress` | `boolean` | `true` | Whether to close the select when overlay is pressed |
| `forceMount` | `boolean` | - | Whether to force mount the component in the DOM |
| `asChild` | `boolean` | `false` | Whether to render as a child element |
| `...Animated.ViewProps` | `Animated.ViewProps` | - | All Reanimated Animated.View props are supported |
#### SelectOverlayAnimation
Animation configuration for Select.Overlay component. Can be:
* `false` or `"disabled"`: Disable all animations
* `true` or `undefined`: Use default animations (progress-based opacity for bottom-sheet/dialog, Keyframe animations for popover)
* `object`: Custom animation configuration
| prop | type | default | description |
| --------------- | -------------------------- | ----------- | ---------------------------------------------------------------------------- |
| `state` | `'disabled' \| boolean` | - | Disable animations while customizing properties |
| `opacity.value` | `[number, number, number]` | `[0, 1, 0]` | Opacity values \[idle, open, close] (for bottom-sheet/dialog presentation) |
| `entering` | `EntryOrExitLayoutType` | - | Custom Keyframe animation for entering transition (for popover presentation) |
| `exiting` | `EntryOrExitLayoutType` | - | Custom Keyframe animation for exiting transition (for popover presentation) |
### Select.Content (Popover Presentation)
| prop | type | default | description |
| ----------------------- | ------------------------------------------------ | --------------- | ------------------------------------------------------ |
| `children` | `ReactNode` | - | The select content |
| `width` | `number \| 'trigger' \| 'content-fit' \| 'full'` | `'content-fit'` | Width sizing strategy for the content |
| `presentation` | `'popover'` | `'popover'` | Presentation mode for the select |
| `placement` | `'top' \| 'bottom' \| 'left' \| 'right'` | `'bottom'` | Placement of the content relative to trigger |
| `align` | `'start' \| 'center' \| 'end'` | `'center'` | Alignment along the placement axis |
| `avoidCollisions` | `boolean` | `true` | Whether to flip placement when close to viewport edges |
| `offset` | `number` | `8` | Distance from trigger element in pixels |
| `alignOffset` | `number` | `0` | Offset along the alignment axis in pixels |
| `className` | `string` | - | Additional CSS classes for the content container |
| `animation` | `SelectContentPopoverAnimation` | - | Animation configuration |
| `forceMount` | `boolean` | - | Whether to force mount the component in the DOM |
| `insets` | `Insets` | - | Screen edge insets to respect when positioning |
| `asChild` | `boolean` | `false` | Whether to render as a child element |
| `...Animated.ViewProps` | `Animated.ViewProps` | - | All Reanimated Animated.View props are supported |
#### SelectContentPopoverAnimation
Animation configuration for Select.Content component (popover presentation). Can be:
* `false` or `"disabled"`: Disable all animations
* `true` or `undefined`: Use default Keyframe animations (translateY/translateX, scale, opacity based on placement)
* `object`: Custom animation configuration with `entering` and/or `exiting` Keyframe animations
| prop | type | default | description |
| ---------- | ----------------------- | ------- | ------------------------------------------------------------------------------------------------------------------------------------------ |
| `state` | `'disabled' \| boolean` | - | Disable animations while customizing properties |
| `entering` | `EntryOrExitLayoutType` | - | Custom Keyframe animation for entering transition (default: Keyframe with translateY/translateX, scale, opacity based on placement, 200ms) |
| `exiting` | `EntryOrExitLayoutType` | - | Custom Keyframe animation for exiting transition (default: Keyframe mirroring entering animation, 150ms) |
### Select.Content (Bottom Sheet Presentation)
| prop | type | default | description |
| --------------------------- | ------------------ | ------- | ------------------------------------------------ |
| `children` | `ReactNode` | - | The bottom sheet content |
| `presentation` | `'bottom-sheet'` | - | Presentation mode for the select |
| `contentContainerClassName` | `string` | - | Additional CSS classes for the content container |
| `...BottomSheetProps` | `BottomSheetProps` | - | All @gorhom/bottom-sheet props are supported |
### Select.Content (Dialog Presentation)
| prop | type | default | description |
| -------------- | -------------------------------------------------------- | ------- | --------------------------------------------------- |
| `children` | `ReactNode` | - | The dialog content |
| `presentation` | `'dialog'` | - | Presentation mode for the select |
| `classNames` | `{ wrapper?: string; content?: string }` | - | Additional CSS classes for wrapper and content |
| `styles` | `Partial>` | - | Styles for different parts of the dialog content |
| `animation` | `SelectContentAnimation` | - | Animation configuration |
| `isSwipeable` | `boolean` | `true` | Whether the dialog content can be swiped to dismiss |
| `forceMount` | `boolean` | - | Whether to force mount the component in the DOM |
| `asChild` | `boolean` | `false` | Whether to render as a child element |
| `...ViewProps` | `ViewProps` | - | All standard React Native View props are supported |
#### `styles`
| prop | type | description |
| --------- | ----------- | -------------------------------- |
| `wrapper` | `ViewStyle` | Styles for the wrapper container |
| `content` | `ViewStyle` | Styles for the dialog content |
#### SelectContentAnimation
Animation configuration for Select.Content component (dialog presentation). Can be:
* `false` or `"disabled"`: Disable all animations
* `true` or `undefined`: Use default Keyframe animations (scale and opacity transitions)
* `object`: Custom animation configuration with `entering` and/or `exiting` Keyframe animations
| prop | type | default | description |
| ---------- | ----------------------- | ------- | -------------------------------------------------------------------------------------------------------- |
| `state` | `'disabled' \| boolean` | - | Disable animations while customizing properties |
| `entering` | `EntryOrExitLayoutType` | - | Custom Keyframe animation for entering transition (default: Keyframe with scale and opacity, 200ms) |
| `exiting` | `EntryOrExitLayoutType` | - | Custom Keyframe animation for exiting transition (default: Keyframe mirroring entering animation, 150ms) |
### Select.Close
Select.Close extends [CloseButton](./close-button) and automatically handles select dismissal when pressed.
### Select.ListLabel
| prop | type | default | description |
| -------------- | ----------- | ------- | -------------------------------------------------- |
| `children` | `ReactNode` | - | The label text content |
| `className` | `string` | - | Additional CSS classes for the list label |
| `...TextProps` | `TextProps` | - | All standard React Native Text props are supported |
### Select.Item
| prop | type | default | description |
| ------------------- | ------------------------------------------------------------ | ------- | -------------------------------------------------------------------------- |
| `children` | `ReactNode \| ((props: SelectItemRenderProps) => ReactNode)` | - | Custom item content. Defaults to label and indicator, or a render function |
| `value` | `any` | - | The value associated with this item (required) |
| `label` | `string` | - | The label text for this item (required) |
| `isDisabled` | `boolean` | `false` | Whether this item is disabled |
| `className` | `string` | - | Additional CSS classes for the item |
| `...PressableProps` | `PressableProps` | - | All standard React Native Pressable props are supported |
#### SelectItemRenderProps
When using a render function for `children`, the following props are provided:
| property | type | description |
| ------------ | --------- | --------------------------------------- |
| `isSelected` | `boolean` | Whether this item is currently selected |
| `value` | `string` | The value of the item |
| `isDisabled` | `boolean` | Whether the item is disabled |
### Select.ItemLabel
| prop | type | default | description |
| -------------- | ----------- | ------- | -------------------------------------------------- |
| `className` | `string` | - | Additional CSS classes for the item label |
| `...TextProps` | `TextProps` | - | All standard React Native Text props are supported |
### Select.ItemDescription
| prop | type | default | description |
| -------------- | ----------- | ------- | -------------------------------------------------- |
| `children` | `ReactNode` | - | The description text content |
| `className` | `string` | - | Additional CSS classes for the item description |
| `...TextProps` | `TextProps` | - | All standard React Native Text props are supported |
### Select.ItemIndicator
| prop | type | default | description |
| -------------- | ------------------------------ | ------- | -------------------------------------------------- |
| `children` | `ReactNode` | - | Custom indicator content. Defaults to check icon |
| `className` | `string` | - | Additional CSS classes for the item indicator |
| `iconProps` | `SelectItemIndicatorIconProps` | - | Check icon configuration |
| `...ViewProps` | `ViewProps` | - | All standard React Native View props are supported |
#### SelectItemIndicatorIconProps
| prop | type | default | description |
| ------- | -------- | ---------------- | ----------------- |
| `size` | `number` | `16` | Size of the icon |
| `color` | `string` | `--colors-muted` | Color of the icon |
## Hooks
### useSelect
Hook to access the Select root context. Returns the select state and control functions.
```tsx
import { useSelect } from 'heroui-native';
const {
isOpen,
onOpenChange,
isDefaultOpen,
isDisabled,
presentation,
triggerPosition,
setTriggerPosition,
contentLayout,
setContentLayout,
nativeID,
value,
onValueChange,
} = useSelect();
```
#### Return Value
| property | type | description |
| -------------------- | -------------------------------------------------- | --------------------------------------------------------- |
| `isOpen` | `boolean` | Whether the select is currently open |
| `onOpenChange` | `(open: boolean) => void` | Callback to change the open state |
| `isDefaultOpen` | `boolean \| undefined` | Whether the select is open by default (uncontrolled mode) |
| `isDisabled` | `boolean \| undefined` | Whether the select is disabled |
| `presentation` | `'popover' \| 'bottom-sheet' \| 'dialog'` | Presentation mode for the select content |
| `triggerPosition` | `LayoutPosition \| null` | Position of the trigger element relative to viewport |
| `setTriggerPosition` | `(position: LayoutPosition \| null) => void` | Updates the trigger element's position |
| `contentLayout` | `LayoutRectangle \| null` | Layout measurements of the select content |
| `setContentLayout` | `(layout: LayoutRectangle \| null) => void` | Updates the content layout measurements |
| `nativeID` | `string` | Unique identifier for the select instance |
| `value` | `SelectOption \| SelectOption[]` | Currently selected option |
| `onValueChange` | `(option: SelectOption \| SelectOption[]) => void` | Callback fired when the selected value changes |
**Note:** This hook must be used within a `Select` component. It will throw an error if called outside of the select context.
### useSelectAnimation
Hook to access the Select animation state values within custom components or compound components.
```tsx
import { useSelectAnimation } from 'heroui-native';
const { selectState, progress, isDragging, isGestureReleaseAnimationRunning } =
useSelectAnimation();
```
#### Return Value
| property | type | description |
| ---------------------------------- | ---------------------- | ---------------------------------------------------------- |
| `progress` | `SharedValue` | Progress value for animations (0=idle, 1=open, 2=close) |
| `isDragging` | `SharedValue` | Whether the select content is currently being dragged |
| `isGestureReleaseAnimationRunning` | `SharedValue` | Whether the gesture release animation is currently running |
**Note:** This hook must be used within a `Select` component. It will throw an error if called outside of the select animation context.
#### SelectOption
| property | type | description |
| -------- | -------- | ---------------------------- |
| `value` | `string` | The value of the option |
| `label` | `string` | The label text of the option |
### useSelectItem
Hook to access the Select Item context. Returns the item's value and label.
```tsx
import { useSelectItem } from 'heroui-native';
const { itemValue, label } = useSelectItem();
```
#### Return Value
| property | type | description |
| ----------- | -------- | ---------------------------------- |
| `itemValue` | `string` | The value of the current item |
| `label` | `string` | The label text of the current item |
## Special Notes
### Element Inspector (iOS)
Select uses FullWindowOverlay on iOS. To enable the React Native element inspector during development, set `disableFullWindowOverlay={true}` on `Select.Portal`. Tradeoff: the select dropdown will not appear above native modals when disabled.
# TextArea
**Category**: native
**URL**: https://v3.heroui.com/docs/native/components/text-area
**Source**: https://raw.githubusercontent.com/heroui-inc/heroui/refs/heads/v3/apps/docs/content/docs/native/components/(forms)/text-area.mdx
> A multiline text input component with styled border and background for collecting longer user input.
## Import
```tsx
import { TextArea } from 'heroui-native';
```
## Usage
### Basic Usage
TextArea can be used standalone or within a TextField component.
```tsx
import { TextArea } from 'heroui-native';
```
### Within TextField
TextArea works seamlessly with TextField for complete form structure.
```tsx
import { Description, Label, TextArea, TextField } from 'heroui-native';
Please provide as much detail as possible.
```
### With Validation
Display error state when the text area is invalid.
```tsx
import { FieldError, Label, TextArea, TextField } from 'heroui-native';
Please enter a valid message
```
### Disabled State
Disable the text area to prevent interaction.
```tsx
import { Label, TextArea, TextField } from 'heroui-native';
```
### With Variant
Use different variants to style the text area based on context.
```tsx
import { Label, TextArea, TextField } from 'heroui-native';
```
### Custom Styling
Customize the text area appearance using className.
```tsx
import { Label, TextArea, TextField } from 'heroui-native';
```
## Example
```tsx
import { Description, FieldError, Label, TextArea, TextField } from 'heroui-native';
import { View } from 'react-native';
export default function TextAreaExample() {
return (
Default variant with primary stylingSecondary variant for surfaces
);
}
```
You can find more examples in the [GitHub repository](https://github.com/heroui-inc/heroui-native/blob/rc/example/src/app/\(home\)/components/text-area.tsx).
## API Reference
TextArea extends [Input](./input) component and inherits all its props. The only differences are default values: `multiline` defaults to `true` and `textAlignVertical` defaults to `'top'`.
# TextField
**Category**: native
**URL**: https://v3.heroui.com/docs/native/components/text-field
**Source**: https://raw.githubusercontent.com/heroui-inc/heroui/refs/heads/v3/apps/docs/content/docs/native/components/(forms)/text-field.mdx
> A text input component with label, description, and error handling for collecting user input.
## Import
```tsx
import { TextField } from 'heroui-native';
```
## Anatomy
```tsx
......
```
* **TextField**: Root container that provides spacing and state management
* **Label**: Label with optional asterisk for required fields (from [Label](./label) component)
* **Input**: Input container with animated border and background (from [Input](./input) component)
* **Description**: Secondary descriptive helper text (from [Description](./description) component)
* **FieldError**: Validation error message display (from [FieldError](./field-error) component)
## Usage
### Basic Usage
TextField provides a complete form input structure with label and description.
```tsx
We'll never share your email
```
### With Required Field
Mark fields as required to show an asterisk in the label.
```tsx
```
### With Validation
Display error messages when the field is invalid.
```tsx
import { FieldError, Input, Label, TextField } from 'heroui-native';
Please enter a valid email;
```
### With Local Invalid State Override
Override the context's invalid state for individual components.
```tsx
import {
Description,
FieldError,
Input,
Label,
TextField,
} from 'heroui-native';
This shows despite input being invalid
Email format is incorrect;
```
### Multiline Input
Create text areas for longer content.
```tsx
Maximum 500 characters
```
### Disabled State
Disable the entire field to prevent interaction.
```tsx
```
### With Variant
Use different variants to style the input based on context.
```tsx
```
### Custom Styling
Customize the input appearance using className.
```tsx
```
## Example
```tsx
import { Ionicons } from '@expo/vector-icons';
import { Description, Input, Label, TextField } from 'heroui-native';
import { useState } from 'react';
import { Pressable, View } from 'react-native';
import { withUniwind } from 'uniwind';
const StyledIonicons = withUniwind(Ionicons);
export const TextInputContent = () => {
const [email, setEmail] = useState('');
const [password, setPassword] = useState('');
const [isPasswordVisible, setIsPasswordVisible] = useState(false);
return (
We'll never share your email with anyone else.
setIsPasswordVisible(!isPasswordVisible)}
>
Password must be at least 6 characters
);
};
```
You can find more examples in the [GitHub repository](https://github.com/heroui-inc/heroui-native/blob/rc/example/src/app/\(home\)/components/text-field.tsx).
## API Reference
### TextField
| prop | type | default | description |
| ------------ | ---------------------------- | ----------- | ----------------------------------------------------------------------------------------- |
| children | `React.ReactNode` | - | Content to render inside the text field |
| isDisabled | `boolean` | `false` | Whether the entire text field is disabled |
| isInvalid | `boolean` | `false` | Whether the text field is in an invalid state |
| isRequired | `boolean` | `false` | Whether the text field is required (shows asterisk) |
| className | `string` | - | Custom class name for the root element |
| animation | `"disable-all" \| undefined` | `undefined` | Animation configuration. Use `"disable-all"` to disable all animations including children |
| ...ViewProps | `ViewProps` | - | All standard React Native View props are supported |
> **Note**: For Label, Input, Description, and FieldError components, see their respective documentation:
>
> * [Label documentation](./label)
> * [Input documentation](./input)
> * [Description documentation](./description)
> * [FieldError documentation](./field-error)
>
> These components automatically consume form state from TextField via the form-item-state context.
## Hooks
### useTextField
Hook to access the TextField context values. Must be used within a `TextField` component.
```tsx
import { TextField, useTextField } from 'heroui-native';
function CustomComponent() {
const { isDisabled, isInvalid, isRequired } = useTextField();
// Use the context values...
}
```
#### Returns
| property | type | description |
| ---------- | --------- | --------------------------------------------- |
| isDisabled | `boolean` | Whether the entire text field is disabled |
| isInvalid | `boolean` | Whether the text field is in an invalid state |
| isRequired | `boolean` | Whether the text field is required |
# Card
**Category**: native
**URL**: https://v3.heroui.com/docs/native/components/card
**Source**: https://raw.githubusercontent.com/heroui-inc/heroui/refs/heads/v3/apps/docs/content/docs/native/components/(layout)/card.mdx
> Displays a card container with flexible layout sections for structured content.
## Import
```tsx
import { Card } from 'heroui-native';
```
## Anatomy
```tsx
............
```
* **Card**: Main container that extends Surface component. Provides base card structure with configurable surface variants and handles overall layout.
* **Card.Header**: Header section for top-aligned content like icons or badges.
* **Card.Body**: Main content area with flex-1 that expands to fill all available space between Card.Header and Card.Footer.
* **Card.Title**: Title text with foreground color and medium font weight.
* **Card.Description**: Description text with muted color and smaller font size.
* **Card.Footer**: Footer section for bottom-aligned actions like buttons.
## Usage
### Basic Usage
The Card component creates a container with built-in sections for organized content.
```tsx
...
```
### With Title and Description
Combine title and description components for structured text content.
```tsx
......
```
### With Header and Footer
Add header and footer sections for icons, badges, or actions.
```tsx
.........
```
### Variants
Control the card's background appearance using different variants.
```tsx
............
```
### Horizontal Layout
Create horizontal cards by using flex-row styling.
```tsx
```
### Background Image
Use an image as an absolute positioned background.
```tsx
...
```
## Example
```tsx
import { Button, Card } from 'heroui-native';
import { Ionicons } from '@expo/vector-icons';
import { View } from 'react-native';
export default function CardExample() {
return (
$450Living room Sofa • Collection 2025
This sofa is perfect for modern tropical spaces, baroque inspired
spaces.
);
}
```
You can find more examples in the [GitHub repository](https://github.com/heroui-inc/heroui-native/blob/rc/example/src/app/\(home\)/components/card.tsx).
## API Reference
### Card
| prop | type | default | description |
| -------------- | --------------------------------------------------------- | ----------- | ----------------------------------------------------------------------------------------- |
| `children` | `React.ReactNode` | - | Content to be rendered inside the card |
| `variant` | `'default' \| 'secondary' \| 'tertiary' \| 'transparent'` | `'default'` | Visual variant of the card surface |
| `className` | `string` | - | Additional CSS classes to apply |
| `animation` | `"disable-all" \| undefined` | `undefined` | Animation configuration. Use `"disable-all"` to disable all animations including children |
| `...ViewProps` | `ViewProps` | - | All standard React Native View props are supported |
### Card.Header
| prop | type | default | description |
| -------------- | ----------------- | ------- | -------------------------------------------------- |
| `children` | `React.ReactNode` | - | Children elements to be rendered inside the header |
| `className` | `string` | - | Additional CSS classes |
| `...ViewProps` | `ViewProps` | - | All standard React Native View props are supported |
### Card.Body
| prop | type | default | description |
| -------------- | ----------------- | ------- | -------------------------------------------------- |
| `children` | `React.ReactNode` | - | Children elements to be rendered inside the body |
| `className` | `string` | - | Additional CSS classes |
| `...ViewProps` | `ViewProps` | - | All standard React Native View props are supported |
### Card.Footer
| prop | type | default | description |
| -------------- | ----------------- | ------- | -------------------------------------------------- |
| `children` | `React.ReactNode` | - | Children elements to be rendered inside the footer |
| `className` | `string` | - | Additional CSS classes |
| `...ViewProps` | `ViewProps` | - | All standard React Native View props are supported |
### Card.Title
| prop | type | default | description |
| -------------- | ----------------- | ------- | -------------------------------------------------- |
| `children` | `React.ReactNode` | - | Children elements to be rendered as the title text |
| `className` | `string` | - | Additional CSS classes |
| `...TextProps` | `TextProps` | - | All standard React Native Text props are supported |
### Card.Description
| prop | type | default | description |
| -------------- | ----------------- | ------- | -------------------------------------------------------- |
| `children` | `React.ReactNode` | - | Children elements to be rendered as the description text |
| `className` | `string` | - | Additional CSS classes |
| `...TextProps` | `TextProps` | - | All standard React Native Text props are supported |
# Separator
**Category**: native
**URL**: https://v3.heroui.com/docs/native/components/separator
**Source**: https://raw.githubusercontent.com/heroui-inc/heroui/refs/heads/v3/apps/docs/content/docs/native/components/(layout)/separator.mdx
> A simple line to separate content visually.
## Import
```tsx
import { Separator } from "heroui-native";
```
## Anatomy
```tsx
```
* **Separator**: A simple line component that separates content visually. Can be oriented horizontally or vertically, with customizable thickness and variant styles.
## Usage
### Basic Usage
The Separator component creates a visual separation between content sections.
```tsx
```
### Orientation
Control the direction of the separator with the `orientation` prop.
```tsx
Horizontal separatorContent belowLeftRight
```
### Variants
Choose between thin and thick variants for different visual emphasis.
```tsx
```
### Custom Thickness
Set a specific thickness value for precise control.
```tsx
```
## Example
```tsx
import { Separator, Surface } from 'heroui-native';
import { Text, View } from 'react-native';
export default function SeparatorExample() {
return (
HeroUI Native
A modern React Native component library.
ComponentsThemesExamples
);
}
```
You can find more examples in the [GitHub repository](https://github.com/heroui-inc/heroui-native/blob/rc/example/src/app/\(home\)/components/separator.tsx).
## API Reference
### Separator
| prop | type | default | description |
| -------------- | ---------------------------- | -------------- | -------------------------------------------------------------------------------------------- |
| `variant` | `'thin' \| 'thick'` | `'thin'` | Variant style of the separator |
| `orientation` | `'horizontal' \| 'vertical'` | `'horizontal'` | Orientation of the separator |
| `thickness` | `number` | `undefined` | Custom thickness in pixels. Controls height for horizontal or width for vertical orientation |
| `className` | `string` | `undefined` | Additional CSS classes to apply |
| `...ViewProps` | `ViewProps` | - | All standard React Native View props are supported |
# Surface
**Category**: native
**URL**: https://v3.heroui.com/docs/native/components/surface
**Source**: https://raw.githubusercontent.com/heroui-inc/heroui/refs/heads/v3/apps/docs/content/docs/native/components/(layout)/surface.mdx
> Container component that provides elevation and background styling.
## Import
```tsx
import { Surface } from 'heroui-native';
```
## Anatomy
The Surface component is a container that provides elevation and background styling. It accepts children and can be customized with variants and styling props.
```tsx
...
```
* **Surface**: Main container component that provides consistent padding, background styling, and elevation through variants.
## Usage
### Basic Usage
The Surface component creates a container with consistent padding and styling.
```tsx
...
```
### Variants
Control the visual appearance with different surface levels.
```tsx
...
...
...
```
### Nested Surfaces
Create visual hierarchy by nesting surfaces with different variants.
```tsx
...
...
...
```
### Custom Styling
Apply custom styles using className or style props.
```tsx
...
...
```
### Disable All Animations
Disable all animations including children by using the `"disable-all"` value for the `animation` prop.
```tsx
{
/* Disable all animations including children */
}
No Animations;
```
## Example
```tsx
import { Surface } from 'heroui-native';
import { Text, View } from 'react-native';
export default function SurfaceExample() {
return (
Surface Content
This is a default surface variant. It uses bg-surface styling.
Surface Content
This is a secondary surface variant. It uses bg-surface-secondary
styling.
Surface Content
This is a tertiary surface variant. It uses bg-surface-tertiary
styling.
);
}
```
You can find more examples in the [GitHub repository](https://github.com/heroui-inc/heroui-native/blob/rc/example/src/app/\(home\)/components/surface.tsx).
## API Reference
### Surface
| prop | type | default | description |
| -------------- | --------------------------------------------------------- | ----------- | ----------------------------------------------------------------------------------------- |
| `variant` | `'default' \| 'secondary' \| 'tertiary' \| 'transparent'` | `'default'` | Visual variant controlling background color and border |
| `children` | `React.ReactNode` | - | Content to be rendered inside the surface |
| `className` | `string` | - | Additional CSS classes to apply |
| `animation` | `"disable-all" \| undefined` | `undefined` | Animation configuration. Use `"disable-all"` to disable all animations including children |
| `...ViewProps` | `ViewProps` | - | All standard React Native View props are supported |
# Avatar
**Category**: native
**URL**: https://v3.heroui.com/docs/native/components/avatar
**Source**: https://raw.githubusercontent.com/heroui-inc/heroui/refs/heads/v3/apps/docs/content/docs/native/components/(media)/avatar.mdx
> Displays a user avatar with support for images, text initials, or fallback icons.
## Import
```tsx
import { Avatar } from 'heroui-native';
```
## Anatomy
```tsx
```
* **Avatar**: Main container that manages avatar display state. Provides size and color context to child components. Supports animation configuration to control all child animations.
* **Avatar.Image**: Optional image component that displays the avatar image. Handles loading states and errors automatically with opacity-based fade-in animation.
* **Avatar.Fallback**: Optional fallback component shown when image fails to load or is unavailable. Displays a default person icon when no children are provided. Supports configurable entering animations with delay support.
## Usage
### Basic Usage
The Avatar component displays a default person icon when no image or text is provided.
```tsx
```
### With Image
Display an avatar image with automatic fallback handling.
```tsx
JD
```
### With Text Initials
Show text initials as the avatar content.
```tsx
AB
```
### With Custom Icon
Provide a custom icon as fallback content.
```tsx
```
### Sizes
Control the avatar size with the size prop.
```tsx
```
### Variants
Choose between different visual styles with the `variant` prop.
```tsx
DFSF
```
### Colors
Apply different color variants to the avatar.
```tsx
DFACSCWRDG
```
### Delayed Fallback
Show fallback after a delay to prevent flashing during image load.
```tsx
NA
```
### Custom Image Component
Use a custom image component with the asChild prop.
```tsx
import { Image } from 'expo-image';
EI;
```
### Animation Control
Control animations at different levels of the Avatar component.
#### Disable All Animations
Disable all animations including children from the root component:
```tsx
JD
```
#### Custom Image Animation
Customize the image opacity animation:
```tsx
JD
```
#### Custom Fallback Animation
Customize the fallback entering animation:
```tsx
import { FadeInDown } from 'react-native-reanimated';
JD
;
```
#### Disable Individual Animations
Disable animations for specific components:
```tsx
JD
```
## Example
```tsx
import { Avatar } from 'heroui-native';
import { View } from 'react-native';
export default function AvatarExample() {
const users = [
{ id: 1, image: 'https://example.com/user1.jpg', name: 'John Doe' },
{ id: 2, image: 'https://example.com/user2.jpg', name: 'Jane Smith' },
{ id: 3, image: 'https://example.com/user3.jpg', name: 'Bob Johnson' },
];
return (
{users.map((user) => (
{user.name
.split(' ')
.map((n) => n[0])
.join('')}
))}
);
}
```
You can find more examples in the [GitHub repository](https://github.com/heroui-inc/heroui-native/blob/rc/example/src/app/\(home\)/components/avatar.tsx).
## API Reference
### Avatar
| prop | type | default | description |
| -------------- | ------------------------------------------------------------- | ----------- | ----------------------------------------------------------------------------------------- |
| `children` | `React.ReactNode` | - | Avatar content (Image and/or Fallback components) |
| `size` | `'sm' \| 'md' \| 'lg'` | `'md'` | Size of the avatar |
| `variant` | `'default' \| 'soft'` | `'default'` | Visual variant of the avatar |
| `color` | `'default' \| 'accent' \| 'success' \| 'warning' \| 'danger'` | `'accent'` | Color variant of the avatar |
| `className` | `string` | - | Additional CSS classes to apply |
| `animation` | `"disable-all"` \| `undefined` | `undefined` | Animation configuration. Use `"disable-all"` to disable all animations including children |
| `alt` | `string` | - | Alternative text description for accessibility |
| `...ViewProps` | `ViewProps` | - | All standard React Native View props are supported |
### Avatar.Image
Props extend different base types depending on the `asChild` prop value:
* When `asChild={false}` (default): extends `AnimatedProps` from React Native Reanimated
* When `asChild={true}`: extends primitive image props for custom image components
**Note:** When using `asChild={true}` with custom image components, the `className` prop may not be applied in some cases depending on the custom component's implementation. Ensure your custom component properly handles style props.
| prop | type | default | description |
| ----------------------- | ---------------------------------------------- | ------- | ------------------------------------------------------------ |
| `source` | `ImageSourcePropType` | - | Image source (required when `asChild={false}`) |
| `asChild` | `boolean` | `false` | Whether to use a custom image component as child |
| `className` | `string` | - | Additional CSS classes to apply |
| `animation` | `AvatarImageAnimation` | - | Animation configuration |
| `isAnimatedStyleActive` | `boolean` | `true` | Whether animated styles (react-native-reanimated) are active |
| `...AnimatedProps` | `AnimatedProps` or primitive props | - | Additional props based on `asChild` value |
#### AvatarImageAnimation
Animation configuration for avatar image component. Can be:
* `false` or `"disabled"`: Disable all animations
* `true` or `undefined`: Use default animations
* `object`: Custom animation configuration
| prop | type | default | description |
| ---------------------- | ----------------------- | --------------------------------------------------- | ----------------------------------------------------- |
| `state` | `'disabled' \| boolean` | - | Disable animations while customizing properties |
| `opacity.value` | `[number, number]` | `[0, 1]` | Opacity values \[initial, loaded] for image animation |
| `opacity.timingConfig` | `WithTimingConfig` | `{ duration: 200, easing: Easing.in(Easing.ease) }` | Animation timing configuration |
**Note:** Animation is automatically disabled when `asChild={true}`
### Avatar.Fallback
| prop | type | default | description |
| ----------------------- | ------------------------------------------------------------- | --------------------- | --------------------------------------------------------------------------------- |
| `children` | `React.ReactNode` | - | Fallback content (text, icon, or custom element) |
| `delayMs` | `number` | `0` | Delay in milliseconds before showing the fallback (applied to entering animation) |
| `color` | `'default' \| 'accent' \| 'success' \| 'warning' \| 'danger'` | inherited from parent | Color variant of the fallback |
| `className` | `string` | - | Additional CSS classes for the container |
| `classNames` | `ElementSlots` | - | Additional CSS classes for different parts |
| `styles` | `{ container?: ViewStyle; text?: TextStyle }` | - | Styles for different parts of the avatar fallback |
| `textProps` | `TextProps` | - | Props to pass to Text component when children is a string |
| `iconProps` | `PersonIconProps` | - | Props to customize the default person icon |
| `animation` | `AvatarFallbackAnimation` | - | Animation configuration |
| `...Animated.ViewProps` | `Animated.ViewProps` | - | All Reanimated Animated.View props are supported |
**classNames prop:** `ElementSlots` provides type-safe CSS classes for different parts of the fallback component. Available slots: `container`, `text`.
#### `styles`
| prop | type | description |
| ----------- | ----------- | --------------------------- |
| `container` | `ViewStyle` | Styles for the container |
| `text` | `TextStyle` | Styles for the text content |
#### AvatarFallbackAnimation
Animation configuration for avatar fallback component. Can be:
* `false` or `"disabled"`: Disable all animations
* `true` or `undefined`: Use default animations
* `object`: Custom animation configuration
| prop | type | default | description |
| ---------------- | ----------------------- | -------------------------------------------------------------------------------------- | ----------------------------------------------- |
| `state` | `'disabled' \| boolean` | - | Disable animations while customizing properties |
| `entering.value` | `EntryOrExitLayoutType` | `FadeIn` `.duration(200)` `.easing(Easing.in(Easing.ease))` `.delay(0)` | Custom entering animation for fallback |
#### PersonIconProps
| prop | type | description |
| ------- | -------- | ------------------------------------- |
| `size` | `number` | Size of the icon in pixels (optional) |
| `color` | `string` | Color of the icon (optional) |
## Hooks
### useAvatar Hook
Hook to access Avatar primitive root context. Provides access to avatar status.
**Note:** The `status` property is particularly useful for adding a skeleton loader while the image is loading.
```tsx
import { Avatar, useAvatar, Skeleton } from 'heroui-native';
function AvatarWithSkeleton() {
return (
JD
);
}
function AvatarContent() {
const { status } = useAvatar();
if (status === 'loading') {
return ;
}
return null;
}
```
| property | type | description |
| ----------- | ---------------------------------------------------- | ----------------------------------------------------------- |
| `status` | `'loading' \| 'loaded' \| 'error'` | Current loading state of the avatar image. |
| `setStatus` | `(status: 'loading' \| 'loaded' \| 'error') => void` | Function to manually set the avatar status (advanced usage) |
**Status Values:**
* `'loading'`: Image is currently being loaded. Use this state to show a skeleton loader.
* `'loaded'`: Image has successfully loaded.
* `'error'`: Image failed to load or source is invalid. The fallback component is automatically shown in this state.
# Accordion
**Category**: native
**URL**: https://v3.heroui.com/docs/native/components/accordion
**Source**: https://raw.githubusercontent.com/heroui-inc/heroui/refs/heads/v3/apps/docs/content/docs/native/components/(navigation)/accordion.mdx
> A collapsible content panel for organizing information in a compact space
## Import
```tsx
import { Accordion } from 'heroui-native';
```
## Anatomy
```tsx
...
......
```
* **Accordion**: Main container that manages the accordion state and behavior. Controls expansion/collapse of items, supports single or multiple selection modes, and provides variant styling (default or surface).
* **Accordion.Item**: Container for individual accordion items. Wraps the trigger and content, managing the expanded state for each item.
* **Accordion.Trigger**: Interactive element that toggles item expansion. Built on Header and Trigger primitives.
* **Accordion.Indicator**: Optional visual indicator showing expansion state. Defaults to an animated chevron icon that rotates based on item state.
* **Accordion.Content**: Container for expandable content. Animated with layout transitions for smooth expand/collapse effects.
## Usage
### Basic Usage
The Accordion component uses compound parts to create expandable content sections.
```tsx
...
...
```
### Single Selection Mode
Allow only one item to be expanded at a time.
```tsx
............
```
### Multiple Selection Mode
Allow multiple items to be expanded simultaneously.
```tsx
..................
```
### Surface Variant
Apply a surface container style to the accordion.
```tsx
...
...
```
### Custom Indicator
Replace the default chevron indicator with custom content.
```tsx
...
...
```
### Without Separators
Hide the separators between accordion items.
```tsx
............
```
### Custom Styling
Apply custom styles using className, classNames, or styles props.
```tsx
......
```
### With PressableFeedback
Use `Accordion.Trigger` with `asChild` prop and wrap content with `PressableFeedback` to add custom press feedback animations.
```tsx
import { Accordion, PressableFeedback } from 'heroui-native';
import { View } from 'react-native';
Item Title...;
```
## Example
```tsx
import { Accordion, useThemeColor } from 'heroui-native';
import { Ionicons } from '@expo/vector-icons';
import { View, Text } from 'react-native';
export default function AccordionExample() {
const themeColorMuted = useThemeColor('muted');
const accordionData = [
{
id: '1',
title: 'How do I place an order?',
icon: ,
content:
'Lorem ipsum dolor sit amet consectetur. Netus nunc mauris risus consequat. Libero placerat dignissim consectetur nisl.',
},
{
id: '2',
title: 'What payment methods do you accept?',
icon: ,
content:
'Lorem ipsum dolor sit amet consectetur. Netus nunc mauris risus consequat. Libero placerat dignissim consectetur nisl.',
},
{
id: '3',
title: 'How much does shipping cost?',
icon: ,
content:
'Lorem ipsum dolor sit amet consectetur. Netus nunc mauris risus consequat. Libero placerat dignissim consectetur nisl.',
},
];
return (
{accordionData.map((item) => (
{item.icon}
{item.title}
{item.content}
))}
);
}
```
You can find more examples in the [GitHub repository](https://github.com/heroui-inc/heroui-native/blob/rc/example/src/app/\(home\)/components/accordion.tsx).
## API Reference
### Accordion
| prop | type | default | description |
| ----------------------- | -------------------------------------------------- | ----------- | -------------------------------------------------------------- |
| `children` | `React.ReactNode` | - | Children elements to be rendered inside the accordion |
| `selectionMode` | `'single' \| 'multiple'` | - | Whether the accordion allows single or multiple expanded items |
| `variant` | `'default' \| 'surface'` | `'default'` | Visual variant of the accordion |
| `hideSeparator` | `boolean` | `false` | Whether to hide the separator between accordion items |
| `defaultValue` | `string \| string[] \| undefined` | - | Default expanded item(s) in uncontrolled mode |
| `value` | `string \| string[] \| undefined` | - | Controlled expanded item(s) |
| `isDisabled` | `boolean` | - | Whether all accordion items are disabled |
| `isCollapsible` | `boolean` | `true` | Whether expanded items can be collapsed |
| `animation` | `AccordionRootAnimation` | - | Animation configuration for accordion |
| `className` | `string` | - | Additional CSS classes for the container |
| `classNames` | `ElementSlots` | - | Additional CSS classes for the slots |
| `styles` | `Partial>` | - | Styles for different parts of the accordion root |
| `onValueChange` | `(value: string \| string[] \| undefined) => void` | - | Callback when expanded items change |
| `...Animated.ViewProps` | `Animated.ViewProps` | - | All Reanimated Animated.View props are supported |
#### `ElementSlots`
| prop | type | description |
| ----------- | -------- | ------------------------------------------------- |
| `container` | `string` | Custom class name for the accordion container |
| `separator` | `string` | Custom class name for the separator between items |
#### `styles`
| prop | type | description |
| ----------- | ----------- | -------------------------------------- |
| `container` | `ViewStyle` | Styles for the accordion container |
| `separator` | `ViewStyle` | Styles for the separator between items |
#### AccordionRootAnimation
Animation configuration for accordion root component. Can be:
* `false` or `"disabled"`: Disable only root animations
* `"disable-all"`: Disable all animations including children
* `true` or `undefined`: Use default animations
* `object`: Custom animation configuration
| prop | type | default | description |
| -------------- | ---------------------------------------- | --------------------------------------------------------------------------------------------------- | ------------------------------------------------- |
| `state` | `'disabled' \| 'disable-all' \| boolean` | - | Disable animations while customizing properties |
| `layout.value` | `LayoutTransition` | `LinearTransition` `.springify()` `.damping(140)` `.stiffness(1600)` `.mass(4)` | Custom layout animation for accordion transitions |
### Accordion.Item
| prop | type | default | description |
| ----------------------- | --------------------------------------------------------------------------- | ------- | -------------------------------------------------------------------------------- |
| `children` | `React.ReactNode \| ((props: AccordionItemRenderProps) => React.ReactNode)` | - | Children elements to be rendered inside the accordion item, or a render function |
| `value` | `string` | - | Unique value to identify this item |
| `isDisabled` | `boolean` | - | Whether this specific item is disabled |
| `className` | `string` | - | Additional CSS classes |
| `...Animated.ViewProps` | `Animated.ViewProps` | - | All Reanimated Animated.View props are supported |
#### AccordionItemRenderProps
| prop | type | description |
| ------------ | --------- | ------------------------------------------------ |
| `isExpanded` | `boolean` | Whether the accordion item is currently expanded |
| `value` | `string` | Unique value identifier for this accordion item |
### Accordion.Trigger
| prop | type | default | description |
| ------------------- | ----------------- | ------- | ------------------------------------------------------- |
| `children` | `React.ReactNode` | - | Children elements to be rendered inside the trigger |
| `className` | `string` | - | Additional CSS classes |
| `isDisabled` | `boolean` | - | Whether the trigger is disabled |
| `...PressableProps` | `PressableProps` | - | All standard React Native Pressable props are supported |
### Accordion.Indicator
| prop | type | default | description |
| ----------------------- | ----------------------------- | ------- | ---------------------------------------------------------------------- |
| `children` | `React.ReactNode` | - | Custom indicator content, if not provided defaults to animated chevron |
| `className` | `string` | - | Additional CSS classes |
| `iconProps` | `AccordionIndicatorIconProps` | - | Icon configuration |
| `animation` | `AccordionIndicatorAnimation` | - | Animation configuration for indicator |
| `isAnimatedStyleActive` | `boolean` | `true` | Whether animated styles (react-native-reanimated) are active |
| `...Animated.ViewProps` | `Animated.ViewProps` | - | All Reanimated Animated.View props are supported |
#### AccordionIndicatorIconProps
| prop | type | default | description |
| ------- | -------- | ------------ | ----------------- |
| `size` | `number` | `16` | Size of the icon |
| `color` | `string` | `foreground` | Color of the icon |
#### AccordionIndicatorAnimation
Animation configuration for accordion indicator component. Can be:
* `false` or `"disabled"`: Disable all animations
* `true` or `undefined`: Use default animations
* `object`: Custom animation configuration
| prop | type | default | description |
| ----------------------- | ----------------------- | -------------------------------------------- | ------------------------------------------------- |
| `state` | `'disabled' \| boolean` | - | Disable animations while customizing properties |
| `rotation.value` | `[number, number]` | `[0, -180]` | Rotation values \[collapsed, expanded] in degrees |
| `rotation.springConfig` | `WithSpringConfig` | `{ damping: 140, stiffness: 1000, mass: 4 }` | Spring animation configuration for rotation |
### Accordion.Content
| prop | type | default | description |
| -------------- | --------------------------- | ------- | --------------------------------------------------- |
| `children` | `React.ReactNode` | - | Children elements to be rendered inside the content |
| `className` | `string` | - | Additional CSS classes |
| `animation` | `AccordionContentAnimation` | - | Animation configuration for content |
| `...ViewProps` | `ViewProps` | - | All standard React Native View props are supported |
#### AccordionContentAnimation
Animation configuration for accordion content component. Can be:
* `false` or `"disabled"`: Disable all animations
* `true` or `undefined`: Use default animations
* `object`: Custom animation configuration
| prop | type | default | description |
| ---------------- | ----------------------- | ---------------------------------------------------------------------- | ----------------------------------------------- |
| `state` | `'disabled' \| boolean` | - | Disable animations while customizing properties |
| `entering.value` | `EntryOrExitLayoutType` | `FadeIn` `.duration(200)` `.easing(Easing.out(Easing.ease))` | Custom entering animation for content |
| `exiting.value` | `EntryOrExitLayoutType` | `FadeOut` `.duration(200)` `.easing(Easing.in(Easing.ease))` | Custom exiting animation for content |
## Hooks
### useAccordion
Hook to access the accordion root context. Must be used within an `Accordion` component.
```tsx
import { useAccordion } from 'heroui-native';
const { value, onValueChange, selectionMode, isCollapsible, isDisabled } =
useAccordion();
```
#### Returns
| property | type | description |
| --------------- | --------------------------------------------------------------------- | ---------------------------------------------------------------------------- |
| `selectionMode` | `'single' \| 'multiple' \| undefined` | Whether the accordion allows single or multiple expanded items |
| `value` | `(string \| undefined) \| string[]` | Currently expanded item(s) - string for single mode, array for multiple mode |
| `onValueChange` | `(value: string \| undefined) => void \| ((value: string[]) => void)` | Callback function to update expanded items |
| `isCollapsible` | `boolean` | Whether expanded items can be collapsed |
| `isDisabled` | `boolean \| undefined` | Whether all accordion items are disabled |
### useAccordionItem
Hook to access the accordion item context. Must be used within an `Accordion.Item` component.
```tsx
import { useAccordionItem } from 'heroui-native';
const { value, isExpanded, isDisabled, nativeID } = useAccordionItem();
```
#### Returns
| property | type | description |
| ------------ | ---------------------- | ---------------------------------------------------- |
| `value` | `string` | Unique value identifier for this accordion item |
| `isExpanded` | `boolean` | Whether the accordion item is currently expanded |
| `isDisabled` | `boolean \| undefined` | Whether this specific item is disabled |
| `nativeID` | `string` | Native ID used for accessibility and ARIA attributes |
## Special Notes
When using the Accordion component alongside other components in the same view, you should import and apply `AccordionLayoutTransition` to those components to ensure smooth and consistent layout animations across the entire screen.
```jsx
import { Accordion, AccordionLayoutTransition } from 'heroui-native';
import Animated from 'react-native-reanimated';
{/* Other content */}
{/* Accordion items */};
```
This ensures that when the accordion expands or collapses, all components on the screen animate with the same timing and easing, creating a cohesive user experience.
# ListGroup
**Category**: native
**URL**: https://v3.heroui.com/docs/native/components/list-group
**Source**: https://raw.githubusercontent.com/heroui-inc/heroui/refs/heads/v3/apps/docs/content/docs/native/components/(navigation)/list-group.mdx
> A Surface-based container that groups related list items with consistent layout and spacing.
## Import
```tsx
import { ListGroup } from 'heroui-native';
```
## Anatomy
```tsx
.........
```
* **ListGroup**: Surface-based root container that groups related list items. Supports all Surface variants (default, secondary, tertiary, transparent).
* **ListGroup.Item**: Pressable horizontal flex-row container for a single item, providing consistent spacing and alignment.
* **ListGroup.ItemPrefix**: Optional leading content slot for icons, avatars, or other visual elements.
* **ListGroup.ItemContent**: Flex-1 wrapper for title and description, occupying the remaining horizontal space.
* **ListGroup.ItemTitle**: Primary text label styled with foreground color and medium font weight.
* **ListGroup.ItemDescription**: Secondary text styled with muted color and smaller font size.
* **ListGroup.ItemSuffix**: Optional trailing content slot. Renders a chevron-right icon by default; accepts children to override the default icon.
## Usage
### Basic Usage
The ListGroup component uses compound parts to create grouped list items with title and description.
```tsx
Personal Info
Name, email, phone number
Payment Methods
Visa ending in 4829
```
### With Icons
Add leading icons using the `ListGroup.ItemPrefix` slot.
```tsx
Profile
Name, photo, bio
Security
Password, 2FA
```
### Title Only
Omit `ListGroup.ItemDescription` to display title-only items.
```tsx
Wi-FiBluetooth
```
### Surface Variant
Apply a different visual variant to the root container.
```tsx
Wi-Fi
```
### Custom Suffix
Override the default chevron icon by passing children to `ListGroup.ItemSuffix`.
```tsx
LanguageEnglishNotifications7
```
### Custom Suffix Icon Props
Customise the default chevron icon size and color using `iconProps`.
```tsx
Storage
12.4 GB of 50 GB used
```
### With PressableFeedback
Wrap items with `PressableFeedback` to add scale and ripple press feedback animations. When using this pattern, pass `onPress` on `PressableFeedback` instead of `ListGroup.Item` and disable the item with `disabled` prop.
```tsx
import { ListGroup, PressableFeedback, Separator } from 'heroui-native';
{}}>
Appearance
Theme, font size, display
{}}>
Notifications
Alerts, sounds, badges
```
## Example
```tsx
import { Ionicons } from '@expo/vector-icons';
import { ListGroup, Separator, useThemeColor } from 'heroui-native';
import { View, Text } from 'react-native';
import { withUniwind } from 'uniwind';
const StyledIonicons = withUniwind(Ionicons);
export default function ListGroupExample() {
const mutedColor = useThemeColor('muted');
return (
AccountPersonal Info
Name, email, phone number
Payment Methods
Visa ending in 4829
PreferencesAppearance
Theme, font size, display
Notifications
Alerts, sounds, badges
);
}
```
You can find more examples in the [GitHub repository](https://github.com/heroui-inc/heroui-native/blob/rc/example/src/app/\(home\)/components/list-group.tsx).
## API Reference
### ListGroup
| prop | type | default | description |
| -------------- | --------------------------------------------------------- | ----------- | -------------------------------------------------- |
| `children` | `React.ReactNode` | - | Children elements to be rendered inside the group |
| `variant` | `'default' \| 'secondary' \| 'tertiary' \| 'transparent'` | `'default'` | Visual variant of the underlying Surface container |
| `className` | `string` | - | Additional CSS classes for the root container |
| `...ViewProps` | `ViewProps` | - | All standard React Native View props are supported |
### ListGroup.Item
| prop | type | default | description |
| ------------------- | ----------------- | ------- | ------------------------------------------------------- |
| `children` | `React.ReactNode` | - | Children elements to be rendered inside the item |
| `className` | `string` | - | Additional CSS classes for the item |
| `...PressableProps` | `PressableProps` | - | All standard React Native Pressable props are supported |
### ListGroup.ItemPrefix
| prop | type | default | description |
| -------------- | ----------------- | ------- | -------------------------------------------------- |
| `children` | `React.ReactNode` | - | Leading content such as icons or avatars |
| `className` | `string` | - | Additional CSS classes for the prefix |
| `...ViewProps` | `ViewProps` | - | All standard React Native View props are supported |
### ListGroup.ItemContent
| prop | type | default | description |
| -------------- | ----------------- | ------- | -------------------------------------------------- |
| `children` | `React.ReactNode` | - | Content area, typically title and description |
| `className` | `string` | - | Additional CSS classes for the content area |
| `...ViewProps` | `ViewProps` | - | All standard React Native View props are supported |
### ListGroup.ItemTitle
| prop | type | default | description |
| -------------- | ----------------- | ------- | -------------------------------------------------- |
| `children` | `React.ReactNode` | - | Title text or custom content |
| `className` | `string` | - | Additional CSS classes for the title |
| `...ViewProps` | `ViewProps` | - | All standard React Native View props are supported |
### ListGroup.ItemDescription
| prop | type | default | description |
| -------------- | ----------------- | ------- | -------------------------------------------------- |
| `children` | `React.ReactNode` | - | Description text or custom content |
| `className` | `string` | - | Additional CSS classes for the description |
| `...ViewProps` | `ViewProps` | - | All standard React Native View props are supported |
### ListGroup.ItemSuffix
| prop | type | default | description |
| -------------- | -------------------- | ------- | -------------------------------------------------------------------------------- |
| `children` | `React.ReactNode` | - | Custom trailing content; overrides the default chevron-right icon when provided |
| `className` | `string` | - | Additional CSS classes for the suffix |
| `iconProps` | `ListGroupIconProps` | - | Props to customise the default chevron-right icon. Only applies when no children |
| `...ViewProps` | `ViewProps` | - | All standard React Native View props are supported |
#### ListGroupIconProps
| prop | type | default | description |
| ------- | -------- | ------------------- | ---------------------------------- |
| `size` | `number` | `16` | Size of the chevron icon in pixels |
| `color` | `string` | theme `muted` color | Color of the chevron icon |
# Tabs
**Category**: native
**URL**: https://v3.heroui.com/docs/native/components/tabs
**Source**: https://raw.githubusercontent.com/heroui-inc/heroui/refs/heads/v3/apps/docs/content/docs/native/components/(navigation)/tabs.mdx
> Organize content into tabbed views with animated transitions and indicators.
## Import
```tsx
import { Tabs } from 'heroui-native';
```
## Anatomy
```tsx
.........
```
* **Tabs**: Main container that manages tab state and selection. Controls active tab, handles value changes, and provides context to child components.
* **Tabs.List**: Container for tab triggers. Groups triggers together with optional styling variants (primary or secondary).
* **Tabs.ScrollView**: Optional scrollable wrapper for tab triggers. Enables horizontal scrolling when tabs overflow with automatic centering of active tab.
* **Tabs.Trigger**: Interactive button for each tab. Handles press events to change active tab and measures its position for indicator animation.
* **Tabs.Label**: Text content for tab triggers. Displays the tab title with appropriate styling.
* **Tabs.Indicator**: Animated visual indicator for active tab. Smoothly transitions between tabs using spring or timing animations.
* **Tabs.Separator**: Visual separator between tabs. Shows when the current tab value is not in the `betweenValues` array, with animated opacity transitions.
* **Tabs.Content**: Container for tab panel content. Shows content when its value matches the active tab.
## Usage
### Basic Usage
The Tabs component uses compound parts to create navigable content sections.
```tsx
Tab 1Tab 2......
```
### Primary Variant
Default rounded primary style for tab triggers.
```tsx
SettingsProfile......
```
### Secondary Variant
Underline style indicator for a more minimal appearance.
```tsx
OverviewAnalytics......
```
### Scrollable Tabs
Handle many tabs with horizontal scrolling.
```tsx
First TabSecond TabThird TabFourth TabFifth Tab...............
```
### Disabled Tabs
Disable specific tabs to prevent interaction.
```tsx
ActiveDisabledAnother......
```
### With Icons
Combine icons with labels for enhanced visual context.
```tsx
HomeSearch......
```
### With Render Function
Use a render function on `Tabs.Trigger` to access state and customize content based on selection.
```tsx
{({ isSelected, value, isDisabled }) => (
Settings
)}
{({ isSelected }) => (
<>
Profile
>
)}
......
```
### With Separators
Add visual separators between tabs that show when the active tab is not between specified values.
```tsx
GeneralNotificationsProfile.........
```
## Example
```tsx
import {
Button,
Checkbox,
Description,
ControlField,
Label,
Tabs,
TextField,
} from 'heroui-native';
import { useState } from 'react';
import { View, Text } from 'react-native';
import Animated, {
FadeIn,
FadeOut,
LinearTransition,
} from 'react-native-reanimated';
const AnimatedContentContainer = ({
children,
}: {
children: React.ReactNode;
}) => (
{children}
);
export default function TabsExample() {
const [activeTab, setActiveTab] = useState('general');
const [showSidebar, setShowSidebar] = useState(true);
const [accountActivity, setAccountActivity] = useState(true);
const [name, setName] = useState('');
return (
GeneralNotificationsProfileDisplay the sidebar navigation panel
Notifications about your account activity
);
}
```
You can find more examples in the [GitHub repository](https://github.com/heroui-inc/heroui-native/blob/rc/example/src/app/\(home\)/components/tabs.tsx).
## API Reference
### Tabs
| prop | type | default | description |
| --------------- | ---------------------------- | ----------- | ----------------------------------------------------------------------------------------- |
| `children` | `React.ReactNode` | - | Children elements to be rendered inside tabs |
| `value` | `string` | - | Currently active tab value |
| `variant` | `'primary' \| 'secondary'` | `'primary'` | Visual variant of the tabs |
| `className` | `string` | - | Additional CSS classes for the container |
| `animation` | `"disable-all" \| undefined` | `undefined` | Animation configuration. Use `"disable-all"` to disable all animations including children |
| `onValueChange` | `(value: string) => void` | - | Callback when the active tab changes |
| `...ViewProps` | `ViewProps` | - | All standard React Native View props are supported |
### Tabs.List
| prop | type | default | description |
| -------------- | ----------------- | ------- | -------------------------------------------------- |
| `children` | `React.ReactNode` | - | Children elements to be rendered inside the list |
| `className` | `string` | - | Additional CSS classes |
| `...ViewProps` | `ViewProps` | - | All standard React Native View props are supported |
### Tabs.ScrollView
| prop | type | default | description |
| --------------------------- | ---------------------------------------- | ---------- | -------------------------------------------------------- |
| `children` | `React.ReactNode` | - | Children elements to be rendered inside the scroll view |
| `scrollAlign` | `'start' \| 'center' \| 'end' \| 'none'` | `'center'` | Scroll alignment variant for the selected item |
| `className` | `string` | - | Additional CSS classes for the scroll view |
| `contentContainerClassName` | `string` | - | Additional CSS classes for the content container |
| `...ScrollViewProps` | `ScrollViewProps` | - | All standard React Native ScrollView props are supported |
### Tabs.Trigger
| prop | type | default | description |
| ------------------- | ------------------------------------------------------------------------- | ------- | ------------------------------------------------------------------------- |
| `children` | `React.ReactNode \| ((props: TabsTriggerRenderProps) => React.ReactNode)` | - | Children elements to be rendered inside the trigger, or a render function |
| `value` | `string` | - | The unique value identifying this tab |
| `isDisabled` | `boolean` | `false` | Whether the trigger is disabled |
| `className` | `string` | - | Additional CSS classes |
| `...PressableProps` | `PressableProps` | - | All standard React Native Pressable props are supported |
#### TabsTriggerRenderProps
When using a render function for `children`, the following props are provided:
| property | type | description |
| ------------ | --------- | ------------------------------------------ |
| `isSelected` | `boolean` | Whether this trigger is currently selected |
| `value` | `string` | The value of the trigger |
| `isDisabled` | `boolean` | Whether the trigger is disabled |
### Tabs.Label
| prop | type | default | description |
| -------------- | ----------------- | ------- | -------------------------------------------------- |
| `children` | `React.ReactNode` | - | Text content to be rendered as label |
| `className` | `string` | - | Additional CSS classes |
| `...TextProps` | `TextProps` | - | All standard React Native Text props are supported |
### Tabs.Indicator
| prop | type | default | description |
| ----------------------- | ------------------------ | ------- | ------------------------------------------------------------ |
| `children` | `React.ReactNode` | - | Custom indicator content |
| `className` | `string` | - | Additional CSS classes |
| `animation` | `TabsIndicatorAnimation` | - | Animation configuration |
| `isAnimatedStyleActive` | `boolean` | `true` | Whether animated styles (react-native-reanimated) are active |
| `...Animated.ViewProps` | `Animated.ViewProps` | - | All Reanimated Animated.View props are supported |
#### TabsIndicatorAnimation
Animation configuration for Tabs.Indicator component. Can be:
* `false` or `"disabled"`: Disable all animations
* `true` or `undefined`: Use default animations
* `object`: Custom animation configuration
| prop | type | default | description |
| ------------------- | -------------------------------------- | ---------------------------------------------------------------------------- | ----------------------------------------------- |
| `state` | `'disabled' \| boolean` | - | Disable animations while customizing properties |
| `width.type` | `'spring' \| 'timing'` | `'spring'` | Type of animation to use |
| `width.config` | `WithSpringConfig \| WithTimingConfig` | `{ stiffness: 1200, damping: 120 }` (spring) or `{ duration: 200 }` (timing) | Reanimated animation configuration |
| `height.type` | `'spring' \| 'timing'` | `'spring'` | Type of animation to use |
| `height.config` | `WithSpringConfig \| WithTimingConfig` | `{ stiffness: 1200, damping: 120 }` (spring) or `{ duration: 200 }` (timing) | Reanimated animation configuration |
| `translateX.type` | `'spring' \| 'timing'` | `'spring'` | Type of animation to use |
| `translateX.config` | `WithSpringConfig \| WithTimingConfig` | `{ stiffness: 1200, damping: 120 }` (spring) or `{ duration: 200 }` (timing) | Reanimated animation configuration |
### Tabs.Separator
| prop | type | default | description |
| ----------------------- | ------------------------ | ------- | -------------------------------------------------------------------------------------------------------------------------------------- |
| `betweenValues` | `string[]` | - | Array of tab values between which the separator should be visible. The separator shows when the current tab value is NOT in this array |
| `isAlwaysVisible` | `boolean` | `false` | If true, opacity is always 1 regardless of the current tab value |
| `className` | `string` | - | Additional CSS classes |
| `animation` | `TabsSeparatorAnimation` | - | Animation configuration |
| `isAnimatedStyleActive` | `boolean` | `true` | Whether animated styles (react-native-reanimated) are active |
| `children` | `React.ReactNode` | - | Custom separator content |
| `...Animated.ViewProps` | `Animated.ViewProps` | - | All Reanimated Animated.View props are supported |
**Note:** The following style properties are occupied by animations and cannot be set via className:
* `opacity` - Animated for separator visibility transitions (0 when current tab is in `betweenValues`, 1 when not)
To customize these properties, use the `animation` prop. To completely disable animated styles and use your own via className or style prop, set `isAnimatedStyleActive={false}`.
#### TabsSeparatorAnimation
Animation configuration for Tabs.Separator component. Can be:
* `false` or `"disabled"`: Disable all animations
* `true` or `undefined`: Use default animations
* `object`: Custom animation configuration
| prop | type | default | description |
| ---------------------- | ----------------------- | ------------------- | ----------------------------------------------- |
| `state` | `'disabled' \| boolean` | - | Disable animations while customizing properties |
| `opacity.value` | `[number, number]` | `[0, 1]` | Opacity values \[hidden, visible] |
| `opacity.timingConfig` | `WithTimingConfig` | `{ duration: 200 }` | Animation timing configuration |
### Tabs.Content
| prop | type | default | description |
| -------------- | ----------------- | ------- | --------------------------------------------------- |
| `children` | `React.ReactNode` | - | Children elements to be rendered inside the content |
| `value` | `string` | - | The value of the tab this content belongs to |
| `className` | `string` | - | Additional CSS classes |
| `...ViewProps` | `ViewProps` | - | All standard React Native View props are supported |
## Hooks
### useTabs
Hook to access tabs root context values within custom components or compound components.
```tsx
import { useTabs } from 'heroui-native';
const CustomComponent = () => {
const { value, onValueChange, nativeID } = useTabs();
// ... your implementation
};
```
**Returns:** `UseTabsReturn`
| property | type | description |
| --------------- | ------------------------- | ------------------------------------------ |
| `value` | `string` | Currently active tab value |
| `onValueChange` | `(value: string) => void` | Callback function to change the active tab |
| `nativeID` | `string` | Unique identifier for the tabs instance |
**Note:** This hook must be used within a `Tabs` component. It will throw an error if called outside of the tabs context.
### useTabsMeasurements
Hook to access tab measurements context values for managing tab trigger positions and dimensions.
```tsx
import { useTabsMeasurements } from 'heroui-native';
const CustomIndicator = () => {
const { measurements, variant } = useTabsMeasurements();
// ... your implementation
};
```
**Returns:** `UseTabsMeasurementsReturn`
| property | type | description |
| ----------------- | ------------------------------------------------------- | ------------------------------------------------- |
| `measurements` | `Record` | Record of measurements for each tab trigger |
| `setMeasurements` | `(key: string, measurements: ItemMeasurements) => void` | Function to update measurements for a tab trigger |
| `variant` | `'primary' \| 'secondary'` | Visual variant of the tabs |
#### ItemMeasurements
| property | type | description |
| -------- | -------- | ----------------------------------- |
| `width` | `number` | Width of the tab trigger in pixels |
| `height` | `number` | Height of the tab trigger in pixels |
| `x` | `number` | X position of the tab trigger |
**Note:** This hook must be used within a `Tabs` component. It will throw an error if called outside of the tabs context.
### useTabsTrigger
Hook to access tab trigger context values within custom components or compound components.
```tsx
import { useTabsTrigger } from 'heroui-native';
const CustomLabel = () => {
const { value, isSelected, nativeID } = useTabsTrigger();
// ... your implementation
};
```
**Returns:** `UseTabsTriggerReturn`
| property | type | description |
| ------------ | --------- | ------------------------------------------ |
| `value` | `string` | The value of this trigger |
| `nativeID` | `string` | Unique identifier for this trigger |
| `isSelected` | `boolean` | Whether this trigger is currently selected |
**Note:** This hook must be used within a `Tabs.Trigger` component. It will throw an error if called outside of the trigger context.
# BottomSheet
**Category**: native
**URL**: https://v3.heroui.com/docs/native/components/bottom-sheet
**Source**: https://raw.githubusercontent.com/heroui-inc/heroui/refs/heads/v3/apps/docs/content/docs/native/components/(overlays)/bottom-sheet.mdx
> Displays a bottom sheet that slides up from the bottom with animated transitions and swipe-to-dismiss gestures.
## Import
```tsx
import { BottomSheet } from 'heroui-native';
```
## Anatomy
```tsx
............
```
* **BottomSheet**: Root component that manages open state and provides context to child components.
* **BottomSheet.Trigger**: Pressable element that opens the bottom sheet when pressed.
* **BottomSheet.Portal**: Renders bottom sheet content in a portal with full window overlay.
* **BottomSheet.Overlay**: Background overlay that covers the screen, typically closes bottom sheet when pressed.
* **BottomSheet.Content**: Main bottom sheet container using @gorhom/bottom-sheet for rendering with gesture support.
* **BottomSheet.Close**: Close button for the bottom sheet. Can accept custom children or uses default close icon.
* **BottomSheet.Title**: Bottom sheet title text with semantic heading role and accessibility linking.
* **BottomSheet.Description**: Bottom sheet description text that provides additional context with accessibility linking.
## Usage
### Basic Bottom Sheet
Simple bottom sheet with title, description, and close button.
```tsx
......
```
### Detached Bottom Sheet
Bottom sheet that appears detached from the bottom edge with custom spacing.
```tsx
...
...
```
### Scrollable with Snap Points
Bottom sheet with multiple snap points and scrollable content.
```tsx
......
```
### Custom Overlay
Replace the default overlay with custom content like blur effects.
```tsx
import { useBottomSheet, useBottomSheetAnimation } from 'heroui-native';
import { StyleSheet, Pressable } from 'react-native';
import { interpolate, useDerivedValue } from 'react-native-reanimated';
import { AnimatedBlurView } from './animated-blur-view';
import { useUniwind } from 'uniwind';
export const BottomSheetBlurOverlay = () => {
const { theme } = useUniwind();
const { onOpenChange } = useBottomSheet();
const { progress } = useBottomSheetAnimation();
const blurIntensity = useDerivedValue(() => {
return interpolate(progress.get(), [0, 1, 2], [0, 40, 0]);
});
return (
onOpenChange(false)}
>
);
};
```
```tsx
......
```
## Example
```tsx
import { BottomSheet, Button } from 'heroui-native';
import { useState } from 'react';
import { View } from 'react-native';
import { withUniwind } from 'uniwind';
import Ionicons from '@expo/vector-icons/Ionicons';
const StyledIonicons = withUniwind(Ionicons);
export default function BottomSheetExample() {
const [isOpen, setIsOpen] = useState(false);
return (
Keep yourself safe
Update your software to the latest version for better security and
performance.
);
}
```
You can find more examples in the [GitHub repository](https://github.com/heroui-inc/heroui-native/blob/rc/example/src/app/\(home\)/components/bottom-sheet.tsx).
## API Reference
### BottomSheet
| prop | type | default | description |
| --------------- | -------------------------- | ------- | -------------------------------------------------- |
| `children` | `React.ReactNode` | - | Bottom sheet content and trigger elements |
| `isOpen` | `boolean` | - | Controlled open state of the bottom sheet |
| `isDefaultOpen` | `boolean` | `false` | Initial open state when uncontrolled |
| `animation` | `AnimationRootDisableAll` | - | Animation configuration |
| `onOpenChange` | `(value: boolean) => void` | - | Callback when open state changes |
| `...ViewProps` | `ViewProps` | - | All standard React Native View props are supported |
#### Animation Configuration
Animation configuration for bottom sheet root component. Can be:
* `"disable-all"`: Disable all animations including children
* `undefined`: Use default animations
### BottomSheet.Trigger
| prop | type | default | description |
| -------------------------- | ----------------------- | ------- | -------------------------------------------------------------- |
| `children` | `React.ReactNode` | - | Trigger element content |
| `asChild` | `boolean` | - | Render as child element without wrapper |
| `...TouchableOpacityProps` | `TouchableOpacityProps` | - | All standard React Native TouchableOpacity props are supported |
### BottomSheet.Portal
| prop | type | default | description |
| -------------------------- | ---------------------- | ------- | ----------------------------------------------------------------------------------------------------------------------------- |
| `children` | `React.ReactNode` | - | Portal content (overlay and bottom sheet) |
| `disableFullWindowOverlay` | `boolean` | `false` | When true on iOS, uses View instead of FullWindowOverlay. Enables element inspector; overlay won't appear above native modals |
| `className` | `string` | - | Additional CSS classes for portal container |
| `style` | `StyleProp` | - | Additional styles for portal container |
| `hostName` | `string` | - | Optional portal host name for specific container |
| `forceMount` | `boolean` | - | Force mount when closed for animation purposes |
### BottomSheet.Overlay
| prop | type | default | description |
| ----------------------- | ------------------------------------------------------ | ------- | ------------------------------------------------------------ |
| `children` | `React.ReactNode` | - | Custom overlay content |
| `className` | `string` | - | Additional CSS classes for overlay |
| `style` | `ViewStyle` | - | Additional styles for overlay container |
| `animation` | `Omit` | - | Animation configuration |
| `isAnimatedStyleActive` | `boolean` | `true` | Whether animated styles (react-native-reanimated) are active |
| `isCloseOnPress` | `boolean` | `true` | Whether pressing overlay closes bottom sheet |
| `...PressableProps` | `PressableProps` | - | All standard React Native Pressable props are supported |
#### Animation Configuration
Animation configuration for bottom sheet overlay component. Can be:
* `false` or `"disabled"`: Disable all animations
* `true` or `undefined`: Use default animations
* `object`: Custom animation configuration (excluding `entering` and `exiting` properties)
| prop | type | default | description |
| --------------- | -------------------------- | ----------- | ----------------------------------------------- |
| `state` | `'disabled' \| boolean` | - | Disable animations while customizing properties |
| `opacity.value` | `[number, number, number]` | `[0, 1, 0]` | Opacity values \[idle, open, close] |
### BottomSheet.Content
| prop | type | default | description |
| --------------------------- | ---------------------------------------- | ------- | -------------------------------------------------------------------------------------------------- |
| `children` | `React.ReactNode` | - | Bottom sheet content |
| `className` | `string` | - | Additional CSS classes for bottom sheet container |
| `containerClassName` | `string` | - | Additional CSS classes for container |
| `contentContainerClassName` | `string` | - | Additional CSS classes for content container |
| `backgroundClassName` | `string` | - | Additional CSS classes for background |
| `handleClassName` | `string` | - | Additional CSS classes for handle |
| `handleIndicatorClassName` | `string` | - | Additional CSS classes for handle indicator |
| `contentContainerProps` | `Omit` | - | Props for the content container |
| `animation` | `AnimationDisabled` | - | Animation configuration |
| `...GorhomBottomSheetProps` | `Partial` | - | All [@gorhom/bottom-sheet props](https://gorhom.dev/react-native-bottom-sheet/props) are supported |
**Note**: You can use all components from [@gorhom/bottom-sheet](https://gorhom.dev/react-native-bottom-sheet/components/bottomsheetview) inside the content, such as `BottomSheetView`, `BottomSheetScrollView`, `BottomSheetFlatList`, etc.
### BottomSheet.Close
BottomSheet.Close extends [CloseButton](./close-button) and automatically handles bottom sheet dismissal when pressed.
### BottomSheet.Title
| prop | type | default | description |
| -------------- | ----------------- | ------- | -------------------------------------------------- |
| `children` | `React.ReactNode` | - | Title content |
| `className` | `string` | - | Additional CSS classes for title |
| `...TextProps` | `TextProps` | - | All standard React Native Text props are supported |
### BottomSheet.Description
| prop | type | default | description |
| -------------- | ----------------- | ------- | -------------------------------------------------- |
| `children` | `React.ReactNode` | - | Description content |
| `className` | `string` | - | Additional CSS classes for description |
| `...TextProps` | `TextProps` | - | All standard React Native Text props are supported |
## Hooks
### useBottomSheet
Hook to access bottom sheet primitive context.
```tsx
const { isOpen, onOpenChange } = useBottomSheet();
```
| property | type | description |
| -------------- | -------------------------- | ----------------------------- |
| `isOpen` | `boolean` | Current open state |
| `onOpenChange` | `(value: boolean) => void` | Function to change open state |
### useBottomSheetAnimation
Hook to access bottom sheet animation context for advanced customization.
```tsx
const { progress } = useBottomSheetAnimation();
```
| property | type | description |
| ---------- | --------------------- | -------------------------------------------- |
| `progress` | `SharedValue` | Animation progress (0=idle, 1=open, 2=close) |
## Special Notes
### Element Inspector (iOS)
BottomSheet uses FullWindowOverlay on iOS, which renders in a separate native window. This breaks the React Native element inspector. To enable the inspector during development, set `disableFullWindowOverlay={true}` on `BottomSheet.Portal`. Tradeoff: the bottom sheet will not appear above native modals when disabled.
### Handling Close Callbacks
It's recommended to use `BottomSheet`'s `onOpenChange` prop for handling close callbacks, as it reliably fires for all close scenarios (swiping down, pressing overlay, pressing close button, programmatic close, etc.).
```tsx
{
setIsOpen(value);
if (!value) {
// This callback runs whenever the bottom sheet closes
// regardless of how it was closed
yourCallbackOnClose();
}
}}
>
...
```
**Note**: `BottomSheet.Content`'s `onClose` prop (from @gorhom/bottom-sheet) has limitations and will only fire when the bottom sheet is closed by swiping down. It won't fire when closing via overlay press, close button, or programmatic close. For reliable close callbacks, always use `BottomSheet`'s `onOpenChange` prop instead.
# Dialog
**Category**: native
**URL**: https://v3.heroui.com/docs/native/components/dialog
**Source**: https://raw.githubusercontent.com/heroui-inc/heroui/refs/heads/v3/apps/docs/content/docs/native/components/(overlays)/dialog.mdx
> Displays a modal overlay with animated transitions and gesture-based dismissal.
## Import
```tsx
import { Dialog } from 'heroui-native';
```
## Anatomy
```tsx
```
* **Dialog**: Root component that manages open state and provides context to child components.
* **Dialog.Trigger**: Pressable element that opens the dialog when pressed.
* **Dialog.Portal**: Renders dialog content in a portal with centered layout and animation control.
* **Dialog.Overlay**: Background overlay that appears behind the dialog content, typically closes dialog when pressed.
* **Dialog.Content**: Main dialog container with gesture support for drag-to-dismiss.
* **Dialog.Close**: Close button for the dialog. Can accept custom children or uses default close icon.
* **Dialog.Title**: Dialog title text with semantic heading role.
* **Dialog.Description**: Dialog description text that provides additional context.
## Usage
### Basic Dialog
Simple dialog with title, description, and close button.
```tsx
```
### Scrollable Content
Handle long content with scroll views.
```tsx
```
### Form Dialog
Dialog with text inputs and keyboard handling.
```tsx
```
## Example
```tsx
import { Button, Dialog } from 'heroui-native';
import { View } from 'react-native';
import { useState } from 'react';
export default function DialogExample() {
const [isOpen, setIsOpen] = useState(false);
return (
);
}
```
You can find more examples in the [GitHub repository](https://github.com/heroui-inc/heroui-native/blob/rc/example/src/app/\(home\)/components/dialog.tsx).
## API Reference
### Dialog
| prop | type | default | description |
| --------------- | -------------------------- | ------- | -------------------------------------------------- |
| `children` | `React.ReactNode` | - | Dialog content and trigger elements |
| `isOpen` | `boolean` | - | Controlled open state of the dialog |
| `isDefaultOpen` | `boolean` | `false` | Initial open state when uncontrolled |
| `animation` | `AnimationRootDisableAll` | - | Animation configuration |
| `onOpenChange` | `(value: boolean) => void` | - | Callback when open state changes |
| `...ViewProps` | `ViewProps` | - | All standard React Native View props are supported |
#### AnimationRootDisableAll
Animation configuration for dialog root component. Can be:
* `false` or `"disabled"`: Disable only root animations
* `"disable-all"`: Disable all animations including children
* `true` or `undefined`: Use default animations
### Dialog.Trigger
| prop | type | default | description |
| -------------------------- | ----------------------- | ------- | -------------------------------------------------------------- |
| `children` | `React.ReactNode` | - | Trigger element content |
| `asChild` | `boolean` | - | Render as child element without wrapper |
| `...TouchableOpacityProps` | `TouchableOpacityProps` | - | All standard React Native TouchableOpacity props are supported |
### Dialog.Portal
| prop | type | default | description |
| -------------------------- | ---------------------- | ------- | ----------------------------------------------------------------------------------------------------------------------------- |
| `children` | `React.ReactNode` | - | Portal content (overlay and dialog) |
| `disableFullWindowOverlay` | `boolean` | `false` | When true on iOS, uses View instead of FullWindowOverlay. Enables element inspector; overlay won't appear above native modals |
| `className` | `string` | - | Additional CSS classes for portal container |
| `style` | `StyleProp` | - | Additional styles for portal container |
| `hostName` | `string` | - | Optional portal host name for specific container |
| `forceMount` | `boolean` | - | Force mount when closed for animation purposes |
### Dialog.Overlay
| prop | type | default | description |
| ----------------------- | ------------------------ | ------- | ------------------------------------------------------------ |
| `children` | `React.ReactNode` | - | Custom overlay content |
| `className` | `string` | - | Additional CSS classes for overlay |
| `style` | `ViewStyle` | - | Additional styles for overlay container |
| `animation` | `DialogOverlayAnimation` | - | Animation configuration |
| `isAnimatedStyleActive` | `boolean` | `true` | Whether animated styles (react-native-reanimated) are active |
| `isCloseOnPress` | `boolean` | `true` | Whether pressing overlay closes dialog |
| `forceMount` | `boolean` | - | Force mount when closed for animation purposes |
| `...PressableProps` | `PressableProps` | - | All standard React Native Pressable props are supported |
#### DialogOverlayAnimation
Animation configuration for dialog overlay component. Can be:
* `false` or `"disabled"`: Disable all animations
* `true` or `undefined`: Use default animations
* `object`: Custom animation configuration
| prop | type | default | description |
| --------------- | -------------------------- | ----------------------- | ----------------------------------------------------------------------------- |
| `state` | `'disabled' \| boolean` | - | Disable animations while customizing properties |
| `opacity.value` | `[number, number, number]` | `[0, 1, 0]` | Opacity values \[idle, open, close] (progress-based, for dialog presentation) |
| `entering` | `EntryOrExitLayoutType` | `FadeIn.duration(200)` | Custom entering animation (for popover presentation) |
| `exiting` | `EntryOrExitLayoutType` | `FadeOut.duration(150)` | Custom exiting animation (for popover presentation) |
### Dialog.Content
| prop | type | default | description |
| ----------------------- | ------------------------ | ------- | --------------------------------------------------- |
| `children` | `React.ReactNode` | - | Dialog content |
| `className` | `string` | - | Additional CSS classes for content container |
| `style` | `StyleProp` | - | Additional styles for content container |
| `animation` | `DialogContentAnimation` | - | Animation configuration |
| `isSwipeable` | `boolean` | `true` | Whether the dialog content can be swiped to dismiss |
| `forceMount` | `boolean` | - | Force mount when closed for animation purposes |
| `...Animated.ViewProps` | `Animated.ViewProps` | - | All Reanimated Animated.View props are supported |
#### DialogContentAnimation
Animation configuration for dialog content component. Can be:
* `false` or `"disabled"`: Disable all animations
* `true` or `undefined`: Use default animations
* `object`: Custom animation configuration
| prop | type | default | description |
| ---------- | ----------------------- | ------------------------------------------------------------------------------------------- | ----------------------------------------------- |
| `state` | `'disabled' \| boolean` | - | Disable animations while customizing properties |
| `entering` | `EntryOrExitLayoutType` | Keyframe with `scale: 0.96→1` and `opacity: 0→1` (200ms, easing: `Easing.out(Easing.ease)`) | Custom entering animation |
| `exiting` | `EntryOrExitLayoutType` | Keyframe with `scale: 1→0.96` and `opacity: 1→0` (150ms, easing: `Easing.in(Easing.ease)`) | Custom exiting animation |
### Dialog.Close
Dialog.Close extends [CloseButton](./close-button) and automatically handles dialog dismissal when pressed.
### Dialog.Title
| prop | type | default | description |
| -------------- | ----------------- | ------- | -------------------------------------------------- |
| `children` | `React.ReactNode` | - | Title content |
| `className` | `string` | - | Additional CSS classes for title |
| `...TextProps` | `TextProps` | - | All standard React Native Text props are supported |
### Dialog.Description
| prop | type | default | description |
| -------------- | ----------------- | ------- | -------------------------------------------------- |
| `children` | `React.ReactNode` | - | Description content |
| `className` | `string` | - | Additional CSS classes for description |
| `...TextProps` | `TextProps` | - | All standard React Native Text props are supported |
## Hooks
### useDialog
Hook to access dialog primitive context.
```tsx
const { isOpen, onOpenChange } = useDialog();
```
| property | type | description |
| -------------- | -------------------------- | ----------------------------- |
| `isOpen` | `boolean` | Current open state |
| `onOpenChange` | `(value: boolean) => void` | Function to change open state |
### useDialogAnimation
Hook to access dialog animation context for advanced customization.
```tsx
const { progress, isDragging, isGestureReleaseAnimationRunning } =
useDialogAnimation();
```
| property | type | description |
| ---------------------------------- | ---------------------- | -------------------------------------------- |
| `progress` | `SharedValue` | Animation progress (0=idle, 1=open, 2=close) |
| `isDragging` | `SharedValue` | Whether dialog is being dragged |
| `isGestureReleaseAnimationRunning` | `SharedValue` | Whether gesture release animation is running |
## Special Notes
### Element Inspector (iOS)
Dialog uses FullWindowOverlay on iOS. To enable the React Native element inspector during development, set `disableFullWindowOverlay={true}` on `Dialog.Portal`. Tradeoff: the dialog will not appear above native modals when disabled.
# Popover
**Category**: native
**URL**: https://v3.heroui.com/docs/native/components/popover
**Source**: https://raw.githubusercontent.com/heroui-inc/heroui/refs/heads/v3/apps/docs/content/docs/native/components/(overlays)/popover.mdx
> Displays a floating content panel anchored to a trigger element with placement and alignment options.
## Import
```tsx
import { Popover } from 'heroui-native';
```
## Anatomy
```tsx
.........
```
* **Popover**: Main container that manages open/close state, positioning, and provides context to child components.
* **Popover.Trigger**: Clickable element that toggles popover visibility. Wraps any child element with press handlers.
* **Popover.Portal**: Renders popover content in a portal layer above other content. Ensures proper stacking and positioning.
* **Popover.Overlay**: Optional background overlay. Can be transparent or semi-transparent to capture outside clicks.
* **Popover.Content**: Container for popover content with positioning, styling, and collision detection. Supports both popover and bottom-sheet presentations.
* **Popover.Arrow**: Optional arrow element pointing to the trigger. Automatically positioned based on placement.
* **Popover.Close**: Close button for the popover. Can accept custom children or uses default close icon.
* **Popover.Title**: Optional title text with pre-styled typography.
* **Popover.Description**: Optional description text with muted styling.
## Usage
### Basic Usage
The Popover component uses compound parts to create floating content panels.
```tsx
......
```
### With Title and Description
Structure popover content with title and description for better information hierarchy.
```tsx
.........
```
### With Arrow
Add an arrow pointing to the trigger element for better visual connection.
```tsx
...
...
```
> **Note:** When using ``, you need to apply a border to `Popover.Content`, for instance using the `border border-border` class. This ensures the arrow visually connects properly with the content border.
### Width Control
Control the width of the popover content using the `width` prop.
```tsx
{
/* Fixed width in pixels */
}
...
...
;
{
/* Match trigger width */
}
...
...
;
{
/* Full width (100%) */
}
...
...
;
{
/* Auto-size to content (default) */
}
...
...
;
```
### Bottom Sheet Presentation
Use bottom sheet presentation for mobile-optimized interaction patterns.
> **Important:** The `presentation` prop on `Popover.Content` must match the `presentation` prop on `Popover.Root`. In development mode, a mismatch will throw an error.
```tsx
.........
```
### Placement Options
Control where the popover appears relative to the trigger element.
```tsx
...
...
```
### Alignment Options
Fine-tune content alignment along the placement axis.
```tsx
...
...
```
### Custom Animation
Configure custom animations for open and close transitions using the `animation` prop on `Popover.Root`.
```tsx
......
```
### Programmatic control
```tsx
// Open or close popover programmatically using ref
const popoverRef = useRef(null);
// Open programmatically
popoverRef.current?.open();
// Close programmatically
popoverRef.current?.close();
// Full example
Content;
```
## Example
```tsx
import { Ionicons } from '@expo/vector-icons';
import { Button, Popover, useThemeColor } from 'heroui-native';
import { Text, View } from 'react-native';
export default function PopoverExample() {
const themeColorMuted = useThemeColor('muted');
return (
Information
This popover includes a title and description to provide more
structured information to users.
);
}
```
You can find more examples in the [GitHub repository](https://github.com/heroui-inc/heroui-native/blob/rc/example/src/app/\(home\)/components/popover.tsx).
## API Reference
### Popover
| prop | type | default | description |
| --------------- | ----------------------------- | ----------- | ---------------------------------------------------------------------------------------------- |
| `children` | `ReactNode` | - | Children elements to be rendered inside the popover |
| `isOpen` | `boolean` | - | Whether the popover is open (controlled mode) |
| `isDefaultOpen` | `boolean` | - | The open state of the popover when initially rendered (uncontrolled mode) |
| `onOpenChange` | `(isOpen: boolean) => void` | - | Callback when the popover open state changes |
| `animation` | `AnimationRootDisableAll` | - | Animation configuration. Can be `false`, `"disabled"`, `"disable-all"`, `true`, or `undefined` |
| `presentation` | `'popover' \| 'bottom-sheet'` | `'popover'` | Presentation mode for the popover content |
| `asChild` | `boolean` | `false` | Whether to render as a child element |
| `...ViewProps` | `ViewProps` | - | All standard React Native View props are supported |
#### AnimationRootDisableAll
Animation configuration for popover root component. Can be:
* `false` or `"disabled"`: Disable only root animations
* `"disable-all"`: Disable all animations including children
* `true` or `undefined`: Use default animations
### Popover.Trigger
| prop | type | default | description |
| ------------------- | ---------------- | ------- | ------------------------------------------------------- |
| `children` | `ReactNode` | - | The trigger element content |
| `className` | `string` | - | Additional CSS classes for the trigger |
| `asChild` | `boolean` | `true` | Whether to render as a child element |
| `...PressableProps` | `PressableProps` | - | All standard React Native Pressable props are supported |
### Popover.Portal
| prop | type | default | description |
| -------------------------- | ----------- | ------- | ----------------------------------------------------------------------------------------------------------------------------- |
| `children` | `ReactNode` | - | The portal content (required) |
| `disableFullWindowOverlay` | `boolean` | `false` | When true on iOS, uses View instead of FullWindowOverlay. Enables element inspector; overlay won't appear above native modals |
| `hostName` | `string` | - | Optional name of the host element for the portal |
| `forceMount` | `boolean` | - | Whether to force mount the component in the DOM |
| `className` | `string` | - | Additional CSS classes for the portal container |
| `...ViewProps` | `ViewProps` | - | All standard React Native View props are supported |
### Popover.Overlay
| prop | type | default | description |
| ----------------------- | ------------------------- | ------- | ------------------------------------------------------------ |
| `className` | `string` | - | Additional CSS classes for the overlay |
| `closeOnPress` | `boolean` | `true` | Whether to close the popover when overlay is pressed |
| `forceMount` | `boolean` | - | Whether to force mount the component in the DOM |
| `animation` | `PopoverOverlayAnimation` | - | Animation configuration |
| `isAnimatedStyleActive` | `boolean` | `true` | Whether animated styles (react-native-reanimated) are active |
| `asChild` | `boolean` | `false` | Whether to render as a child element |
| `...Animated.ViewProps` | `Animated.ViewProps` | - | All Reanimated Animated.View props are supported |
#### PopoverOverlayAnimation
Animation configuration for popover overlay component. Can be:
* `false` or `"disabled"`: Disable all animations
* `true` or `undefined`: Use default animations
* `object`: Custom animation configuration
| prop | type | default | description |
| --------------- | -------------------------- | --------------------------- | ----------------------------------------------------------------------------------------- |
| `state` | `'disabled' \| boolean` | - | Disable animations while customizing properties |
| `opacity.value` | `[number, number, number]` | `[0, 1, 0]` | Opacity values \[idle, open, close] - Takes effect for bottom-sheet/dialog presentation |
| `entering` | `EntryOrExitLayoutType` | FadeIn with duration 200ms | Custom Keyframe animation for entering transition - Takes effect for popover presentation |
| `exiting` | `EntryOrExitLayoutType` | FadeOut with duration 150ms | Custom Keyframe animation for exiting transition - Takes effect for popover presentation |
### Popover.Content (Popover Presentation)
| prop | type | default | description |
| ------------------------- | ------------------------------------------------ | --------------- | ------------------------------------------------------------------------------------------------------- |
| `children` | `ReactNode` | - | The popover content |
| `presentation` | `'popover'` | `'popover'` | Presentation mode - must match Popover.Root presentation prop. When not provided, defaults to 'popover' |
| `width` | `number \| 'trigger' \| 'content-fit' \| 'full'` | `'content-fit'` | Width sizing strategy for the content |
| `placement` | `'top' \| 'bottom' \| 'left' \| 'right'` | `'bottom'` | Placement of the popover relative to trigger |
| `align` | `'start' \| 'center' \| 'end'` | `'center'` | Alignment along the placement axis |
| `avoidCollisions` | `boolean` | `true` | Whether to flip placement when close to viewport edges |
| `offset` | `number` | `9` | Distance from trigger element in pixels |
| `alignOffset` | `number` | `0` | Offset along the alignment axis in pixels |
| `disablePositioningStyle` | `boolean` | `false` | Whether to disable automatic positioning styles |
| `forceMount` | `boolean` | - | Whether to force mount the component in the DOM |
| `insets` | `Insets` | - | Screen edge insets to respect when positioning |
| `className` | `string` | - | Additional CSS classes for the content container |
| `animation` | `PopupPopoverContentAnimation` | - | Animation configuration |
| `isAnimatedStyleActive` | `boolean` | `true` | Whether animated styles (react-native-reanimated) are active |
| `asChild` | `boolean` | `false` | Whether to render as a child element |
| `...Animated.ViewProps` | `Animated.ViewProps` | - | All Reanimated Animated.View props are supported |
### Popover.Content (Bottom Sheet Presentation)
| prop | type | default | description |
| --------------------------- | ---------------------- | ------- | ---------------------------------------------------------------------------------------------- |
| `children` | `ReactNode` | - | The bottom sheet content |
| `presentation` | `'bottom-sheet'` | - | Presentation mode - must be 'bottom-sheet' and match Popover.Root presentation prop (required) |
| `contentContainerClassName` | `string` | - | Additional CSS classes for the content container |
| `contentContainerProps` | `BottomSheetViewProps` | - | Props for the content container |
| `enablePanDownToClose` | `boolean` | `true` | Whether pan down gesture closes the sheet |
| `backgroundStyle` | `ViewStyle` | - | Style for the bottom sheet background |
| `handleIndicatorStyle` | `ViewStyle` | - | Style for the bottom sheet handle indicator |
| `...BottomSheetProps` | `BottomSheetProps` | - | All @gorhom/bottom-sheet props are supported |
#### PopupPopoverContentAnimation
Animation configuration for popover content component (popover presentation). Can be:
* `false` or `"disabled"`: Disable all animations
* `true` or `undefined`: Use default animations
* `object`: Custom animation configuration
| prop | type | default | description |
| ---------- | ----------------------- | --------------------------------------------------------------- | ------------------------------------------------- |
| `state` | `'disabled' \| boolean` | - | Disable animations while customizing properties |
| `entering` | `EntryOrExitLayoutType` | Keyframe with translateY/translateX, scale, and opacity (200ms) | Custom Keyframe animation for entering transition |
| `exiting` | `EntryOrExitLayoutType` | Keyframe mirroring entering animation (150ms) | Custom Keyframe animation for exiting transition |
### Popover.Arrow
| prop | type | default | description |
| --------------------- | ---------------------------------------- | ------- | --------------------------------------------------------------------- |
| `className` | `string` | - | Additional CSS classes for the arrow |
| `height` | `number` | `12` | Height of the arrow in pixels |
| `width` | `number` | `20` | Width of the arrow in pixels |
| `fill` | `string` | - | Fill color of the arrow (defaults to content background) |
| `stroke` | `string` | - | Stroke (border) color of the arrow (defaults to content border color) |
| `strokeWidth` | `number` | `1` | Stroke width of the arrow border in pixels |
| `strokeBaselineInset` | `number` | `1` | Baseline inset in pixels for stroke alignment |
| `placement` | `'top' \| 'bottom' \| 'left' \| 'right'` | - | Placement of the popover (inherited from content) |
| `children` | `ReactNode` | - | Custom arrow content (replaces default SVG arrow) |
| `style` | `StyleProp` | - | Additional styles for the arrow container |
| `...ViewProps` | `ViewProps` | - | All standard React Native View props are supported |
### Popover.Close
Popover.Close extends [CloseButton](./close-button) and automatically handles popover dismissal when pressed.
### Popover.Title
| prop | type | default | description |
| -------------- | ----------- | ------- | -------------------------------------------------- |
| `children` | `ReactNode` | - | The title text content |
| `className` | `string` | - | Additional CSS classes for the title |
| `...TextProps` | `TextProps` | - | All standard React Native Text props are supported |
### Popover.Description
| prop | type | default | description |
| -------------- | ----------- | ------- | -------------------------------------------------- |
| `children` | `ReactNode` | - | The description text content |
| `className` | `string` | - | Additional CSS classes for the description |
| `...TextProps` | `TextProps` | - | All standard React Native Text props are supported |
## Hooks
### usePopover
Hook to access popover context values within custom components or compound components.
```tsx
import { usePopover } from 'heroui-native';
const CustomContent = () => {
const { isOpen, onOpenChange, triggerPosition } = usePopover();
// ... your implementation
};
```
**Returns:** `UsePopoverReturn`
| property | type | description |
| -------------------- | --------------------------------------------------- | ----------------------------------------------------------------- |
| `isOpen` | `boolean` | Whether the popover is currently open |
| `onOpenChange` | `(open: boolean) => void` | Callback function to change the popover open state |
| `isDefaultOpen` | `boolean \| undefined` | Whether the popover should be open by default (uncontrolled mode) |
| `isDisabled` | `boolean \| undefined` | Whether the popover is disabled |
| `triggerPosition` | `LayoutPosition \| null` | The position of the trigger element relative to the viewport |
| `setTriggerPosition` | `(triggerPosition: LayoutPosition \| null) => void` | Function to update the trigger element's position |
| `contentLayout` | `LayoutRectangle \| null` | The layout measurements of the popover content |
| `setContentLayout` | `(contentLayout: LayoutRectangle \| null) => void` | Function to update the content layout measurements |
| `nativeID` | `string` | Unique identifier for the popover instance |
**Note:** This hook must be used within a `Popover` component. It will throw an error if called outside of the popover context.
### usePopoverAnimation
Hook to access popover animation state values within custom components or compound components.
```tsx
import { usePopoverAnimation } from 'heroui-native';
const CustomContent = () => {
const { progress, isDragging } = usePopoverAnimation();
// ... your implementation
};
```
**Returns:** `UsePopoverAnimationReturn`
| property | type | description |
| ------------ | ---------------------- | ------------------------------------------------------------------ |
| `progress` | `SharedValue` | Progress value for the popover animation (0=idle, 1=open, 2=close) |
| `isDragging` | `SharedValue` | Dragging state shared value |
**Note:** This hook must be used within a `Popover` component. It will throw an error if called outside of the popover animation context.
## Special Notes
### Element Inspector (iOS)
Popover uses FullWindowOverlay on iOS. To enable the React Native element inspector during development, set `disableFullWindowOverlay={true}` on `Popover.Portal`. Tradeoff: the popover will not appear above native modals when disabled.
# Toast
**Category**: native
**URL**: https://v3.heroui.com/docs/native/components/toast
**Source**: https://raw.githubusercontent.com/heroui-inc/heroui/refs/heads/v3/apps/docs/content/docs/native/components/(overlays)/toast.mdx
> Displays temporary notification messages that appear at the top or bottom of the screen.
## Import
```tsx
import { Toast, useToast } from 'heroui-native';
```
## Anatomy
```tsx
.........
```
* **Toast**: Main container that displays notification messages. Handles positioning, animations, and swipe gestures.
* **Toast.Title**: Title text of the toast notification. Inherits variant styling from parent Toast context.
* **Toast.Description**: Descriptive text content displayed below the title.
* **Toast.Action**: Action button within the toast. Button variant is automatically determined based on toast variant but can be overridden.
* **Toast.Close**: Close button for dismissing the toast. Renders as an icon-only button that calls hide when pressed.
## Usage
### Usage Pattern 1: Simple String
Show a toast with a simple string message.
```tsx
const { toast } = useToast();
toast.show('This is a toast message');
```
### Usage Pattern 2: Config Object
Show a toast with label, description, variant, and action button using a config object.
```tsx
const { toast } = useToast();
toast.show({
variant: 'success',
label: 'You have upgraded your plan',
description: 'You can continue using HeroUI Chat',
icon: ,
actionLabel: 'Close',
onActionPress: ({ hide }) => hide(),
});
```
### Usage Pattern 3: Custom Component
Show a toast with a fully custom component for complete control over styling and layout.
```tsx
const { toast } = useToast();
toast.show({
component: (props) => (
Custom ToastThis is a custom toast component
),
});
```
**Note**: Toast items are memoized for performance. If you need to pass external state (like loading state) to a custom toast component, it will not update automatically. Use shared state techniques instead, such as React Context, state management libraries, or refs to ensure state updates propagate to the toast component.
### Disabling All Animations
Disable all animations including children by using `"disable-all"`. This cascades down to all child components (like Button in Toast.Action).
```tsx
const { toast } = useToast();
toast.show({
variant: 'success',
label: 'Operation completed',
description: 'All animations are disabled',
animation: 'disable-all',
});
```
Or with a custom component:
```tsx
const { toast } = useToast();
toast.show({
component: (props) => (
No animations
This toast has all animations disabled
Action
),
});
```
## Example
```tsx
import { Button, Toast, useToast, useThemeColor } from 'heroui-native';
import { View } from 'react-native';
export default function ToastExample() {
const { toast } = useToast();
const themeColorForeground = useThemeColor('foreground');
return (
);
}
```
You can find more examples in the [GitHub repository](https://github.com/heroui-inc/heroui-native/blob/rc/example/src/app/\(home\)/components/toast.tsx).
## Global Configuration
Configure toast behavior globally using `HeroUINativeProvider` config prop. Global configs serve as defaults for all toasts unless overridden locally.
> **Note**: For complete provider configuration options, see the [Provider documentation](/docs/native/getting-started/handbook/provider#toast-configuration).
### Insets
Insets control the distance of toast sides from screen edges. Insets are added to safe area insets. To set all toasts to have a side distance of 20px from screen edges, configure insets:
```tsx
{children}
```
### Content Wrapper with KeyboardAvoidingView
Wrap toast content with KeyboardAvoidingView to ensure toasts adjust when the keyboard appears:
```tsx
import {
KeyboardAvoidingView,
KeyboardProvider,
} from 'react-native-keyboard-controller';
import { HeroUINativeProvider } from 'heroui-native';
import { useCallback } from 'react';
function AppContent() {
const contentWrapper = useCallback(
(children: React.ReactNode) => (
{children}
),
[]
);
return (
{children}
);
}
```
### Default Props
Set global defaults for variant, placement, animation, and swipe behavior:
```tsx
{children}
```
## API Reference
### Toast
| prop | type | default | description |
| ----------------------- | ------------------------------------------------------------- | ----------- | ------------------------------------------------------------------------- |
| `variant` | `'default' \| 'accent' \| 'success' \| 'warning' \| 'danger'` | `'default'` | Visual variant of the toast |
| `placement` | `'top' \| 'bottom'` | `'top'` | Placement of the toast on screen |
| `isSwipeable` | `boolean` | `true` | Whether the toast can be swiped to dismiss and dragged with rubber effect |
| `animation` | `ToastRootAnimation` | - | Animation configuration |
| `isAnimatedStyleActive` | `boolean` | `true` | Whether animated styles (react-native-reanimated) are active |
| `className` | `string` | - | Additional CSS class for the toast container |
| `...ViewProps` | `ViewProps` | - | All standard React Native View props are supported |
#### ToastRootAnimation
Animation configuration for Toast component. Can be:
* `false` or `"disabled"`: Disable only root animations
* `"disable-all"`: Disable all animations including children
* `true` or `undefined`: Use default animations
* `object`: Custom animation configuration
| prop | type | default | description |
| ------------------------- | ---------------------------------------- | ---------------------------------------------------------------------------------------------------------------------------- | -------------------------------------------------------------------------------- |
| `state` | `'disabled' \| 'disable-all' \| boolean` | - | Disable animations while customizing properties |
| `opacity.value` | `[number, number]` | `[1, 0]` | Opacity interpolation values for fade effect as toasts move beyond visible stack |
| `opacity.timingConfig` | `WithTimingConfig` | `{ duration: 300 }` | Animation timing configuration for opacity transitions |
| `translateY.value` | `[number, number]` | `[0, 10]` | Translate Y interpolation values for peek effect of stacked toasts |
| `translateY.timingConfig` | `WithTimingConfig` | `{ duration: 300 }` | Animation timing configuration for translateY transitions |
| `scale.value` | `[number, number]` | `[1, 0.97]` | Scale interpolation values for depth effect of stacked toasts |
| `scale.timingConfig` | `WithTimingConfig` | `{ duration: 300 }` | Animation timing configuration for scale transitions |
| `entering.top` | `EntryOrExitLayoutType` | `FadeInUp` `.springify()` `.withInitialValues({ opacity: 1, transform: [{ translateY: -100 }] })` `.mass(3)` | Custom entering animation for top placement |
| `entering.bottom` | `EntryOrExitLayoutType` | `FadeInDown` `.springify()` `.withInitialValues({ opacity: 1, transform: [{ translateY: 100 }] })` `.mass(3)` | Custom entering animation for bottom placement |
| `exiting.top` | `EntryOrExitLayoutType` | Keyframe animation with `translateY: -100, scale: 0.97, opacity: 0.5` | Custom exiting animation for top placement |
| `exiting.bottom` | `EntryOrExitLayoutType` | Keyframe animation with `translateY: 100, scale: 0.97, opacity: 0.5` | Custom exiting animation for bottom placement |
### Toast.Title
| prop | type | default | description |
| -------------- | ----------------- | ------- | -------------------------------------------------- |
| `children` | `React.ReactNode` | - | Content to be rendered as title |
| `className` | `string` | - | Additional CSS classes |
| `...TextProps` | `TextProps` | - | All standard React Native Text props are supported |
### Toast.Description
| prop | type | default | description |
| -------------- | ----------------- | ------- | -------------------------------------------------- |
| `children` | `React.ReactNode` | - | Content to be rendered as description |
| `className` | `string` | - | Additional CSS classes |
| `...TextProps` | `TextProps` | - | All standard React Native Text props are supported |
### Toast.Action
Toast.Action extends all props from [Button](button) component. Button variant is automatically determined based on toast variant but can be overridden.
| prop | type | default | description |
| ----------- | ---------------------- | ------- | ---------------------------------------------------------------------------- |
| `children` | `React.ReactNode` | - | Content to be rendered as action button label |
| `variant` | `ButtonVariant` | - | Button variant. If not provided, automatically determined from toast variant |
| `size` | `'sm' \| 'md' \| 'lg'` | `'sm'` | Size of the action button |
| `className` | `string` | - | Additional CSS classes |
For inherited props including `onPress`, `isDisabled`, and all Button props, see [Button API Reference](button#api-reference).
### Toast.Close
Toast.Close extends all props from [Button](button) component.
| prop | type | default | description |
| ----------- | ----------------------------------- | ------- | ---------------------------------------------- |
| `children` | `React.ReactNode` | - | Custom close icon. Defaults to CloseIcon |
| `iconProps` | `{ size?: number; color?: string }` | - | Props for the default close icon |
| `size` | `'sm' \| 'md' \| 'lg'` | `'sm'` | Size of the close button |
| `className` | `string` | - | Additional CSS classes |
| `onPress` | `(event: any) => void` | - | Custom press handler. Defaults to hiding toast |
For inherited props including `isDisabled` and all Button props, see [Button API Reference](button#api-reference).
### ToastProviderProps
Props for configuring toast behavior globally via `HeroUINativeProvider` config prop.
| prop | type | default | description |
| -------------------------- | --------------------------------------------------- | ------- | ---------------------------------------------------------------------------------------------------------------------------- |
| `defaultProps` | `ToastGlobalConfig` | - | Global toast configuration used as defaults for all toasts |
| `disableFullWindowOverlay` | `boolean` | `false` | When true on iOS, uses View instead of FullWindowOverlay. Enables element inspector; toasts won't appear above native modals |
| `insets` | `ToastInsets` | - | Insets for spacing from screen edges (added to safe area insets) |
| `maxVisibleToasts` | `number` | `3` | Maximum number of visible toasts before opacity starts fading |
| `contentWrapper` | `(children: React.ReactNode) => React.ReactElement` | - | Custom wrapper function to wrap toast content |
| `children` | `React.ReactNode` | - | Children to render |
#### ToastGlobalConfig
Global toast configuration used as defaults for all toasts unless overridden locally.
| prop | type | description |
| ------------- | ------------------------------------------------------------- | ------------------------------------------------------------------------- |
| `variant` | `'default' \| 'accent' \| 'success' \| 'warning' \| 'danger'` | Visual variant of the toast |
| `placement` | `'top' \| 'bottom'` | Placement of the toast on screen |
| `isSwipeable` | `boolean` | Whether the toast can be swiped to dismiss and dragged with rubber effect |
| `animation` | `ToastRootAnimation` | Animation configuration for toast |
#### ToastInsets
Insets for spacing from screen edges. Values are added to safe area insets.
| prop | type | default | description |
| -------- | -------- | ------- | --------------------------------------------------------------------------------------------------------- |
| `top` | `number` | - | Inset from the top edge in pixels (added to safe area inset). Platform-specific: iOS = 0, Android = 12 |
| `bottom` | `number` | - | Inset from the bottom edge in pixels (added to safe area inset). Platform-specific: iOS = 6, Android = 12 |
| `left` | `number` | - | Inset from the left edge in pixels (added to safe area inset). Default: 12 |
| `right` | `number` | - | Inset from the right edge in pixels (added to safe area inset). Default: 12 |
## Hooks
### useToast
Hook to access toast functionality. Must be used within a `ToastProvider` (provided by `HeroUINativeProvider`).
| return value | type | description |
| ---------------- | -------------- | ---------------------------------------- |
| `toast` | `ToastManager` | Toast manager with show and hide methods |
| `isToastVisible` | `boolean` | Whether any toast is currently visible |
#### ToastManager
| method | type | description |
| ------ | ------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------ |
| `show` | `(options: string \| ToastShowOptions) => string` | Show a toast. Returns the ID of the shown toast. Supports three usage patterns: simple string, config object, or custom component |
| `hide` | `(ids?: string \| string[] \| 'all') => void` | Hide one or more toasts. No argument hides the last toast, 'all' hides all toasts, single ID or array of IDs hides specific toast(s) |
#### ToastShowOptions
Options for showing a toast. Can be either a config object with default styling or a custom component.
**When using config object (without component):**
| prop | type | default | description |
| --------------- | --------------------------------------------------------------------------------------------------------------------------------- | ------- | ----------------------------------------------------------------------------------- |
| `variant` | `'default' \| 'accent' \| 'success' \| 'warning' \| 'danger'` | - | Visual variant of the toast |
| `placement` | `'top' \| 'bottom'` | - | Placement of the toast on screen |
| `isSwipeable` | `boolean` | - | Whether the toast can be swiped to dismiss |
| `animation` | `ToastRootAnimation \| false \| "disabled" \| "disable-all"` | - | Animation configuration for toast |
| `duration` | `number \| 'persistent'` | `4000` | Duration in milliseconds before auto-hide. Set to 'persistent' to prevent auto-hide |
| `id` | `string` | - | Optional ID for the toast. If not provided, one will be generated |
| `label` | `string` | - | Label text for the toast |
| `description` | `string` | - | Description text for the toast |
| `actionLabel` | `string` | - | Action button label text |
| `onActionPress` | `(helpers: { show: (options: string \| ToastShowOptions) => string; hide: (ids?: string \| string[] \| 'all') => void }) => void` | - | Callback function called when the action button is pressed |
| `icon` | `React.ReactNode` | - | Icon element to display in the toast |
| `onShow` | `() => void` | - | Callback function called when the toast is shown |
| `onHide` | `() => void` | - | Callback function called when the toast is hidden |
**When using custom component:**
| prop | type | default | description |
| ----------- | ---------------------------------------------------- | ------- | ----------------------------------------------------------------------------------- |
| `id` | `string` | - | Optional ID for the toast. If not provided, one will be generated |
| `component` | `(props: ToastComponentProps) => React.ReactElement` | - | A function that receives toast props and returns a React element |
| `duration` | `number \| 'persistent'` | `4000` | Duration in milliseconds before auto-hide. Set to 'persistent' to prevent auto-hide |
| `onShow` | `() => void` | - | Callback function called when the toast is shown |
| `onHide` | `() => void` | - | Callback function called when the toast is hidden |
## Special Notes
### Element Inspector (iOS)
Toast uses FullWindowOverlay on iOS. To enable the React Native element inspector during development, set `disableFullWindowOverlay={true}` on `ToastProvider` (via `config.toast` when using HeroUINativeProvider). Tradeoff: toasts will not appear above native modals when disabled.
# PressableFeedback
**Category**: native
**URL**: https://v3.heroui.com/docs/native/components/pressable-feedback
**Source**: https://raw.githubusercontent.com/heroui-inc/heroui/refs/heads/v3/apps/docs/content/docs/native/components/(utilities)/pressable-feedback.mdx
> Container component that provides visual feedback for press interactions with automatic scale animation.
## Import
```tsx
import { PressableFeedback } from 'heroui-native';
```
## Anatomy
```tsx
...
```
* **PressableFeedback**: Pressable container with built-in scale animation. Manages press state and container dimensions, providing them to child compound parts via context. Use `animation={false}` to disable the built-in scale when using `PressableFeedback.Scale` instead.
* **PressableFeedback.Scale**: Scale animation wrapper for applying scale to a specific child element. Use this instead of the root's built-in scale when you need control over which element scales or need to apply `className` / `style` to the scale wrapper.
* **PressableFeedback.Highlight**: Highlight overlay for iOS-style press feedback. Renders an absolute-positioned layer that fades in on press.
* **PressableFeedback.Ripple**: Ripple overlay for Android-style press feedback. Renders a radial gradient circle that expands from the touch point.
## Usage
### Basic
PressableFeedback provides press-down scale feedback out of the box. This is the recommended way to use it in most cases.
```tsx
...
```
### With Highlight
Add a highlight overlay for iOS-style feedback effect alongside the built-in scale.
```tsx
...
```
### With Ripple
Add a ripple overlay for Android-style feedback effect alongside the built-in scale.
```tsx
...
```
### Custom Scale Animation
Customize the built-in scale animation via the `animation.scale` prop. Accepts `value`, `timingConfig`, and `ignoreScaleCoefficient`.
```tsx
...
```
### Custom Highlight Animation
Configure highlight overlay opacity and background color.
```tsx
...
```
### Custom Ripple Animation
Configure ripple effect color, opacity, and duration.
```tsx
...
```
### Scale on a Specific Child (PressableFeedback.Scale)
When you need to apply the scale animation to a specific element inside the container rather than the root itself, disable the root's built-in scale with `animation={false}` and use the `PressableFeedback.Scale` compound part. This gives you full control over which element scales and lets you apply `className` / `style` directly to the scale wrapper.
```tsx
...
```
You can combine it with Highlight or Ripple inside the Scale wrapper:
```tsx
...
```
### Disable All Animations
Set `animation="disable-all"` on the root to cascade-disable all animations including the built-in scale and any child compound parts (Scale, Highlight, Ripple).
```tsx
...
```
You can also disable all animations while keeping a scale config (e.g. for toggling at runtime):
```tsx
...
```
## Example
```tsx
import { PressableFeedback, Card, Button } from 'heroui-native';
import { Image } from 'expo-image';
import { LinearGradient } from 'expo-linear-gradient';
import { StyleSheet, View, Text } from 'react-native';
export default function PressableFeedbackExample() {
return (
Neo
Home robot
Available soonGet notified
);
}
```
You can find more examples in the [GitHub repository](https://github.com/heroui-inc/heroui-native/blob/rc/example/src/app/\(home\)/components/pressable-feedback.tsx).
## API Reference
### PressableFeedback
| prop | type | default | description |
| ----------------------- | -------------------------------- | ------- | ----------------------------------------------------------------------------------------------------------- |
| `children` | `React.ReactNode` | - | Content to be wrapped with press feedback |
| `isDisabled` | `boolean` | `false` | Whether the pressable component is disabled |
| `className` | `string` | - | Additional CSS classes |
| `animation` | `PressableFeedbackRootAnimation` | - | Customize scale via `{ scale: ... }`, `false` to disable root scale, `'disable-all'` to cascade-disable all |
| `isAnimatedStyleActive` | `boolean` | `true` | Whether the root's built-in animated styles are active |
| `...rest` | `AnimatedProps` | - | All Reanimated Animated Pressable props are supported |
#### PressableFeedbackRootAnimation
The root animation prop supports the standard `AnimationRoot` control flow:
* `true` or `undefined`: Use the default built-in scale animation
* `false` or `"disabled"`: Disable the root's built-in scale (use this when applying scale via `PressableFeedback.Scale` instead)
* `"disable-all"`: Cascade-disable all animations including the built-in scale and children (Scale, Highlight, Ripple)
* `object`: Custom configuration for the built-in scale
| prop | type | default | description |
| ------- | ---------------------------------------- | ------- | ------------------------------------------------------------------------------- |
| `scale` | `PressableFeedbackScaleAnimation` | - | Customize the built-in scale animation (value, timingConfig, etc.) |
| `state` | `'disabled' \| 'disable-all' \| boolean` | - | Control animation state while keeping configuration (e.g. for runtime toggling) |
### PressableFeedback.Scale
Use this compound part when you need to apply scale to a specific child element inside the container, instead of scaling the root itself. Set `animation={false}` on the root to disable its built-in scale when using this component.
| prop | type | default | description |
| ----------------------- | --------------------------------- | ------- | ------------------------------------------------------------ |
| `className` | `string` | - | Additional CSS classes |
| `animation` | `PressableFeedbackScaleAnimation` | - | Animation configuration for scale effect |
| `isAnimatedStyleActive` | `boolean` | `true` | Whether animated styles (react-native-reanimated) are active |
| `style` | `ViewStyle` | - | Additional styles |
| `...AnimatedProps` | `AnimatedProps` | - | All Reanimated Animated View props are supported |
#### PressableFeedbackScaleAnimation
Animation configuration for scale effect. Can be:
* `false` or `"disabled"`: Disable scale animation
* `true` or `undefined`: Use default scale animation
* `object`: Custom scale configuration
| prop | type | default | description |
| ------------------------ | ----------------------- | ---------------------------------------------------- | -------------------------------------------------------------------------- |
| `state` | `'disabled' \| boolean` | - | Disable animations while customizing properties |
| `value` | `number` | `0.985` | Scale value when pressed (automatically adjusted based on container width) |
| `timingConfig` | `WithTimingConfig` | `{ duration: 300, easing: Easing.out(Easing.ease) }` | Animation timing configuration |
| `ignoreScaleCoefficient` | `boolean` | `false` | Ignore automatic scale coefficient and use the scale value directly |
### PressableFeedback.Highlight
| prop | type | default | description |
| ----------------------- | ------------------------------------- | ------- | ------------------------------------------------------------ |
| `className` | `string` | - | Additional CSS classes |
| `animation` | `PressableFeedbackHighlightAnimation` | - | Animation configuration for highlight overlay |
| `isAnimatedStyleActive` | `boolean` | `true` | Whether animated styles (react-native-reanimated) are active |
| `style` | `ViewStyle` | - | Additional styles |
| `...AnimatedProps` | `AnimatedProps` | - | All Reanimated Animated View props are supported |
#### PressableFeedbackHighlightAnimation
Animation configuration for highlight overlay. Can be:
* `false` or `"disabled"`: Disable highlight animations
* `true` or `undefined`: Use default animations
* `object`: Custom animation configuration
| prop | type | default | description |
| ----------------------- | ----------------------- | ------------------- | ----------------------------------------------- |
| `state` | `'disabled' \| boolean` | - | Disable animations while customizing properties |
| `opacity.value` | `[number, number]` | `[0, 0.1]` | Opacity values \[unpressed, pressed] |
| `opacity.timingConfig` | `WithTimingConfig` | `{ duration: 200 }` | Animation timing configuration |
| `backgroundColor.value` | `string` | Theme-aware gray | Background color of highlight overlay |
### PressableFeedback.Ripple
| prop | type | default | description |
| ----------------------- | ----------------------------------------- | ------- | ------------------------------------------------------------ |
| `className` | `string` | - | Additional CSS classes for container slot |
| `classNames` | `ElementSlots` | - | Additional CSS classes for slots (container, ripple) |
| `styles` | `Partial>` | - | Styles for different parts of the ripple overlay |
| `animation` | `PressableFeedbackRippleAnimation` | - | Animation configuration for ripple overlay |
| `isAnimatedStyleActive` | `boolean` | `true` | Whether animated styles (react-native-reanimated) are active |
| `...ViewProps` | `Omit` | - | All View props except style are supported |
#### `styles`
| prop | type | description |
| ----------- | ----------- | ----------------------------- |
| `container` | `ViewStyle` | Styles for the container slot |
| `ripple` | `ViewStyle` | Styles for the ripple slot |
#### PressableFeedbackRippleAnimation
Animation configuration for ripple overlay. Can be:
* `false` or `"disabled"`: Disable ripple animations
* `true` or `undefined`: Use default animations
* `object`: Custom animation configuration
| prop | type | default | description |
| ------------------------------------ | -------------------------- | ----------------------- | ---------------------------------------------------------------------------- |
| `state` | `'disabled' \| boolean` | - | Disable animations while customizing properties |
| `backgroundColor.value` | `string` | Computed based on theme | Background color of ripple effect |
| `progress.baseDuration` | `number` | `1000` | Base duration for ripple progress (automatically adjusted based on diagonal) |
| `progress.minBaseDuration` | `number` | `750` | Minimum base duration for the ripple progress animation |
| `progress.ignoreDurationCoefficient` | `boolean` | `false` | Ignore automatic duration coefficient and use base duration directly |
| `opacity.value` | `[number, number, number]` | `[0, 0.1, 0]` | Opacity values \[start, peak, end] for ripple animation |
| `opacity.timingConfig` | `WithTimingConfig` | `{ duration: 200 }` | Animation timing configuration |
| `scale.value` | `[number, number, number]` | `[0, 1, 1]` | Scale values \[start, peak, end] for ripple animation |
| `scale.timingConfig` | `WithTimingConfig` | `{ duration: 200 }` | Animation timing configuration |
#### `ElementSlots`
Additional CSS classes for ripple slots:
| slot | description |
| ----------- | ------------------------------------------------------------------------------------------------------------------- |
| `container` | Outer container slot (`absolute inset-0`) - styles can be fully customized |
| `ripple` | Inner ripple slot (`absolute top-0 left-0 rounded-full`) - has animated properties that cannot be set via className |
# ScrollShadow
**Category**: native
**URL**: https://v3.heroui.com/docs/native/components/scroll-shadow
**Source**: https://raw.githubusercontent.com/heroui-inc/heroui/refs/heads/v3/apps/docs/content/docs/native/components/(utilities)/scroll-shadow.mdx
> Adds dynamic gradient shadows to scrollable content based on scroll position and overflow.
## Import
```tsx
import { ScrollShadow } from 'heroui-native';
```
## Anatomy
```tsx
...
```
* **ScrollShadow**: Main container that wraps scrollable components and adds dynamic gradient shadows at the edges based on scroll position and content overflow. Automatically detects scroll orientation (horizontal/vertical) and manages shadow visibility.
* **LinearGradientComponent**: Required prop that accepts a LinearGradient component from compatible libraries (expo-linear-gradient, react-native-linear-gradient, etc.) to render the gradient shadows.
## Usage
### Basic Usage
Wrap any scrollable component to automatically add edge shadows.
```tsx
...
```
### Horizontal Scrolling
The component auto-detects horizontal scrolling from the child's `horizontal` prop.
```tsx
```
### Custom Shadow Size
Control the gradient shadow height/width with the `size` prop.
```tsx
...
```
### Visibility Control
Specify which shadows to display using the `visibility` prop.
```tsx
.........
```
### Custom Shadow Color
Override the default shadow color which uses the theme's background.
```tsx
...
```
### With Custom Scroll Handler
**Important:** ScrollShadow internally converts the child to a Reanimated animated component. If you need to use the `onScroll` prop, you must use `useAnimatedScrollHandler` from react-native-reanimated.
```tsx
import { LinearGradient } from 'expo-linear-gradient';
import Animated, { useAnimatedScrollHandler } from 'react-native-reanimated';
const scrollHandler = useAnimatedScrollHandler({
onScroll: (event) => {
console.log(event.contentOffset.y);
},
});
...;
```
## Example
```tsx
import { ScrollShadow, Surface } from 'heroui-native';
import { LinearGradient } from 'expo-linear-gradient';
import { FlatList, ScrollView, Text, View } from 'react-native';
export default function ScrollShadowExample() {
const horizontalData = Array.from({ length: 10 }, (_, i) => ({
id: i,
title: `Card ${i + 1}`,
}));
return (
Horizontal List (
{item.title}
)}
showsHorizontalScrollIndicator={false}
contentContainerClassName="p-5 gap-4"
/>
Vertical ContentLong Content
Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do
eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim
ad minim veniam, quis nostrud exercitation ullamco laboris.
Sed ut perspiciatis unde omnis iste natus error sit voluptatem
accusantium doloremque laudantium, totam rem aperiam, eaque ipsa
quae ab illo inventore veritatis et quasi architecto beatae vitae.
);
}
```
You can find more examples in the [GitHub repository](https://github.com/heroui-inc/heroui-native/blob/rc/example/src/app/\(home\)/components/scroll-shadow.tsx).
## API Reference
### ScrollShadow
| prop | type | default | description |
| ------------------------- | ---------------------------------------------------------------------- | ------------ | --------------------------------------------------------------------------------------------------------------- |
| `children` | `React.ReactElement` | - | The scrollable component to enhance with shadows. Must be a single React element (ScrollView, FlatList, etc.) |
| `LinearGradientComponent` | `ComponentType<` `LinearGradientProps>` | **required** | LinearGradient component from any compatible library (expo-linear-gradient, react-native-linear-gradient, etc.) |
| `size` | `number` | `50` | Size (height/width) of the gradient shadow in pixels |
| `orientation` | `'horizontal' \| 'vertical'` | auto-detect | Orientation of the scroll shadow. If not provided, will auto-detect from child's `horizontal` prop |
| `visibility` | `'auto' \| 'top' \| 'bottom' \| 'left' \| 'right' \| 'both' \| 'none'` | `'auto'` | Visibility mode for the shadows. 'auto' shows shadows based on scroll position and content overflow |
| `color` | `string` | theme color | Custom color for the gradient shadow. If not provided, uses the theme's background color |
| `isEnabled` | `boolean` | `true` | Whether the shadow effect is enabled |
| `animation` | `ScrollShadowRootAnimation` | - | Animation configuration |
| `className` | `string` | - | Additional CSS classes to apply to the container |
| `...ViewProps` | `ViewProps` | - | All standard React Native View props are supported |
#### ScrollShadowRootAnimation
Animation configuration for ScrollShadow component. Can be:
* `false` or `"disabled"`: Disable only root animations
* `"disable-all"`: Disable all animations including children
* `true` or `undefined`: Use default animations
* `object`: Custom animation configuration
| prop | type | default | description |
| --------------- | ---------------------------------------- | -------- | ------------------------------------------------------------------------------------ |
| `state` | `'disabled' \| 'disable-all' \| boolean` | - | Disable animations while customizing properties |
| `opacity.value` | `[number, number]` | `[0, 1]` | `Opacity values [initial, active].` `For bottom/right shadow, this is reversed` |
### LinearGradientProps
The `LinearGradientComponent` prop expects a component that accepts these props:
| prop | type | description |
| ----------- | --------------------------------- | ------------------------------------------------------------------ |
| `colors` | `any` | Array of colors for the gradient |
| `locations` | `any` (optional) | Array of numbers defining the location of each gradient color stop |
| `start` | `any` (optional) | Start point of the gradient (e.g., `{ x: 0, y: 0 }`) |
| `end` | `any` (optional) | End point of the gradient (e.g., `{ x: 1, y: 0 }`) |
| `style` | `StyleProp` (optional) | Style to apply to the gradient view |
## Special Notes
**Important:** ScrollShadow internally converts the child to a Reanimated animated component. If you need to use the `onScroll` prop on your scrollable component, you must use `useAnimatedScrollHandler` from react-native-reanimated instead of the standard `onScroll` prop.
# Animation
**Category**: native
**URL**: https://v3.heroui.com/docs/native/getting-started/animation
**Source**: https://raw.githubusercontent.com/heroui-inc/heroui/refs/heads/v3/apps/docs/content/docs/native/getting-started/(handbook)/animation.mdx
> Add smooth animations and transitions to HeroUI Native components
All animations in HeroUI Native are built with [react-native-reanimated](https://docs.swmansion.com/react-native-reanimated/) and gesture control is handled by [react-native-gesture-handler](https://docs.swmansion.com/react-native-gesture-handler/). It's worth familiarizing yourself with these libraries if you want more control over animations.
## The `animation` Prop
Every animated component in HeroUI Native exposes a single `animation` prop that controls all animations for that component. This prop allows you to modify animation values, timing configurations, layout animations, or completely disable animations.
**Approach**: If you're working with animations, first look for the `animation` prop on the component you're using.
## Modifying Animations
You can customize animations by passing an object to the `animation` prop. Each component exposes different animation properties that you can modify. The approach is simple: if you want to slightly change the animation behavior of already written animations in components, we provide all necessary values for modification. If you want to write your own animations without relying on our written ones, you must create your own custom components with animations.
### Example 1: Simple Value Modification
Modify animation values like scale, opacity, or colors:
```tsx
import {Switch} from 'heroui-native';
;
```
### Example 2: Timing Configuration
Customize animation timing and easing:
```tsx
import {Accordion} from 'heroui-native';
;
```
### Example 3: Layout Animations (Entering/Exiting)
Customize entering and exiting animations using Reanimated's layout animations:
```tsx
import {Accordion} from 'heroui-native';
import {FadeInRight, FadeInLeft, ZoomIn} from 'react-native-reanimated';
import {Easing} from 'react-native-reanimated';
Content here
;
```
### Example 4: State Prop for Granular Control
The `state` prop allows you to disable animations while still customizing animation properties. This is useful when you want to fine-tune component behavior without enabling animations:
```tsx
import {Switch} from 'heroui-native';
```
The `state` prop accepts:
* `'disabled'`: Disable animations while allowing property customization
* `'disable-all'`: Disable all animations including children (only available at root level)
* `boolean`: Simple enable/disable control (`true` enables, `false` disables)
This provides more granular control over animation behavior, allowing you to customize properties without enabling animations.
## Disabling Animations
You can disable animations at different levels using the `animation` prop.
### Disable Options
* `animation={false}` or `animation="disabled"`: Disable animations for the specific component only
* `animation="disable-all"`: Disable all animations including children (only available at root level)
* `animation={true}` or `animation={undefined}`: Use default animations
### Component-Level Disabling
Disable animations for a specific component:
```tsx
```
### Root-Level Disabling (`disable-all`)
The `"disable-all"` option is only available at the root level of compound components. When used, it disables all animations including children, even if those children are not part of the compound component structure:
```tsx
// Disables all animations including Button components inside Card
$450Living room Sofa
```
**Important**: `"disable-all"` cascades down to all child components, including standalone components like `Button`, `Spinner`, etc., not just compound component parts.
## Global Animation Configuration
You can disable all HeroUI Native animations globally using the `HeroUINativeProvider`:
```tsx
import {HeroUINativeProvider} from 'heroui-native';
;
```
This will disable all animations across your entire application, regardless of individual component `animation` prop settings.
## Accessibility
Reduce motion is handled automatically under the hood. When a user enables "Reduce Motion" in their device accessibility settings, all animations are automatically disabled globally. This is handled by the `GlobalAnimationSettingsProvider` which checks `useReducedMotion()` from react-native-reanimated.
You don't need to do anything - the library respects the user's accessibility preferences automatically.
## Animation State Management
We keep disabled state of animations under control internally to ensure they look nice without unpredictable lags or jumps. When animations are disabled, components immediately jump to their final state rather than animating, preventing visual glitches or intermediate states.
## Children Render Function
Many components support a render function pattern for children, which is particularly handy when working with state like `isSelected`:
```tsx
import {Switch} from 'heroui-native';
{({isSelected, isDisabled}) => (
{isSelected ? : }
)}
;
```
This pattern allows you to conditionally render content based on component state, making it easy to create dynamic UIs that respond to selection, disabled states, and other component properties.
## Next Steps
* Learn about [Styling](/docs/native/getting-started/styling) approaches
* View [Theming](/docs/native/getting-started/theming) documentation
* Explore [Colors](/docs/native/getting-started/colors) documentation
# Colors
**Category**: native
**URL**: https://v3.heroui.com/docs/native/getting-started/colors
**Source**: https://raw.githubusercontent.com/heroui-inc/heroui/refs/heads/v3/apps/docs/content/docs/native/getting-started/(handbook)/colors.mdx
> Color palette and theming system for HeroUI Native
import {ColorSwatch, ColorPalette} from "@/components/color-swatch";
HeroUI Native uses CSS variables for colors that automatically switch between light and dark themes. All colors use the `oklch` color space for better color transitions.
## How It Works
HeroUI Native's color system is built on top of [Tailwind CSS v4](https://tailwindcss.com/docs/theme)'s theme via [Uniwind](https://uniwind.dev/). When you import `heroui-native/styles`, it uses Tailwind's built-in color palettes and maps them to semantic variables.
**Naming pattern:**
* Colors without a suffix are backgrounds (e.g., `--accent`)
* Colors with `-foreground` are for text on that background (e.g., `--accent-foreground`)
**Usage:**
```tsx
import { View, Text } from 'react-native';
// This gives you the right background and text colors
Hello;
```
### Base Colors
These four colors stay the same in all themes:
### Background & Surface
### Primary Colors
**Accent** — Your main brand color (used for primary actions)
**Accent Soft** — A lighter version for secondary actions
### Status Colors
For alerts, validation, and status messages:
### Form Field Colors
For consistent form field styling across input components:
### Other Colors
## How to Use Colors
**In your components:**
```tsx
import { View, Text } from 'react-native';
import { Button } from 'heroui-native';
Content;
```
**In CSS files:**
```css title="global.css"
/* Direct CSS variables */
.container {
flex: 1;
background-color: var(--accent);
width: 50px;
height: 50px;
border-radius: var(--radius);
}
```
## Default Theme
The complete theme definition can be found in ([variables.css](https://github.com/heroui-inc/heroui-native/blob/rc/src/styles/variables.css)). This theme automatically switches between light and dark modes through [Uniwind's theming system](https://docs.uniwind.dev/theming/basics), which supports system preferences and programmatic theme switching.
```css
@theme {
/* Primitive Colors (Do not change between light and dark) */
--white: oklch(100% 0 0);
--black: oklch(0% 0 0);
--snow: oklch(0.9911 0 0);
--eclipse: oklch(0.2103 0.0059 285.89);
/* Border */
--border-width: 1px;
--field-border-width: 0px;
/* Base radius */
--radius: 0.5rem;
--field-radius: calc(var(--radius) * 1.5);
/* Opacity */
--opacity-disabled: 0.5;
}
@layer theme {
:root {
@variant light {
/* Base Colors */
--background: oklch(0.9702 0 0);
--foreground: var(--eclipse);
/* Surface: Used for non-overlay components (cards, accordions, disclosure groups) */
--surface: var(--white);
--surface-foreground: var(--foreground);
--surface-secondary: oklch(0.9524 0.0013 286.37);
--surface-secondary-foreground: var(--foreground);
--surface-tertiary: oklch(0.9373 0.0013 286.37);
--surface-tertiary-foreground: var(--foreground);
/* Overlay: Used for floating/overlay components (dialogs, popovers, modals, menus) */
--overlay: var(--white);
--overlay-foreground: var(--foreground);
--muted: oklch(0.5517 0.0138 285.94);
--default: oklch(94% 0.001 286.375);
--default-foreground: var(--eclipse);
--accent: oklch(0.6204 0.195 253.83);
--accent-foreground: var(--snow);
/* Form Fields */
--field-background: var(--white);
--field-foreground: oklch(0.2103 0.0059 285.89);
--field-placeholder: var(--muted);
--field-border: transparent; /* no border by default on form fields */
/* Status Colors */
--success: oklch(0.7329 0.1935 150.81);
--success-foreground: var(--eclipse);
--warning: oklch(0.7819 0.1585 72.33);
--warning-foreground: var(--eclipse);
--danger: oklch(0.6532 0.2328 25.74);
--danger-foreground: var(--snow);
/* Component Colors */
--segment: var(--white);
--segment-foreground: var(--eclipse);
/* Misc Colors */
--border: oklch(90% 0.004 286.32);
--separator: oklch(74% 0.004 286.32);
--focus: var(--accent);
--link: var(--foreground);
/* Shadows */
--surface-shadow:
0 2px 4px 0 rgba(0, 0, 0, 0.04), 0 1px 2px 0 rgba(0, 0, 0, 0.06),
0 0 1px 0 rgba(0, 0, 0, 0.06);
--overlay-shadow:
0 2px 8px 0 rgba(0, 0, 0, 0.02), 0 -6px 12px 0 rgba(0, 0, 0, 0.01),
0 14px 28px 0 rgba(0, 0, 0, 0.03);
--field-shadow:
0 2px 4px 0 rgba(0, 0, 0, 0.04), 0 1px 2px 0 rgba(0, 0, 0, 0.06),
0 0 1px 0 rgba(0, 0, 0, 0.06);
}
@variant dark {
/* Base Colors */
--background: oklch(12% 0.005 285.823);
--foreground: var(--snow);
/* Surface: Used for non-overlay components (cards, accordions, disclosure groups) */
--surface: oklch(0.2103 0.0059 285.89);
--surface-foreground: var(--foreground);
--surface-secondary: oklch(0.257 0.0037 286.14);
--surface-secondary-foreground: var(--foreground);
--surface-tertiary: oklch(0.2721 0.0024 247.91);
--surface-tertiary-foreground: var(--foreground);
/* Overlay: Used for floating/overlay components (dialogs, popovers, modals, menus) - lighter for contrast */
--overlay: oklch(0.2103 0.0059 285.89);
--overlay-foreground: var(--foreground);
--muted: oklch(70.5% 0.015 286.067);
--default: oklch(27.4% 0.006 286.033);
--default-foreground: var(--snow);
--accent: oklch(0.6204 0.195 253.83);
--accent-foreground: var(--snow);
/* Form Field Defaults - Colors (only the ones that are different from light theme) */
--field-background: oklch(0.2103 0.0059 285.89);
--field-foreground: var(--foreground);
--field-placeholder: var(--muted);
--field-border: transparent; /* no border by default on form fields */
/* Status Colors */
--success: oklch(0.7329 0.1935 150.81);
--success-foreground: var(--eclipse);
--warning: oklch(0.8203 0.1388 76.34);
--warning-foreground: var(--eclipse);
--danger: oklch(0.594 0.1967 24.63);
--danger-foreground: var(--snow);
/* Component Colors */
--segment: oklch(0.3964 0.01 285.93);
--segment-foreground: var(--foreground);
/* Misc Colors */
--border: oklch(28% 0.006 286.033);
--separator: oklch(40% 0.006 286.033);
--focus: var(--accent);
--link: var(--foreground);
/* Shadows */
--surface-shadow: 0 0 0 0 transparent inset; /* No shadow on dark mode */
--overlay-shadow: 0 0 1px 0 rgba(255, 255, 255, 0.2) inset;
--field-shadow: 0 0 0 0 transparent inset; /* Transparent shadow to allow ring utilities to work */
}
}
}
```
## Customizing Colors
**Override existing colors:**
```css
@layer theme {
@variant light {
/* Override default colors */
--accent: oklch(0.65 0.25 270); /* Custom indigo accent */
--success: oklch(0.65 0.15 155);
}
@variant dark {
/* Override dark theme colors */
--accent: oklch(0.65 0.25 270);
--success: oklch(0.75 0.12 155);
}
}
```
**Tip:** Convert colors at [oklch.com](https://oklch.com)
**Add your own colors:**
```css
@layer theme {
@variant light {
--info: oklch(0.6 0.15 210);
--info-foreground: oklch(0.98 0 0);
}
@variant 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);
}
```
Now you can use it:
```tsx
import { View, Text } from 'react-native';
Info message;
```
> **Note**: To learn more about theme variables and how they work in Tailwind CSS v4, see the [Tailwind CSS Theme documentation](https://tailwindcss.com/docs/theme).
## useThemeColor Hook
The `useThemeColor` hook has been enhanced to support multiple colors selection, making it more flexible for complex theming scenarios.
**Multiple Colors Selection:**
You can now select multiple colors at once, which is useful when you need to work with related color values together:
```tsx
import { useThemeColor } from 'heroui-native';
// Select multiple colors at once
const [accent, accentForeground, success, danger] = useThemeColor([
'accent',
'accentForeground',
'success',
'danger',
]);
// Use the selected colors
Accent Text;
```
This enhancement improves performance when working with multiple color values and makes it easier to manage complex theming scenarios where multiple colors need to be selected and applied together.
## Quick Tips
* Always use color variables, not hard-coded values
* Use foreground/background pairs for good contrast
* Test in both light and dark modes
* The system respects user's theme preference automatically
## Related
* [Theming](/docs/native/getting-started/theming) - Learn about the theming system
* [Styling](/docs/native/getting-started/styling) - Styling components with CSS
* [Design Principles](/docs/native/getting-started/design-principles) - Understanding HeroUI's design philosophy
# Composition
**Category**: native
**URL**: https://v3.heroui.com/docs/native/getting-started/composition
**Source**: https://raw.githubusercontent.com/heroui-inc/heroui/refs/heads/v3/apps/docs/content/docs/native/getting-started/(handbook)/composition.mdx
> Build flexible UI with component composition patterns
HeroUI Native uses composition patterns to create flexible, customizable components. Change the rendered element, compose components together, and maintain full control over markup.
## Compound Components
HeroUI Native components use a compound component pattern with dot notation—components export sub-components as properties (e.g., `Button.Label`, `Dialog.Trigger`, `Accordion.Item`) that work together to form complete UI elements.
```tsx
import { Button, Dialog } from 'heroui-native';
function DialogExample() {
return (
);
}
```
## The asChild Prop
The `asChild` prop lets you change what element a component renders. When `asChild` is true, HeroUI Native clones the child element and merges props instead of rendering its default element.
```tsx
import { Button, Dialog } from 'heroui-native';
function DialogExample() {
return (
);
}
```
## Custom Components
Create your own components by composing HeroUI Native primitives:
```tsx
import { Button, Card, Popover } from 'heroui-native';
import { View } from 'react-native';
// Product card component
function ProductCard({ title, description, price, onBuy, ...props }) {
return (
{price}{title}{description}
);
}
// Popover button component
function PopoverButton({ children, popoverContent, ...props }) {
return (
{popoverContent}
);
}
// Usage
console.log('Buy')}
/>
InformationAdditional details here
}>
Show Info
```
## Custom Variants
Create custom variants using `tailwind-variants` to extend component styling. Note that text color classes must be applied to `Button.Label`, not the parent `Button`:
```tsx
import { Button } from 'heroui-native';
import type { ButtonRootProps } from 'heroui-native';
import { tv, type VariantProps } from 'tailwind-variants';
const customButtonVariants = tv({
base: 'font-semibold rounded-lg',
variants: {
intent: {
primary: 'bg-blue-500',
secondary: 'bg-gray-200',
danger: 'bg-red-500',
},
},
defaultVariants: {
intent: 'primary',
},
});
const customLabelVariants = tv({
base: '',
variants: {
intent: {
primary: 'text-white',
secondary: 'text-gray-800',
danger: 'text-white',
},
},
defaultVariants: {
intent: 'primary',
},
});
type CustomButtonVariants = VariantProps;
interface CustomButtonProps
extends Omit,
CustomButtonVariants {
className?: string;
labelClassName?: string;
}
export function CustomButton({
intent,
className,
labelClassName,
children,
...props
}: CustomButtonProps) {
return (
);
}
```
## Next Steps
* Learn about [Styling](/docs/native/getting-started/styling) system
* Explore [Theming](/docs/native/getting-started/theming) documentation
* Explore [Animation](/docs/native/getting-started/animation) options
# Portal
**Category**: native
**URL**: https://v3.heroui.com/docs/native/getting-started/portal
**Source**: https://raw.githubusercontent.com/heroui-inc/heroui/refs/heads/v3/apps/docs/content/docs/native/getting-started/(handbook)/portal.mdx
Portals let you render its children into a different part of your app. This is particularly useful for components that need to render above other content, such as modals, overlays, and popups.
## Default Setup
By default, the `PortalHost` is included in the `HeroUINativeProvider`, so there is no need to add it manually. The provider automatically sets up the portal system for all components that use portals.
## Advanced Use Cases
For advanced use cases, you can import `Portal` and `PortalHost` directly from `heroui-native` to create custom portal implementations:
```tsx
import { Portal, PortalHost } from "heroui-native";
import { View, Text } from "react-native";
function AppLayout() {
return (
Header ContentMain Content Area
{/* Portal host positioned at the top of the screen */}
);
}
function CustomNotification() {
return (
This notification appears at the top via Portal
);
}
```
In this example, the `CustomNotification` component uses a `Portal` to render its content at the location of the `PortalHost`, which is positioned at the top of the screen. This allows the notification to appear above all other content regardless of where it's defined in the component tree.
## State Management Considerations
State changes in parent components can cause unexpected issues with components rendered inside portals. For example, when a text input is placed directly inside a portal and the parent component re-renders, it can reset the input's auto-suggestions or cause other UI disruptions.
To avoid this, keep the state of interactive components (like text inputs) inside the portal by creating a separate component for the portal content. This isolates the state from parent re-renders.
### Example Pattern
```tsx
// ❌ Problematic: State in parent causes re-renders that affect portal content
function ParentComponent() {
const [dialogOpen, setDialogOpen] = useState(false);
const [inputValue, setInputValue] = useState(""); // State in parent
return (
);
}
// ✅ Correct: State managed inside separate component within portal
function ParentComponent() {
const [dialogOpen, setDialogOpen] = useState(false);
return (
);
}
function DialogFormContent({ onClose }: { onClose: () => void }) {
const [inputValue, setInputValue] = useState(""); // State inside portal
const [error, setError] = useState("");
return (
{error}
);
}
```
In the correct pattern, the `DialogFormContent` component manages its own state independently of the parent component. This ensures that parent re-renders (such as when `dialogOpen` changes) don't affect the input's internal state, preserving auto-suggestions and other input behaviors.
## API Reference
### PortalHost
By default, children of all Portal components will be rendered as its own children.
| Prop | Type | Note |
| ---- | -------- | --------------------------------------------------- |
| name | `string` | Provide when it is used as a custom host (optional) |
### Portal
| Prop | Type | Note |
| -------- | ----------------- | ------------------------------------------------------------------------------------- |
| name\* | `string` | Unique value otherwise the portal with the same name will replace the original portal |
| hostName | `string` | Provide when its children are to be rendered in a custom host (optional) |
| children | `React.ReactNode` | The content to render in the portal |
\* Required prop
## Related
* [Quick Start](/docs/native/getting-started/quick-start) - Basic setup guide
* View [Provider](/docs/native/getting-started/provider) documentation
# Provider
**Category**: native
**URL**: https://v3.heroui.com/docs/native/getting-started/provider
**Source**: https://raw.githubusercontent.com/heroui-inc/heroui/refs/heads/v3/apps/docs/content/docs/native/getting-started/(handbook)/provider.mdx
> Configure HeroUI Native provider with text, animation, and toast settings
The `HeroUINativeProvider` is the root provider component that configures and initializes HeroUI Native in your React Native application. It provides global configuration and portal management for your application.
## Overview
The provider serves as the main entry point for HeroUI Native, wrapping your application with essential contexts and configurations:
* **Safe Area Insets**: Automatically handles safe area insets updates via `SafeAreaListener` and syncs them with Uniwind for use in Tailwind classes (e.g., `pb-safe-offset-3`)
* **Text Configuration**: Global text component settings for consistency across all HeroUI components
* **Animation Configuration**: Global animation control to disable all animations across the application
* **Toast Configuration**: Global toast system configuration including insets, default props, and wrapper components
* **Portal Management**: Handles overlays, modals, and other components that render on top of the app hierarchy
## Basic Setup
Wrap your application root with the provider:
```tsx
import { HeroUINativeProvider } from 'heroui-native';
import { GestureHandlerRootView } from 'react-native-gesture-handler';
export default function App() {
return (
{/* Your app content */}
);
}
```
## Configuration Options
The provider accepts a `config` prop with the following options:
### Text Component Configuration
Global settings for all Text components within HeroUI Native. These props are carefully selected to include only those that make sense to configure globally across all Text components in the application:
```tsx
import { HeroUINativeProvider } from 'heroui-native';
import type { HeroUINativeConfig } from 'heroui-native';
const config: HeroUINativeConfig = {
textProps: {
// Disable font scaling for accessibility
allowFontScaling: false,
// Auto-adjust font size to fit container
adjustsFontSizeToFit: false,
// Maximum font size multiplier when scaling
maxFontSizeMultiplier: 1.5,
// Minimum font scale (iOS only, 0.01-1.0)
minimumFontScale: 0.5,
},
};
export default function App() {
return (
{/* Your app content */}
);
}
```
### Animation Configuration
Global animation configuration for the entire application:
```tsx
const config: HeroUINativeConfig = {
// Disable all animations across the application (cascades to all children)
animation: 'disable-all',
};
```
**Note**: When set to `'disable-all'`, all animations across the application will be disabled. This is useful for accessibility or performance optimization.
### Developer Information Configuration
Control developer-facing informational messages displayed in the console:
```tsx
const config: HeroUINativeConfig = {
devInfo: {
// Disable styling principles information message
stylingPrinciples: false,
},
};
```
**Note**: By default, informational messages are enabled. Set `stylingPrinciples: false` to disable the styling principles message that appears in the console during development.
### Toast Configuration
Configure the global toast system including insets, default props, and wrapper components. You can also disable the toast provider entirely:
**Option 1: Disable Toast Provider**
```tsx
const config: HeroUINativeConfig = {
// Disable toast provider entirely
toast: false,
// or
toast: 'disabled',
};
```
**Note**: When toast is disabled (`false` or `'disabled'`), the `ToastProvider` will not be rendered, and toast functionality will not be available in your application.
**Option 2: Configure Toast Provider**
```tsx
import { KeyboardAvoidingView } from 'react-native';
const config: HeroUINativeConfig = {
toast: {
// Global toast configuration (used as defaults for all toasts)
defaultProps: {
variant: 'default',
placement: 'top',
isSwipeable: true,
animation: true,
},
// Insets for spacing from screen edges (added to safe area insets)
insets: {
top: 0, // Default: iOS = 0, Android = 12
bottom: 6, // Default: iOS = 6, Android = 12
left: 12, // Default: 12
right: 12, // Default: 12
},
// Maximum number of visible toasts before opacity starts fading
maxVisibleToasts: 3,
// Custom wrapper function to wrap the toast content
contentWrapper: (children) => (
{children}
),
},
};
```
## Complete Example
Here's a comprehensive example showing all configuration options:
```tsx
import { HeroUINativeProvider } from 'heroui-native';
import type { HeroUINativeConfig } from 'heroui-native';
import { GestureHandlerRootView } from 'react-native-gesture-handler';
const config: HeroUINativeConfig = {
// Global text configuration
textProps: {
minimumFontScale: 0.5,
maxFontSizeMultiplier: 1.5,
allowFontScaling: true,
adjustsFontSizeToFit: false,
},
// Global animation configuration
animation: 'disable-all', // Optional: disable all animations
// Developer information messages configuration
devInfo: {
stylingPrinciples: true, // Optional: disable styling principles message
},
// Global toast configuration
// Option 1: Configure toast with custom settings
toast: {
defaultProps: {
variant: 'default',
placement: 'top',
},
insets: {
top: 0,
bottom: 6,
left: 12,
right: 12,
},
maxVisibleToasts: 3,
},
// Option 2: Disable toast entirely
// toast: false,
// or
// toast: 'disabled',
};
export default function App() {
return (
);
}
```
## Integration with Expo Router
When using Expo Router, wrap your root layout:
```tsx
// app/_layout.tsx
import { HeroUINativeProvider } from 'heroui-native';
import type { HeroUINativeConfig } from 'heroui-native';
import { Stack } from 'expo-router';
const config: HeroUINativeConfig = {
textProps: {
minimumFontScale: 0.5,
maxFontSizeMultiplier: 1.5,
},
};
export default function RootLayout() {
return (
);
}
```
## Architecture
### Provider Hierarchy
The `HeroUINativeProvider` internally composes multiple providers:
```
HeroUINativeProvider
├── SafeAreaListener (handles safe area insets updates)
│ └── GlobalAnimationSettingsProvider (animation configuration)
│ └── TextComponentProvider (text configuration)
│ └── ToastProvider (toast configuration, conditionally rendered)
│ └── Your App
│ └── PortalHost (for overlays)
```
**Note**: The `ToastProvider` is conditionally rendered based on the `toast` configuration. If `toast` is set to `false` or `'disabled'`, the `ToastProvider` will not be rendered, and the app content and `PortalHost` will be rendered directly under `TextComponentProvider`.
### Safe Area Insets Handling
The provider automatically wraps your application with [`SafeAreaListener`](https://appandflow.github.io/react-native-safe-area-context/api/safe-area-listener) from `react-native-safe-area-context`. This component listens to safe area insets and frame changes without triggering re-renders, and automatically updates Uniwind with the latest insets via the `onChange` callback.
## Raw Provider
`HeroUINativeProviderRaw` is a lightweight variant of `HeroUINativeProvider` designed for bundle optimization. It excludes `ToastProvider` and `PortalHost`, giving you a bare minimum starting point where you only install and add what you actually need.
### When to Use
Use `HeroUINativeProviderRaw` when you want full control over which dependencies are included in your bundle. With the raw provider imported from `heroui-native/provider-raw`, the following dependencies are optional and only required if you use the corresponding components:
* **react-native-screens** -- required for overlay components (Popover, Dialog)
* **@gorhom/bottom-sheet** -- required for BottomSheet component
* **react-native-svg** -- required for components that use icons (Accordion, Alert, Checkbox, etc.)
### Setup
```tsx
import {
HeroUINativeProviderRaw,
type HeroUINativeConfigRaw,
} from 'heroui-native/provider-raw';
import { GestureHandlerRootView } from 'react-native-gesture-handler';
const config: HeroUINativeConfigRaw = {
textProps: {
maxFontSizeMultiplier: 1.5,
},
};
export default function App() {
return (
{/* Your app content */}
);
}
```
### Adding Toast and Portal Manually
If you need toast or portal functionality with the raw provider, add them yourself:
```tsx
import { HeroUINativeProviderRaw } from 'heroui-native/provider-raw';
import { PortalHost } from 'heroui-native/portal';
import { ToastProvider } from 'heroui-native/toast';
export default function App() {
return (
{/* Your app content */}
);
}
```
### Provider Hierarchy
```
HeroUINativeProviderRaw
├── SafeAreaListener (handles safe area insets updates)
│ └── GlobalAnimationSettingsProvider (animation configuration)
│ └── TextComponentProvider (text configuration)
│ └── Your App
```
## Best Practices
### 1. Single Provider Instance
Always use a single `HeroUINativeProvider` at the root of your app. Don't nest multiple providers:
```tsx
// ❌ Bad
{/* Don't do this */}
// ✅ Good
```
### 2. Configuration Object
Define your configuration outside the component to prevent recreating on each render:
```tsx
// ❌ Bad
function App() {
return (
{/* ... */}
);
}
// ✅ Good
const config: HeroUINativeConfig = {
textProps: {
maxFontSizeMultiplier: 1.5,
},
};
function App() {
return (
{/* ... */}
);
}
```
### 3. Text Configuration
Consider accessibility when configuring text props:
```tsx
const config: HeroUINativeConfig = {
textProps: {
// Allow font scaling for accessibility
allowFontScaling: true,
// But limit maximum scale
maxFontSizeMultiplier: 1.5,
},
};
```
## TypeScript Support
The provider is fully typed. Import types for better IDE support:
```tsx
import { HeroUINativeProvider, type HeroUINativeConfig } from 'heroui-native';
const config: HeroUINativeConfig = {
// Full type safety and autocomplete
textProps: {
allowFontScaling: true,
maxFontSizeMultiplier: 1.5,
},
animation: 'disable-all', // Optional: disable all animations
devInfo: {
stylingPrinciples: true, // Optional: disable styling principles message
},
// Toast configuration options:
// - false or 'disabled': Disable toast provider
// - ToastProviderProps object: Configure toast settings
toast: {
defaultProps: {
variant: 'default',
placement: 'top',
},
insets: {
top: 0,
bottom: 6,
left: 12,
right: 12,
},
},
};
```
## Related
* [Quick Start](/docs/native/getting-started/quick-start) - Basic setup guide
* [Theming](/docs/native/getting-started/theming) - Customize colors and themes
* [Styling](/docs/native/getting-started/styling) - Style components with Tailwind
# Styling
**Category**: native
**URL**: https://v3.heroui.com/docs/native/getting-started/styling
**Source**: https://raw.githubusercontent.com/heroui-inc/heroui/refs/heads/v3/apps/docs/content/docs/native/getting-started/(handbook)/styling.mdx
> Style HeroUI Native components with Tailwind or StyleSheet API
HeroUI Native components provide flexible styling options: Tailwind CSS utilities, StyleSheet API, and render props for dynamic styling.
## Styling Principles
HeroUI Native is built with `className` as the go-to styling solution. You can use Tailwind CSS classes via the `className` prop on all components.
**StyleSheet precedence:** The `style` prop (StyleSheet API) can be used and has precedence over `className` when both are provided. This allows you to override Tailwind classes when needed.
**Animated styles:** Some style properties are animated using `react-native-reanimated` and, like StyleSheet styles, they have precedence over `className`. To identify which styles are animated and cannot be used via `className`:
* **Hover over `className` in your IDE** - The TypeScript definitions will show which properties are available
* **Check component documentation** - Each component page includes a link to the component's style source at the top, which contains notes about animated properties
**Customizing animated styles:** If styles are occupied by animation, you can modify them via the `animation` prop on components that support it.
## Basic Styling
**Using className:** All HeroUI Native components accept `className` props:
```tsx
import { Button } from 'heroui-native';
;
```
**Using style:** Components also accept inline styles via the `style` prop:
```tsx
import { Button } from 'heroui-native';
;
```
## Render Props
Use a render function to access component state and customize content dynamically:
```tsx
import { RadioGroup, Label, cn } from 'heroui-native';
{({ isSelected, isInvalid, isDisabled }) => (
<>
{isSelected && }
>
)}
;
```
## Creating Wrapper Components
Create reusable custom components using [tailwind-variants](https://tailwind-variants.org/)—a Tailwind CSS first-class variant API:
```tsx
import { Button } from 'heroui-native';
import type { ButtonRootProps } from 'heroui-native';
import { tv, type VariantProps } from 'tailwind-variants';
const customButtonVariants = tv({
base: 'font-semibold rounded-lg',
variants: {
intent: {
primary: 'bg-blue-500',
secondary: 'bg-gray-200',
danger: 'bg-red-500',
},
},
defaultVariants: {
intent: 'primary',
},
});
const customLabelVariants = tv({
base: '',
variants: {
intent: {
primary: 'text-white',
secondary: 'text-gray-800',
danger: 'text-white',
},
},
defaultVariants: {
intent: 'primary',
},
});
type CustomButtonVariants = VariantProps;
interface CustomButtonProps
extends Omit,
CustomButtonVariants {
className?: string;
labelClassName?: string;
}
export function CustomButton({
intent,
className,
labelClassName,
children,
...props
}: CustomButtonProps) {
return (
);
}
```
## Using Component classNames
Each HeroUI Native component exports a `classNames` object that contains the same styling functions used internally by the component. This is particularly useful when you want to style your own custom components to match the appearance of HeroUI Native components.
For example, you can style a custom `Link` component to look like a `Button`:
```tsx
import { buttonClassNames, cn } from 'heroui-native';
import { Pressable, Text } from 'react-native';
interface LinkProps {
href: string;
variant?: 'primary' | 'secondary' | 'outline' | 'ghost';
size?: 'sm' | 'md' | 'lg';
children: React.ReactNode;
className?: string;
}
export function Link({
href,
variant = 'primary',
size = 'md',
children,
className,
}: LinkProps) {
return (
{
// Handle navigation
}}
>
{children}
);
}
```
**Available classNames exports:**
Each component exports its `classNames` object. For example:
* `buttonClassNames` - Contains `root` and `label` functions
* `cardClassNames` - Contains `root`, `header`, `body`, `footer`, `label`, and `description` functions
* `chipClassNames` - Contains `root` and `label` functions
* And many more...
**Usage pattern:**
```tsx
import { buttonClassNames } from 'heroui-native';
// Use with variant and size options
const rootClasses = buttonClassNames.root({
variant: 'primary',
size: 'md',
className: 'custom-class', // Optional: merge with your own classes
});
const labelClasses = buttonClassNames.label({
variant: 'primary',
size: 'md',
});
```
The `classNames` functions accept the same variant props as the components themselves, allowing you to maintain visual consistency across your custom components and HeroUI Native components.
## Responsive Design
HeroUI Native supports Tailwind's responsive breakpoint system via [Uniwind](https://docs.uniwind.dev/breakpoints). Use breakpoint prefixes like `sm:`, `md:`, `lg:`, and `xl:` to apply styles conditionally based on screen width.
**Mobile-first approach:** Start with mobile styles (no prefix), then use breakpoints to enhance for larger screens.
### Responsive Typography and Spacing
```tsx
import { Button } from 'heroui-native';
import { View, Text } from 'react-native';
Responsive Heading
;
```
### Responsive Layouts
```tsx
import { View, Text } from 'react-native';
{/* Mobile: 1 column, Tablet: 2 columns, Desktop: 3 columns */}
Item 1;
```
**Default breakpoints:**
* `sm`: 640px
* `md`: 768px
* `lg`: 1024px
* `xl`: 1280px
* `2xl`: 1536px
For custom breakpoints and more details, see the [Uniwind breakpoints documentation](https://docs.uniwind.dev/breakpoints).
## Utilities
HeroUI Native provides utility functions to assist with styling components.
### cn Utility
The `cn` utility function merges Tailwind CSS classes with proper conflict resolution. It's particularly useful when combining conditional classes or merging classes from props:
````tsx
import { cn } from 'heroui-native';
import { View } from 'react-native';
function MyComponent({ className, isActive }) {
return (
);
}
```;
The `cn` utility is powered by `tailwind-variants` and includes:
- Automatic Tailwind class merging (`twMerge: true`)
- Custom opacity class group support
- Proper conflict resolution (later classes override earlier ones)
**Example with conflicts:**
```tsx
// 'bg-accent' overrides 'bg-background'
cn('bg-background p-4', 'bg-accent');
// Result: 'p-4 bg-accent'
````
### useThemeColor Hook
Retrieves theme color values from CSS variables. Supports both single color and multiple colors for efficient batch retrieval.
**Single color usage:**
````tsx
import { useThemeColor } from 'heroui-native';
function MyComponent() {
const accentColor = useThemeColor('accent');
const dangerColor = useThemeColor('danger');
return (
Error message
);
}
```;
**Multiple colors usage (more efficient):**
```tsx
import { useThemeColor } from 'heroui-native';
function MyComponent() {
const [accentColor, backgroundColor, dangerColor] = useThemeColor([
'accent',
'background',
'danger',
]);
return (
Error message
);
}
```;
**Type signatures:**
```tsx
// Single color
useThemeColor(themeColor: ThemeColor): string
// Multiple colors (with type inference for tuples)
useThemeColor(
themeColor: T
): CreateStringTuple
// Multiple colors (array)
useThemeColor(themeColor: ThemeColor[]): string[]
````
Available theme colors include: `background`, `foreground`, `surface`, `accent`, `default`, `success`, `warning`, `danger`, and all their variants (hover, soft, foreground, etc.), plus semantic colors like `muted`, `border`, `separator`, `field`, `overlay`, and more.
## Next Steps
* Learn about [Animation](/docs/native/getting-started/animation) techniques
* Explore [Theming](/docs/native/getting-started/theming) system
* Explore [Colors](/docs/native/getting-started/colors) documentation
# Theming
**Category**: native
**URL**: https://v3.heroui.com/docs/native/getting-started/theming
**Source**: https://raw.githubusercontent.com/heroui-inc/heroui/refs/heads/v3/apps/docs/content/docs/native/getting-started/(handbook)/theming.mdx
> Customize HeroUI Native's design system with CSS variables and global styles
HeroUI Native uses CSS variables for theming. Customize everything from colors to component styles using standard CSS.
## How It Works
HeroUI Native's theming system is built on top of [Tailwind CSS v4](https://tailwindcss.com/docs/theme)'s theme via [Uniwind](https://uniwind.dev/). When you import `heroui-native/styles`, it uses Tailwind's built-in color palettes, maps them to semantic variables, automatically switches between light and dark themes, and uses CSS layers and the `@theme` directive for organization.
**Naming pattern:**
* Colors without a suffix are backgrounds (e.g., `--accent`)
* Colors with `-foreground` are for text on that background (e.g., `--accent-foreground`)
## Quick Start
**Apply colors in your components:**
```tsx
import { View, Text } from 'react-native';
Your app content;
```
**Switch themes:**
HeroUI Native automatically supports dark mode through [Uniwind](https://docs.uniwind.dev/theming/basics). The theme switches between light and dark variants based on system preferences or manual selection:
```tsx
import { Uniwind, useUniwind } from 'uniwind';
import { Button } from 'heroui-native';
function ThemeToggle() {
const { theme } = useUniwind();
return (
);
}
```
**Override colors:**
```css
/* global.css */
@layer theme {
@variant light {
/* Override any color variable */
--accent: oklch(0.65 0.25 270); /* Custom indigo accent */
--success: oklch(0.65 0.15 155);
}
@variant dark {
--accent: oklch(0.65 0.25 270);
--success: oklch(0.75 0.12 155);
}
}
```
> **Note**: See [Colors](/docs/native/getting-started/colors) for the complete color palette and visual reference.
**Create your own theme:**
Create multiple themes using Uniwind's variant system. For complete custom theme documentation, see the [Uniwind Custom Themes Guide](https://docs.uniwind.dev/theming/custom-themes).
**Important:** All themes must define the same variables. See the [Default Theme](/docs/native/getting-started/colors#default-theme) section for a complete list of all required variables.
```css
/* global.css */
@layer theme {
:root {
@variant ocean-light {
/* Base Colors */
--background: oklch(0.95 0.02 230);
--foreground: oklch(0.25 0.04 230);
/* Surface: Used for non-overlay components (cards, accordions, disclosure groups) */
--surface: oklch(0.98 0.01 230);
--surface-foreground: oklch(0.3 0.045 230);
--surface-secondary: oklch(0.96 0.012 230);
--surface-secondary-foreground: oklch(0.3 0.045 230);
--surface-tertiary: oklch(0.94 0.015 230);
--surface-tertiary-foreground: oklch(0.3 0.045 230);
/* Overlay: Used for floating/overlay components (dialogs, popovers, modals, menus) */
--overlay: oklch(0.998 0.003 230);
--overlay-foreground: oklch(0.3 0.045 230);
--muted: oklch(0.55 0.035 230);
--default: oklch(0.94 0.018 230);
--default-foreground: oklch(0.4 0.05 230);
/* Accent */
--accent: oklch(0.6 0.2 230);
--accent-foreground: oklch(0.98 0.005 230);
/* Form Field Defaults - Colors */
--field-background: oklch(0.98 0.01 230);
--field-foreground: oklch(0.25 0.04 230);
--field-placeholder: var(--muted);
--field-border: transparent;
/* Status Colors */
--success: oklch(0.72 0.14 165);
--success-foreground: oklch(0.25 0.08 165);
--warning: oklch(0.78 0.12 85);
--warning-foreground: oklch(0.3 0.08 85);
--danger: oklch(0.68 0.18 15);
--danger-foreground: oklch(0.98 0.005 15);
/* Component Colors */
--segment: oklch(0.98 0.01 230);
--segment-foreground: oklch(0.25 0.04 230);
/* Misc Colors */
--border: oklch(0 0 0 / 0%);
--separator: oklch(0.91 0.015 230);
--focus: var(--accent);
--link: oklch(0.62 0.17 230);
/* Shadows */
--surface-shadow:
0 2px 4px 0 rgba(0, 0, 0, 0.04), 0 1px 2px 0 rgba(0, 0, 0, 0.06),
0 0 1px 0 rgba(0, 0, 0, 0.06);
--overlay-shadow:
0 2px 8px 0 rgba(0, 0, 0, 0.02), 0 -6px 12px 0 rgba(0, 0, 0, 0.01),
0 14px 28px 0 rgba(0, 0, 0, 0.03);
--field-shadow:
0 2px 4px 0 rgba(0, 0, 0, 0.04), 0 1px 2px 0 rgba(0, 0, 0, 0.06),
0 0 1px 0 rgba(0, 0, 0, 0.06);
}
@variant ocean-dark {
/* Base Colors */
--background: oklch(0.15 0.04 230);
--foreground: oklch(0.94 0.01 230);
/* Surface: Used for non-overlay components (cards, accordions, disclosure groups) */
--surface: oklch(0.2 0.048 230);
--surface-foreground: oklch(0.9 0.015 230);
--surface-secondary: oklch(0.24 0.046 230);
--surface-secondary-foreground: oklch(0.9 0.015 230);
--surface-tertiary: oklch(0.27 0.044 230);
--surface-tertiary-foreground: oklch(0.9 0.015 230);
/* Overlay: Used for floating/overlay components (dialogs, popovers, modals, menus) */
--overlay: oklch(0.23 0.045 230);
--overlay-foreground: oklch(0.9 0.015 230);
--muted: oklch(0.5 0.04 230);
--default: oklch(0.25 0.05 230);
--default-foreground: oklch(0.88 0.018 230);
/* Accent */
--accent: oklch(0.72 0.21 230);
--accent-foreground: oklch(0.15 0.04 230);
/* Form Field Defaults - Colors */
--field-background: var(--default);
--field-foreground: var(--foreground);
--field-placeholder: var(--muted);
--field-border: transparent;
/* Status Colors */
--success: oklch(0.68 0.16 165);
--success-foreground: oklch(0.95 0.008 165);
--warning: oklch(0.75 0.14 90);
--warning-foreground: oklch(0.2 0.04 90);
--danger: oklch(0.65 0.2 20);
--danger-foreground: oklch(0.95 0.008 20);
/* Component Colors */
--segment: oklch(0.22 0.046 230);
--segment-foreground: oklch(0.9 0.015 230);
/* Misc Colors */
--border: oklch(0 0 0 / 0%);
--separator: oklch(0.28 0.045 230);
--focus: var(--accent);
--link: oklch(0.75 0.18 230);
/* Shadows */
--surface-shadow: 0 0 0 0 transparent inset; /* No shadow on dark mode */
--overlay-shadow: 0 0 1px 0 rgba(255, 255, 255, 0.3) inset;
--field-shadow: 0 0 0 0 transparent inset; /* Transparent shadow to allow ring utilities to work */
}
}
}
```
**Important:** When adding custom themes, you must register them in your Metro config:
```js
// metro.config.js
const { withUniwindConfig } = require('uniwind/metro');
const {
wrapWithReanimatedMetroConfig,
} = require('react-native-reanimated/metro-config');
const config = {
// ... your existing config
};
module.exports = withUniwindConfig(wrapWithReanimatedMetroConfig(config), {
cssEntryFile: './global.css',
dtsFile: './src/uniwind.d.ts',
extraThemes: ['ocean-light', 'ocean-dark'],
});
```
Apply themes in your app:
```tsx
import { Uniwind } from 'uniwind';
import { Button } from 'heroui-native';
function App() {
return (
);
}
```
## Adding Custom Colors
Add your own semantic colors to the theme:
```css
@layer theme {
@variant light {
--info: oklch(0.6 0.15 210);
--info-foreground: oklch(0.98 0 0);
}
@variant dark {
--info: oklch(0.7 0.12 210);
--info-foreground: oklch(0.15 0 0);
}
}
/* Make the color available to Tailwind */
@theme inline {
--color-info: var(--info);
--color-info-foreground: var(--info-foreground);
}
```
Now use it in your components:
```tsx
import { View, Text } from 'react-native';
Info message;
```
## Custom Fonts
To use a custom font family in your app, you need to load the fonts and then override the font CSS variables.
### 1. Load Fonts in Your App
First, load your custom fonts (using Expo's `useFonts` hook for example):
```tsx
import { useFonts } from 'expo-font';
import { HeroUINativeProvider } from 'heroui-native';
import {
YourFont_400Regular,
YourFont_500Medium,
YourFont_600SemiBold,
} from '@expo-google-fonts/your-font';
export default function App() {
const [fontsLoaded] = useFonts({
YourFont_400Regular,
YourFont_500Medium,
YourFont_600SemiBold,
});
if (!fontsLoaded) {
return null; // Or return a loading screen
}
return {/* Your app content */};
}
```
### 2. Configure Font CSS Variables
After loading the fonts, override the font CSS variables in your `global.css` file:
```css
@theme {
--font-normal: 'YourFont-400Regular';
--font-medium: 'YourFont-500Medium';
--font-semibold: 'YourFont-600SemiBold';
}
```
**Note:** The font names in CSS variables should match the PostScript names of your loaded fonts. Check your font package documentation or use the font names exactly as they appear in your `useFonts` hook.
All HeroUI Native components automatically use these font variables, ensuring consistent typography throughout your app.
## Variables Reference
HeroUI defines three types of variables:
1. **Base Variables** — Non-changing values like `--white`, `--black`
2. **Theme Variables** — Colors that change between light/dark themes
3. **Calculated Variables** — Automatically generated hover (pressed) states and size variants
For a complete reference, see: [Colors Documentation](/docs/native/getting-started/colors), [Default Theme Variables](https://github.com/heroui-inc/heroui-native/blob/rc/src/styles/variables.css), [Shared Theme Utilities](https://github.com/heroui-inc/heroui-native/blob/rc/src/styles/theme.css)
**Calculated variables (Tailwind):**
We use Tailwind's `@theme` directive to automatically create calculated variables for hover (pressed) states and radius variants. These are defined in [theme.css](https://github.com/heroui-inc/heroui-native/blob/rc/src/styles/theme.css):
```css
@theme inline static {
--color-background: var(--background);
--color-foreground: var(--foreground);
--color-surface: var(--surface);
--color-surface-foreground: var(--surface-foreground);
--color-surface-hover: color-mix(in oklab, var(--surface) 92%, var(--surface-foreground) 8%);
--color-surface-secondary: var(--surface-secondary);
--color-surface-secondary-foreground: var(--surface-secondary-foreground);
--color-surface-tertiary: var(--surface-tertiary);
--color-surface-tertiary-foreground: var(--surface-tertiary-foreground);
--color-overlay: var(--overlay);
--color-overlay-foreground: var(--overlay-foreground);
--color-muted: var(--muted);
--color-accent: var(--accent);
--color-accent-foreground: var(--accent-foreground);
--color-segment: var(--segment);
--color-segment-foreground: var(--segment-foreground);
--color-border: var(--border);
--color-separator: var(--separator);
--color-focus: var(--focus);
--color-link: var(--link);
--color-default: var(--default);
--color-default-foreground: var(--default-foreground);
--color-success: var(--success);
--color-success-foreground: var(--success-foreground);
--color-warning: var(--warning);
--color-warning-foreground: var(--warning-foreground);
--color-danger: var(--danger);
--color-danger-foreground: var(--danger-foreground);
/* Form Field Tokens */
--color-field: var(--field-background, var(--default));
--color-field-foreground: var(--field-foreground, var(--foreground));
--color-field-placeholder: var(--field-placeholder, var(--muted));
--color-field-border: var(--field-border, var(--border));
--radius-field: var(--field-radius, var(--radius-xl));
--border-width-field: var(--field-border-width, var(--border-width));
--shadow-surface: var(--surface-shadow);
--shadow-overlay: var(--overlay-shadow);
--shadow-field: var(--field-shadow);
/* Calculated Variables */
/* Colors */
/* --- background shades --- */
--color-background-secondary: color-mix(in oklab, var(--background) 96%, var(--foreground) 4%);
--color-background-tertiary: color-mix(in oklab, var(--background) 92%, var(--foreground) 8%);
--color-background-inverse: var(--foreground);
/* ------------------------- */
--color-default-hover: color-mix(in oklab, var(--default) 96%, var(--default-foreground) 4%);
--color-accent-hover: color-mix(in oklab, var(--accent) 90%, var(--accent-foreground) 10%);
--color-success-hover: color-mix(in oklab, var(--success) 90%, var(--success-foreground) 10%);
--color-warning-hover: color-mix(in oklab, var(--warning) 90%, var(--warning-foreground) 10%);
--color-danger-hover: color-mix(in oklab, var(--danger) 90%, var(--danger-foreground) 10%);
/* Form Field Colors */
--color-field-hover: color-mix(in oklab, var(--field-background, var(--default)) 90%, var(--field-foreground, var(--foreground)) 2%);
--color-field-focus: var(--field-background, var(--default));
--color-field-border-hover: color-mix(in oklab, var(--field-border, var(--border)) 88%, var(--field-foreground, var(--foreground)) 10%);
--color-field-border-focus: color-mix(in oklab, var(--field-border, var(--border)) 74%, var(--field-foreground, var(--foreground)) 22%);
/* Soft Colors */
--color-accent-soft: color-mix(in oklab, var(--accent) 15%, transparent);
--color-accent-soft-foreground: var(--accent);
--color-accent-soft-hover: color-mix(in oklab, var(--accent) 20%, transparent);
--color-danger-soft: color-mix(in oklab, var(--danger) 15%, transparent);
--color-danger-soft-foreground: var(--danger);
--color-danger-soft-hover: color-mix(in oklab, var(--danger) 20%, transparent);
--color-warning-soft: color-mix(in oklab, var(--warning) 15%, transparent);
--color-warning-soft-foreground: var(--warning);
--color-warning-soft-hover: color-mix(in oklab, var(--warning) 20%, transparent);
--color-success-soft: color-mix(in oklab, var(--success) 15%, transparent);
--color-success-soft-foreground: var(--success);
--color-success-soft-hover: color-mix(in oklab, var(--success) 20%, transparent);
/* Separator Colors - Levels */
--color-separator-secondary: color-mix(in oklab, var(--surface) 85%, var(--surface-foreground) 15%);
--color-separator-tertiary: color-mix(in oklab, var(--surface) 81%, var(--surface-foreground) 19%);
/* Border Colors - Levels (progressive contrast: default → secondary → tertiary) */
/* Light mode: lighter → darker | Dark mode: darker → lighter */
--color-border-secondary: color-mix(in oklab, var(--surface) 78%, var(--surface-foreground) 22%);
--color-border-tertiary: color-mix(in oklab, var(--surface) 66%, var(--surface-foreground) 34%);
/* Radius and default sizes - defaults can change by just changing the --radius */
--radius-xs: calc(var(--radius) * 0.25); /* 0.125rem (2px) */
--radius-sm: calc(var(--radius) * 0.5); /* 0.25rem (4px) */
--radius-md: calc(var(--radius) * 0.75); /* 0.375rem (6px) */
--radius-lg: calc(var(--radius) * 1); /* 0.5rem (8px) */
--radius-xl: calc(var(--radius) * 1.5); /* 0.75rem (12px) */
--radius-2xl: calc(var(--radius) * 2); /* 1rem (16px) */
--radius-3xl: calc(var(--radius) * 3); /* 1.5rem (24px) */
--radius-4xl: calc(var(--radius) * 4); /* 2rem (32px) */
}
```
Form controls now rely on the `--field-*` variables and their calculated hover/focus variants. Update them in your theme to restyle inputs, checkboxes, radios, and OTP slots without impacting surfaces like buttons or cards.
## Resources
* [Colors Documentation](/docs/native/getting-started/colors)
* [Styling Guide](/docs/native/getting-started/styling)
* [Tailwind CSS v4 Theming](https://tailwindcss.com/docs/theme)
* [OKLCH Color Tool](https://oklch.com)
# Design Principles
**Category**: native
**URL**: https://v3.heroui.com/docs/native/getting-started/design-principles
**Source**: https://raw.githubusercontent.com/heroui-inc/heroui/refs/heads/v3/apps/docs/content/docs/native/getting-started/(overview)/design-principles.mdx
> Core principles that guide HeroUI v3's design and development
HeroUI Native follows 9 core principles that prioritize clarity, accessibility, customization, and developer experience.
## Core Principles
### 1. Semantic Intent Over Visual Style
Use semantic naming (primary, secondary, tertiary) instead of visual descriptions (solid, flat, bordered). Inspired by [Uber's Base design system](https://base.uber.com/6d2425e9f/p/756216-button), variants follow a clear hierarchy:
```tsx
// ✅ Semantic variants communicate hierarchy
```
| Variant | Purpose | Usage |
| ------------- | --------------------------------- | ---------------- |
| **Primary** | Main action to move forward | 1 per context |
| **Secondary** | Alternative actions | Multiple allowed |
| **Tertiary** | Dismissive actions (cancel, skip) | Sparingly |
| **Danger** | Destructive actions | When needed |
### 2. Accessibility as Foundation
Accessibility follows mobile development best practices with proper touch accessibility, focus management, and screen reader support built into every component. All components include proper accessibility labels and semantic structure for VoiceOver (iOS) and TalkBack (Android).
```tsx
import { Tabs } from 'heroui-native';
ProfileSecurityContentContent
```
### 3. Composition Over Configuration
Compound components let you rearrange, customize, or omit parts as needed. Use dot notation to compose components exactly as you need them.
```tsx
// Compose parts to build exactly what you need
import { Accordion } from 'heroui-native';
Question Text
Answer content
```
### 4. Progressive Disclosure
Start simple, add complexity only when needed. Components work with minimal props and scale up as requirements grow.
```tsx
import { Button, Spinner } from 'heroui-native';
import { Feather } from '@expo/vector-icons';
// Level 1: Minimal
// Level 2: Enhanced
// Level 3: Advanced
```
### 5. Predictable Behavior
Consistent patterns across all components: sizes (`sm`, `md`, `lg`), variants, and className support. Same API, same behavior.
```tsx
import { Button, Chip, Avatar } from 'heroui-native';
// All components follow the same patterns
SuccessJD
```
### 6. Type Safety First
Full TypeScript support with IntelliSense, auto-completion, and compile-time error detection. Extend types for custom components.
```tsx
import type { ButtonRootProps } from 'heroui-native';
// Type-safe props and event handlers
// Extend types for custom components
interface CustomButtonProps extends Omit {
intent: 'save' | 'cancel' | 'delete';
}
```
### 7. Developer Experience Excellence
Clear APIs, descriptive errors, IntelliSense and AI-friendly markdown docs.
### 8. Complete Customization
Beautiful defaults out-of-the-box. Transform the entire look with CSS variables through [Uniwind's theming system](https://docs.uniwind.dev/theming/basics). Every slot is customizable.
```css
/* Custom colors using Uniwind's theme layer */
@layer theme {
@variant light {
--accent: oklch(0.65 0.25 270); /* Custom indigo accent */
--background: oklch(0.98 0 0); /* Custom background */
}
@variant dark {
--accent: oklch(0.65 0.25 270);
--background: oklch(0.15 0 0);
}
}
/* Radius customization */
@theme {
--radius: 0.75rem; /* Increase for rounder components */
}
```
### 9. Open and Extensible
Wrap, extend, and customize components to match your needs. Create custom wrappers or apply custom styles using className.
```tsx
import { Button } from 'heroui-native';
import type { ButtonRootProps } from 'heroui-native';
// Custom wrapper component
interface CTAButtonProps extends Omit {
intent?: 'primary-cta' | 'secondary-cta' | 'minimal';
}
const CTAButton = ({
intent = 'primary-cta',
children,
...props
}: CTAButtonProps) => {
const variantMap = {
'primary-cta': 'primary',
'secondary-cta': 'secondary',
'minimal': 'ghost'
} as const;
return (
);
};
// Usage
Get StartedLearn More
```
**Extend with Tailwind Variants:**
```tsx
import { Button } from 'heroui-native';
import { tv } from 'tailwind-variants';
// Extend button styles with custom variants
const myButtonVariants = tv({
base: 'px-4 py-2 rounded-lg',
variants: {
variant: {
'primary-cta': 'bg-accent px-8 py-4 shadow-lg',
'secondary-cta': 'border-2 border-accent px-6 py-3',
}
},
defaultVariants: {
variant: 'primary-cta',
}
});
// Label variants for text colors (must be applied to Button.Label)
const myLabelVariants = tv({
base: '',
variants: {
variant: {
'primary-cta': 'text-accent-foreground',
'secondary-cta': 'text-accent',
}
},
defaultVariants: {
variant: 'primary-cta',
}
});
// Use the custom variants
function CustomButton({ variant, className, labelClassName, children, ...props }) {
return (
);
}
// Usage
Get StartedLearn More
```
# Quick Start
**Category**: native
**URL**: https://v3.heroui.com/docs/native/getting-started/quick-start
**Source**: https://raw.githubusercontent.com/heroui-inc/heroui/refs/heads/v3/apps/docs/content/docs/native/getting-started/(overview)/quick-start.mdx
> Get started with HeroUI Native in minutes
## Getting Started
### 1. Install HeroUI Native
```bash
npm install heroui-native
```
```bash
pnpm add heroui-native
```
```bash
yarn add heroui-native
```
```bash
bun add heroui-native
```
### 2. Install Mandatory Peer Dependencies
```bash
npm install react-native-screens@^4.16.0 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 @gorhom/bottom-sheet@^5.2.8
```
```bash
pnpm add react-native-screens@^4.16.0 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 @gorhom/bottom-sheet@^5.2.8
```
```bash
yarn add react-native-screens@^4.16.0 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 @gorhom/bottom-sheet@^5.2.8
```
```bash
bun add react-native-screens@^4.16.0 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 @gorhom/bottom-sheet@^5.2.8
```
It's recommended to use the exact versions specified above to avoid compatibility issues. Version mismatches may cause unexpected bugs.
### 3. Set Up Uniwind
Follow the [Uniwind installation guide](https://docs.uniwind.dev/quickstart) to set up Tailwind CSS for React Native.
If you're migrating from NativeWind, see the [migration guide](https://docs.uniwind.dev/migration-from-nativewind).
### 4. Configure global.css
Inside your `global.css` file add the following imports:
```css
@import 'tailwindcss';
@import 'uniwind';
@import 'heroui-native/styles';
/* Path to the heroui-native lib inside node_modules relative to global.css */
/* Examples:
* - If global.css is at project root: ./node_modules/heroui-native/lib
* - If global.css is in app/: ../node_modules/heroui-native/lib
* - If global.css is in src/styles/: ../../node_modules/heroui-native/lib
*/
@source './node_modules/heroui-native/lib';
```
### 5. Wrap Your App with Provider
Wrap your application with `HeroUINativeProvider`. You must wrap it with `GestureHandlerRootView`:
```tsx
import { HeroUINativeProvider } from 'heroui-native';
import { GestureHandlerRootView } from 'react-native-gesture-handler';
export default function App() {
return (
{/* Your app content */}
);
}
```
> **Note**: For advanced configuration options including text props, animation settings, and toast configuration, see the [Provider documentation](/docs/native/getting-started/provider).
### 6. Use Your First Component
```tsx
import { Button } from 'heroui-native';
import { View } from 'react-native';
export default function MyComponent() {
return (
);
}
```
### 7. Reduce Bundle Size with Granular Exports
If you want to reduce bundle size and import only the components you need, our library provides granular exports for each component:
```tsx
// Granular imports - use when you need only a few components
import { HeroUINativeProvider } from "heroui-native/provider";
import { Button } from "heroui-native/button";
import { Card } from "heroui-native/card";
// General import - imports the whole library, use when you're using many components
import { Button, Card } from "heroui-native";
```
Granular imports are ideal when you only need a few components, as they help keep your bundle size smaller. General imports from `heroui-native` will include the entire library, which is convenient when you're using many components throughout your app.
**Available granular exports:**
* `heroui-native/provider` - Provider component
* `heroui-native/provider-raw` - Lightweight provider (keeps bare minimum to start)
* `heroui-native/[component-name]` - Individual components
* `heroui-native/portal` - Portal utilities
* `heroui-native/toast` - Toast provider and utilities
* `heroui-native/utils` - Utility functions
* `heroui-native/hooks` - Custom hooks
**Important**: To keep the bundle size under control, you must follow the pattern with granular imports consistently. Even one general import from `heroui-native` will break this optimization strategy.
> **Tip**: For even more control over your bundle, consider using [`HeroUINativeProviderRaw`](/docs/native/getting-started/provider#raw-provider) — a lightweight provider that excludes `ToastProvider` and `PortalHost`, making dependencies like `react-native-screens`, `@gorhom/bottom-sheet`, and `react-native-svg` fully optional.
## What's Next?
* [HeroUI Native Provider](/docs/native/getting-started/provider)
* [Styling Guide](/docs/native/getting-started/styling)
* [Theming Documentation](/docs/native/getting-started/theming)
## Running on Web (Expo)
HeroUI Native is currently not recommended for web use. We are focusing on mobile platforms (iOS and Android) at this time. For web development, please use [HeroUI React](/docs/react/getting-started/quick-start) instead.
# Agent Skills
**Category**: native
**URL**: https://v3.heroui.com/docs/native/getting-started/agent-skills
**Source**: https://raw.githubusercontent.com/heroui-inc/heroui/refs/heads/v3/apps/docs/content/docs/native/getting-started/(ui-for-agents)/agent-skills.mdx
> Enable AI assistants to build mobile UIs with HeroUI Native components
HeroUI Native Skills give your AI assistant comprehensive knowledge of HeroUI Native components, patterns, and best practices for React Native development.
### Installation
```bash
curl -fsSL https://v3.heroui.com/install | bash -s heroui-native
```
Or using the skills package:
```bash
npx skills add heroui-inc/heroui
```
Support Claude Code, Cursor, OpenCode and more.
### Usage
Skills are **automatically discovered** by your AI assistant, or call it directly using `/heroui-native` command.
Simply ask your AI assistant to:
* Build mobile components using HeroUI Native
* Create screens with HeroUI Native components
* Customize themes and styles
* Access component documentation
For more complex use cases, use the [MCP Server](/docs/native/getting-started/mcp-server) which provides real-time access to component documentation and source code.
### What's Included
* HeroUI Native installation guide
* All HeroUI Native components with props, examples, and usage patterns
* Theming and styling guidelines with Uniwind
* Design principles and composition patterns
### Structure
```
skills/heroui-native/
├── SKILL.md # Main skill documentation
├── LICENSE.txt # MIT license
└── scripts/ # Utility scripts
├── list_components.mjs
├── get_component_docs.mjs
├── get_theme.mjs
└── get_docs.mjs
```
### Related Documentation
* [Agent Skills Specification](https://agentskills.io/home) - Learn about the Agent Skills format
* [Claude Agent Skills](https://platform.claude.com/docs/en/agents-and-tools/agent-skills/overview) - Claude's Skills documentation
* [Cursor Skills](https://cursor.com/docs/context/skills) - Using Skills in Cursor
* [OpenCode Skills](https://opencode.ai/docs/skills) - Using Skills in OpenCode
# AGENTS.md
**Category**: native
**URL**: https://v3.heroui.com/docs/native/getting-started/agents-md
**Source**: https://raw.githubusercontent.com/heroui-inc/heroui/refs/heads/v3/apps/docs/content/docs/native/getting-started/(ui-for-agents)/agents-md.mdx
> Download HeroUI Native documentation for AI coding agents
Download HeroUI Native documentation directly into your project for AI assistants to reference.
**Note:** The `agents-md` command is specifically for HeroUI React v3 and HeroUI Native. Other CLI commands (like `add`, `init`, `upgrade`, etc.) are for HeroUI v2 (for now).
### Usage
```bash
npx heroui-cli@latest agents-md --native
```
Or specify output file:
```bash
npx heroui-cli@latest agents-md --native --output AGENTS.md
```
### What It Does
* Downloads latest HeroUI Native docs to `.heroui-docs/native/`
* Generates an index in `AGENTS.md` or `CLAUDE.md`
* Adds `.heroui-docs/` to `.gitignore` automatically
### Options
* `--native` - Download Native docs only
* `--output ` - Target file(s) (e.g., `AGENTS.md` or `AGENTS.md CLAUDE.md`)
* `--ssh` - Use SSH for git clone
### Requirements
* Tailwind CSS >= v4 (via Uniwind)
### Related Documentation
* [AGENTS.md](https://agents.md/) - Learn about the AGENTS.md format for coding agents
* [CLAUDE.md](https://code.claude.com/docs/en/best-practices#write-an-effective-claude-md) - Claude equivalent of AGENTS.md
* [AGENTS.md vs Skills](https://vercel.com/blog/agents-md-outperforms-skills-in-our-agent-evals) - AGENTS.md performance
# LLMs.txt
**Category**: native
**URL**: https://v3.heroui.com/docs/native/getting-started/llms-txt
**Source**: https://raw.githubusercontent.com/heroui-inc/heroui/refs/heads/v3/apps/docs/content/docs/native/getting-started/(ui-for-agents)/llms-txt.mdx
> Enable AI assistants like Claude, Cursor, and Windsurf to understand HeroUI Native
We provide [LLMs.txt](https://llmstxt.org/) files to make HeroUI Native documentation accessible to AI coding assistants.
## Available Files
**Core documentation:**
* [/native/llms.txt](/native/llms.txt) — Quick reference index for Native documentation
* [/native/llms-full.txt](/native/llms-full.txt) — Complete HeroUI Native documentation
**For limited context windows:**
* [/native/llms-components.txt](/native/llms-components.txt) — Component documentation only
* [/native/llms-patterns.txt](/native/llms-patterns.txt) — Common patterns and recipes
**All platforms:**
* [/llms.txt](/llms.txt) — Quick reference index (React + Native)
* [/llms-full.txt](/llms-full.txt) — Complete documentation (React + Native)
* [/llms-components.txt](/llms-components.txt) — All component documentation
* [/llms-patterns.txt](/llms-patterns.txt) — All patterns and recipes
## Integration
**Claude Code:** Tell Claude to reference the documentation:
```
Use HeroUI Native documentation from https://v3.heroui.com/native/llms.txt
```
Or add to your project's `.claude` file for automatic loading.
**Cursor:** Use the `@Docs` feature:
```
@Docs https://v3.heroui.com/native/llms-full.txt
```
[Learn more](https://docs.cursor.com/context/@-symbols/@-docs)
**Windsurf:** Add to your `.windsurfrules` file:
```
#docs https://v3.heroui.com/native/llms-full.txt
```
[Learn more](https://docs.codeium.com/windsurf/memories#memories-and-rules)
**Other AI tools:** Most AI assistants can reference documentation by URL. Simply provide:
```
https://v3.heroui.com/native/llms.txt
```
**For component-specific documentation:**
```
https://v3.heroui.com/native/llms-components.txt
```
**For patterns and best practices:**
```
https://v3.heroui.com/native/llms-patterns.txt
```
## Contributing
Found an issue with AI-generated code? Help us improve our LLMs.txt files on [GitHub](https://github.com/heroui-inc/heroui).
# MCP Server
**Category**: native
**URL**: https://v3.heroui.com/docs/native/getting-started/mcp-server
**Source**: https://raw.githubusercontent.com/heroui-inc/heroui/refs/heads/v3/apps/docs/content/docs/native/getting-started/(ui-for-agents)/mcp-server.mdx
> Access HeroUI Native documentation directly in your AI assistant
The HeroUI MCP Server gives AI assistants direct access to HeroUI Native component documentation, making it easier to build with HeroUI in AI-powered development environments.
The MCP server currently supports **heroui-native** and [stdio transport](https://modelcontextprotocol.io/specification/2025-06-18/basic/transports#stdio). Published at `@heroui/native-mcp` on npm. View the source code on [GitHub](https://github.com/heroui-inc/heroui-mcp).
As we add more components to HeroUI Native, they'll be available in the MCP server too.
## Quick Setup
**Cursor:**
Or manually add to **Cursor Settings** → **Tools** → **MCP Servers**:
```json title=".cursor/mcp.json"
{
"mcpServers": {
"heroui-native": {
"command": "npx",
"args": ["-y", "@heroui/native-mcp@latest"]
}
}
}
```
Alternatively, add the following to your `~/.cursor/mcp.json` file. To learn more, see the [Cursor documentation](https://cursor.com/docs/context/mcp).
**Claude Code:** Run this command in your terminal:
```bash
claude mcp add heroui-native -- npx -y @heroui/native-mcp@latest
```
Or manually add to your project's `.mcp.json` file:
```json title=".mcp.json"
{
"mcpServers": {
"heroui-native": {
"command": "npx",
"args": ["-y", "@heroui/native-mcp@latest"]
}
}
}
```
After adding the configuration, restart Claude Code and run `/mcp` to see the HeroUI MCP server in the list. If you see **Connected**, you're ready to use it.
See the [Claude Code MCP documentation](https://docs.claude.com/en/docs/claude-code/mcp) for more details.
**Windsurf:** Add the HeroUI server to your project's `.windsurf/mcp.json` configuration file:
```json title=".windsurf/mcp.json"
{
"mcpServers": {
"heroui-native": {
"command": "npx",
"args": ["-y", "@heroui/native-mcp@latest"]
}
}
}
```
After adding the configuration, restart Windsurf to activate the MCP server.
See the [Windsurf MCP documentation](https://docs.windsurf.com/windsurf/cascade/mcp) for more details.
**Zed:** Add the HeroUI server to your `settings.json` configuration file. Open settings via Command Palette (`zed: open settings`) or use `Cmd-,` (Mac) / `Ctrl-,` (Linux):
```json title="settings.json"
{
"context_servers": {
"heroui-native": {
"command": "npx",
"args": ["-y", "@heroui/native-mcp@latest"],
"env": {}
}
}
}
```
After adding the configuration, restart Zed and open the Agent Panel settings view. Check that the indicator dot next to the heroui-native server is green with "Server is active" tooltip.
See the [Zed MCP documentation](https://zed.dev/docs/ai/mcp) for more details.
**VS Code:** To configure MCP in VS Code with GitHub Copilot, add the HeroUI server to your project's `.vscode/mcp.json` configuration file:
```json title=".vscode/mcp.json"
{
"mcpServers": {
"heroui-native": {
"command": "npx",
"args": ["-y", "@heroui/native-mcp@latest"]
}
}
}
```
After adding the configuration, open `.vscode/mcp.json` and click **Start** next to the heroui-native server.
See the [VS Code MCP documentation](https://code.visualstudio.com/docs/copilot/customization/mcp-servers) for more details.
## Usage
Once configured, ask your AI assistant questions like:
* "Help me install HeroUI Native in my Expo app"
* "Show me all HeroUI Native components"
* "What props does the Button component have?"
* "Give me an example of using the Card component"
* "What are the theme variables for dark mode?"
### Automatic Updates
The MCP server can help you upgrade to the latest HeroUI Native version:
```bash
"Hey Cursor, update HeroUI Native to the latest version"
```
Your AI assistant will automatically:
* Compare your current version with the latest release
* Review the changelog for breaking changes
* Apply the necessary code updates to your project
This works for any version upgrade, whether you're updating to the latest alpha, beta, or stable release.
## Available Tools
The MCP server provides these tools to AI assistants:
| Tool | Description |
| --------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `list_components` | List all available HeroUI Native components |
| `get_component_docs` | Get complete component documentation including anatomy, props, examples, and usage patterns for one or more components |
| `get_theme_variables` | Access theme variables for colors, typography, spacing with light/dark mode support |
| `get_docs` | Browse the full HeroUI Native documentation including guides and principles (use path `/docs/native/getting-started/quick-start` for installation instructions) |
## Troubleshooting
**Requirements:** Node.js 22 or higher. The package will be automatically downloaded when using `npx`.
**Need help?** [GitHub Issues](https://github.com/heroui-inc/heroui-mcp/issues) | [Discord Community](https://discord.gg/heroui)
## Links
* [npm Package](https://www.npmjs.com/package/@heroui/native-mcp)
* [GitHub Repository](https://github.com/heroui-inc/heroui-mcp)
* [Contributing Guide](https://github.com/heroui-inc/heroui-mcp/blob/main/CONTRIBUTING.md)
# ButtonGroup
**Category**: react
**URL**: https://v3.heroui.com/docs/react/components/button-group
**Source**: https://raw.githubusercontent.com/heroui-inc/heroui/refs/heads/v3/apps/docs/content/docs/react/components/(buttons)/button-group.mdx
> Group related buttons together with consistent styling and spacing
## Import
```tsx
import { ButtonGroup, Button } from '@heroui/react';
```
### Usage
```tsx
import {
ChevronDown,
ChevronLeft,
ChevronRight,
CodeFork,
Ellipsis,
Picture,
Pin,
QrCode,
Star,
TextAlignCenter,
TextAlignJustify,
TextAlignLeft,
TextAlignRight,
ThumbsDown,
ThumbsUp,
Video,
} from "@gravity-ui/icons";
import {Button, ButtonGroup, Chip, Description, Dropdown, Label} from "@heroui/react";
export function Basic() {
return (
{/* Single button with dropdown */}
All commits from this branch will be added to the base branch
The 14 commits from this branch will be combined into one commit in the base
branch
The 14 commits from this branch will be rebased and added to the base branch
{/* Individual buttons */}
{/* Previous/Next Button Group */}
{/* Content Selection Button Group */}
{/* Text Alignment Button Group */}
{/* Icon-Only Alignment Button Group */}
);
}
```
### Anatomy
Import the ButtonGroup component and access all parts using dot notation.
```tsx
import { ButtonGroup, Button } from '@heroui/react';
export default () => (
);
```
> **ButtonGroup** wraps multiple Button components together, applying consistent styling, spacing, and automatic border radius handling. It uses React Context to pass `size`, `variant`, and `isDisabled` props to all child buttons.
### Variants
```tsx
import {Button, ButtonGroup} from "@heroui/react";
export function Variants() {
return (
Primary
Secondary
Tertiary
Outline
Ghost
Danger
);
}
```
### Sizes
```tsx
import {Button, ButtonGroup} from "@heroui/react";
export function Sizes() {
return (
Small
Medium (default)
Large
);
}
```
### Orientation
Use the `orientation` prop to arrange buttons horizontally or vertically.
```tsx
import {TextAlignCenter, TextAlignJustify, TextAlignLeft, TextAlignRight} from "@gravity-ui/icons";
import {Button, ButtonGroup} from "@heroui/react";
export function Orientation() {
return (
Horizontal
Vertical
);
}
```
### With Icons
```tsx
import {Globe, Plus, TrashBin} from "@gravity-ui/icons";
import {Button, ButtonGroup} from "@heroui/react";
export function WithIcons() {
return (
With icons
Icon only buttons
);
}
```
### Full Width
```tsx
import {TextAlignCenter, TextAlignLeft, TextAlignRight} from "@gravity-ui/icons";
import {Button, ButtonGroup} from "@heroui/react";
export function FullWidth() {
return (
);
}
```
### Disabled State
```tsx
import {Button, ButtonGroup} from "@heroui/react";
export function Disabled() {
return (
All buttons disabled
Group disabled, but one button overrides
);
}
```
### Without Separator
Simply omit the `` component from your buttons.
```tsx
import {Button, ButtonGroup} from "@heroui/react";
export function WithoutSeparator() {
return (
);
}
```
## Related Components
* **Button**: Allows a user to perform an action
* **Dropdown**: Context menu with actions and options
* **Chip**: Compact elements for tags and filters
## Styling
### Passing Tailwind CSS classes
```tsx
import { ButtonGroup, Button } from '@heroui/react';
function CustomButtonGroup() {
return (
);
}
```
### Customizing the component classes
To customize the ButtonGroup component classes, you can use the `@layer components` directive.
[Learn more](https://tailwindcss.com/docs/adding-custom-styles#adding-component-classes).
```css
@layer components {
.button-group {
@apply gap-2 rounded-lg;
}
.button-group__separator {
@apply opacity-25;
}
}
```
HeroUI follows the [BEM](https://getbem.com/) methodology to ensure component variants and states are reusable and easy to customize.
### CSS Classes
The ButtonGroup component uses these CSS classes ([View source styles](https://github.com/heroui-inc/heroui/blob/v3/packages/styles/components/button-group.css)):
#### Base Classes
* `.button-group` - Base button group container
* `.button-group--full-width` - Full width modifier
* `.button-group__separator` - Separator element between buttons
The ButtonGroup component automatically applies border radius to buttons:
* First button gets rounded left/start edge
* Last button gets rounded right/end edge
* Middle buttons have no border radius
* Single button gets full border radius on all edges
Add `` inside each Button (except the first) to show dividers between buttons.
## API Reference
### ButtonGroup Props
| Prop | Type | Default | Description |
| ------------- | --------------------------------------------------------------- | -------------- | --------------------------------------------------------------------------------------- |
| `variant` | `'primary' \| 'secondary' \| 'tertiary' \| 'ghost' \| 'danger'` | - | Visual style variant applied to all buttons in the group |
| `size` | `'sm' \| 'md' \| 'lg'` | - | Size applied to all buttons in the group |
| `orientation` | `'horizontal' \| 'vertical'` | `'horizontal'` | The orientation of the button group |
| `fullWidth` | `boolean` | `false` | Whether the button group should take full width of its container |
| `isDisabled` | `boolean` | `false` | Whether all buttons in the group are disabled (can be overridden on individual buttons) |
| `className` | `string` | - | Additional CSS classes |
| `children` | `React.ReactNode` | - | Button components to group together |
### ButtonGroup.Separator Props
| Prop | Type | Default | Description |
| ----------- | -------- | ------- | ---------------------- |
| `className` | `string` | - | Additional CSS classes |
### Notes
* ButtonGroup uses React Context to pass `size`, `variant`, and `isDisabled` props to all child Button components
* **Only direct child buttons receive the ButtonGroup props** - Buttons nested inside other components (like Modal, Dropdown, etc.) will not inherit the group's props even if they are descendants of the ButtonGroup
* Individual Button components can override the group's `isDisabled` prop by setting `isDisabled={false}`
* The component automatically handles border radius between buttons
* Add `` inside each Button (except the first) to show dividers between buttons
* Buttons in a group have their active/pressed scale transform removed for a more cohesive appearance
# Button
**Category**: react
**URL**: https://v3.heroui.com/docs/react/components/button
**Source**: https://raw.githubusercontent.com/heroui-inc/heroui/refs/heads/v3/apps/docs/content/docs/react/components/(buttons)/button.mdx
> A clickable button component with multiple variants and states
## Import
```tsx
import { Button } from '@heroui/react';
```
### Usage
```tsx
"use client";
import {Button} from "@heroui/react";
export function Basic() {
return ;
}
```
### Variants
```tsx
import {Button} from "@heroui/react";
export function Variants() {
return (
);
}
```
### With Icons
```tsx
import {Envelope, Globe, Plus, TrashBin} from "@gravity-ui/icons";
import {Button} from "@heroui/react";
export function WithIcons() {
return (
);
}
```
### Icon Only
```tsx
import {Ellipsis, Gear, TrashBin} from "@gravity-ui/icons";
import {Button} from "@heroui/react";
export function IconOnly() {
return (
);
}
```
### Loading
```tsx
"use client";
import {Button, Spinner} from "@heroui/react";
import React from "react";
export function Loading() {
return (
);
}
```
### Loading State
```tsx
"use client";
import {Paperclip} from "@gravity-ui/icons";
import {Button, Spinner} from "@heroui/react";
import React, {useState} from "react";
export function LoadingState() {
const [isLoading, setLoading] = useState(false);
const handlePress = () => {
setLoading(true);
setTimeout(() => setLoading(false), 2000);
};
return (
);
}
```
### Sizes
```tsx
import {Button} from "@heroui/react";
export function Sizes() {
return (
);
}
```
### Full Width
```tsx
import {Plus} from "@gravity-ui/icons";
import {Button} from "@heroui/react";
export function FullWidth() {
return (
);
}
```
### Disabled State
```tsx
import {Button} from "@heroui/react";
export function Disabled() {
return (
);
}
```
### Social Buttons
```tsx
import {Button} from "@heroui/react";
import {Icon} from "@iconify/react";
export function Social() {
return (
);
}
```
### Custom Render Function
```tsx
"use client";
import {Button} from "@heroui/react";
export function CustomRenderFunction() {
return (
);
}
```
## Related Components
* **Popover**: Displays content in context with a trigger
* **Tooltip**: Contextual information on hover or focus
* **Form**: Form validation and submission handling
## Styling
### Passing Tailwind CSS classes
```tsx
import { Button } from '@heroui/react';
function CustomButton() {
return (
Purple Button
);
}
```
### Customizing the component classes
To customize the Button component classes, you can use the `@layer components` directive.
[Learn more](https://tailwindcss.com/docs/adding-custom-styles#adding-component-classes).
```css
@layer components {
.button {
@apply bg-purple-500 text-white hover:bg-purple-600;
}
.button--icon-only {
@apply rounded-lg bg-blue-500;
}
}
```
HeroUI follows the [BEM](https://getbem.com/) methodology to ensure component variants and states are reusable and easy to customize.
### Adding custom variants
You can extend HeroUI components by wrapping them and adding your own custom variants.
```tsx
import type {ButtonProps} from "@heroui/react";
import type {VariantProps} from "tailwind-variants";
import {Button, buttonVariants} from "@heroui/react";
import {tv} from "tailwind-variants";
const myButtonVariants = tv({
base: "text-md font-semibold shadow-md text-shadow-lg data-[pending=true]:opacity-40",
defaultVariants: {
radius: "full",
variant: "primary",
},
extend: buttonVariants,
variants: {
radius: {
full: "rounded-full",
lg: "rounded-lg",
md: "rounded-md",
sm: "rounded-sm",
},
size: {
lg: "h-12 px-8",
md: "h-11 px-6",
sm: "h-10 px-4",
xl: "h-13 px-10",
},
variant: {
primary: "text-white dark:bg-white/10 dark:text-white dark:hover:bg-white/15",
},
},
});
type MyButtonVariants = VariantProps;
export type MyButtonProps = Omit &
MyButtonVariants & {className?: string};
function CustomButton({className, radius, variant, ...props}: MyButtonProps) {
return ;
}
export function CustomVariants() {
return Custom Button;
}
```
### Adding Ripple Effect
The Button component supports ripple effects through composition, allowing you to nest ripple components as children. This example uses [m3-ripple](https://github.com/saltyaom/m3-ripple).
```tsx
"use client";
import {Button} from "@heroui/react";
import {Ripple} from "m3-ripple";
import "m3-ripple/ripple.css";
export function RippleEffect() {
return (
Click me
);
}
```
### CSS Classes
The Button component uses these CSS classes ([View source styles](https://github.com/heroui-inc/heroui/blob/v3/packages/styles/components/button.css)):
#### Base & Size Classes
* `.button` - Base button styles
* `.button--sm` - Small size variant
* `.button--md` - Medium size variant
* `.button--lg` - Large size variant
#### Variant Classes
* `.button--primary`
* `.button--secondary`
* `.button--tertiary`
* `.button--outline`
* `.button--ghost`
* `.button--danger`
#### Modifier Classes
* `.button--icon-only`
* `.button--icon-only.button--sm`
* `.button--icon-only.button--lg`
### Interactive States
The button supports both CSS pseudo-classes and data attributes for flexibility:
* **Hover**: `:hover` or `[data-hovered="true"]`
* **Active/Pressed**: `:active` or `[data-pressed="true"]` (includes scale transform)
* **Focus**: `:focus-visible` or `[data-focus-visible="true"]` (shows focus ring)
* **Disabled**: `:disabled` or `[aria-disabled="true"]` (reduced opacity, no pointer events)
* **Pending**: `[data-pending]` (no pointer events during loading)
## API Reference
### Button Props
| Prop | Type | Default | Description |
| ------------ | ---------------------------------------------------------------------------- | ----------- | ---------------------------------------------------------------- |
| `variant` | `'primary' \| 'secondary' \| 'tertiary' \| 'outline' \| 'ghost' \| 'danger'` | `'primary'` | Visual style variant |
| `size` | `'sm' \| 'md' \| 'lg'` | `'md'` | Size of the button |
| `fullWidth` | `boolean` | `false` | Whether the button should take full width of its container |
| `isDisabled` | `boolean` | `false` | Whether the button is disabled |
| `isPending` | `boolean` | `false` | Whether the button is in a loading state |
| `isIconOnly` | `boolean` | `false` | Whether the button contains only an icon |
| `onPress` | `(e: PressEvent) => void` | - | Handler called when the button is pressed |
| `children` | `React.ReactNode \| (values: ButtonRenderProps) => React.ReactNode` | - | Button content or render prop |
| `render` | `DOMRenderFunction` | - | Overrides the default DOM element with a custom render function. |
### ButtonRenderProps
When using the render prop pattern, these values are provided:
| Prop | Type | Description |
| ---------------- | --------- | ---------------------------------------------- |
| `isPending` | `boolean` | Whether the button is in a loading state |
| `isPressed` | `boolean` | Whether the button is currently pressed |
| `isHovered` | `boolean` | Whether the button is hovered |
| `isFocused` | `boolean` | Whether the button is focused |
| `isFocusVisible` | `boolean` | Whether the button should show focus indicator |
| `isDisabled` | `boolean` | Whether the button is disabled |
# CloseButton
**Category**: react
**URL**: https://v3.heroui.com/docs/react/components/close-button
**Source**: https://raw.githubusercontent.com/heroui-inc/heroui/refs/heads/v3/apps/docs/content/docs/react/components/(buttons)/close-button.mdx
> Button component for closing dialogs, modals, or dismissing content
## Import
```tsx
import { CloseButton } from "@heroui/react";
```
### Usage
```tsx
import {CloseButton} from "@heroui/react";
export function Default() {
return ;
}
```
### With Custom Icon
```tsx
import {CircleXmark, Xmark} from "@gravity-ui/icons";
import {CloseButton} from "@heroui/react";
export function WithCustomIcon() {
return (
Custom Icon
Alternative Icon
);
}
```
### Interactive
```tsx
"use client";
import {CloseButton} from "@heroui/react";
import {useState} from "react";
export function Interactive() {
const [count, setCount] = useState(0);
return (
setCount(count + 1)}
/>
Clicked: {count} times
);
}
```
## Related Components
* **Alert**: Display important messages and notifications
* **AlertDialog**: Critical confirmations requiring user attention
* **Chip**: Compact elements for tags and filters
## Styling
### Passing Tailwind CSS classes
```tsx
import {CloseButton} from "@heroui/react";
function CustomCloseButton() {
return Close;
}
```
### Customizing the component classes
To customize the CloseButton component classes, you can use the `@layer components` directive.
[Learn more](https://tailwindcss.com/docs/adding-custom-styles#adding-component-classes).
```css
@layer components {
.close-button {
@apply bg-red-100 text-red-800 hover:bg-red-200;
}
.close-button--custom {
@apply rounded-full border-2 border-red-300;
}
}
```
HeroUI follows the [BEM](https://getbem.com/) methodology to ensure component variants and states are reusable and easy to customize.
### CSS Classes
The CloseButton component uses these CSS classes ([View source styles](https://github.com/heroui-inc/heroui/blob/v3/packages/styles/components/close-button.css)):
#### Base Classes
* `.close-button` - Base component styles
#### Variant Classes
* `.close-button--default` - Default variant
### Interactive States
The component supports both CSS pseudo-classes and data attributes for flexibility:
* **Hover**: `:hover` or `[data-hovered="true"]`
* **Active/Pressed**: `:active` or `[data-pressed="true"]`
* **Focus**: `:focus-visible` or `[data-focus-visible="true"]`
* **Disabled**: `:disabled` or `[aria-disabled="true"]`
## API Reference
### CloseButton Props
| Prop | Type | Default | Description |
| ------------ | ----------------------- | --------------- | ------------------------------------------- |
| `variant` | `"default"` | `"default"` | Visual variant of the button |
| `children` | `ReactNode \| function` | `` | Content to display (defaults to close icon) |
| `onPress` | `() => void` | - | Handler called when the button is pressed |
| `isDisabled` | `boolean` | `false` | Whether the button is disabled |
### React Aria Button Props
CloseButton extends all React Aria Button props. Common props include:
| Prop | Type | Description |
| ------------------ | -------- | --------------------------------------- |
| `aria-label` | `string` | Accessible label for screen readers |
| `aria-labelledby` | `string` | ID of element that labels the button |
| `aria-describedby` | `string` | ID of element that describes the button |
### RenderProps
When using the render prop pattern, these values are provided:
| Prop | Type | Description |
| ------------ | --------- | ------------------------------ |
| `isHovered` | `boolean` | Whether the button is hovered |
| `isPressed` | `boolean` | Whether the button is pressed |
| `isFocused` | `boolean` | Whether the button is focused |
| `isDisabled` | `boolean` | Whether the button is disabled |
# ToggleButtonGroup
**Category**: react
**URL**: https://v3.heroui.com/docs/react/components/toggle-button-group
**Source**: https://raw.githubusercontent.com/heroui-inc/heroui/refs/heads/v3/apps/docs/content/docs/react/components/(buttons)/toggle-button-group.mdx
> Groups multiple ToggleButtons into a unified control, allowing users to select one or multiple options.
## Import
```tsx
import { ToggleButtonGroup, ToggleButton } from '@heroui/react';
```
### Usage
```tsx
import {Bold, Italic, Strikethrough, Underline} from "@gravity-ui/icons";
import {ToggleButton, ToggleButtonGroup} from "@heroui/react";
export function Basic() {
return (
);
}
```
### Anatomy
Import the ToggleButtonGroup component and access all parts using dot notation.
```tsx
import { ToggleButtonGroup, ToggleButton } from '@heroui/react';
export default () => (
First
Second
Third
);
```
### Sizes
```tsx
import {Bold, Italic, Strikethrough, Underline} from "@gravity-ui/icons";
import {ToggleButton, ToggleButtonGroup} from "@heroui/react";
export function Sizes() {
return (
Small
Medium (default)
Large
);
}
```
### Orientation
```tsx
import {Bold, Italic, Underline} from "@gravity-ui/icons";
import {ToggleButton, ToggleButtonGroup} from "@heroui/react";
export function Orientation() {
return (
Horizontal
Vertical
);
}
```
### Detached
Use `isDetached` to separate buttons with gaps instead of connecting them.
```tsx
import {Bold, Italic, Strikethrough, Underline} from "@gravity-ui/icons";
import {ToggleButton, ToggleButtonGroup} from "@heroui/react";
export function Attached() {
return (
Attached (default)
Detached
);
}
```
### Full Width
```tsx
import {
Bold,
Italic,
Strikethrough,
TextAlignCenter,
TextAlignLeft,
TextAlignRight,
Underline,
} from "@gravity-ui/icons";
import {ToggleButton, ToggleButtonGroup} from "@heroui/react";
export function FullWidth() {
return (
Left
Center
Right
);
}
```
### Selection Mode
Use `selectionMode="single"` for mutually exclusive choices or `selectionMode="multiple"` for independent toggles.
```tsx
import {
Bold,
Italic,
Strikethrough,
TextAlignCenter,
TextAlignLeft,
TextAlignRight,
Underline,
} from "@gravity-ui/icons";
import {ToggleButton, ToggleButtonGroup} from "@heroui/react";
export function SelectionMode() {
return (
Single selection
Left
Center
Right
Multiple selection
);
}
```
### Controlled
```tsx
"use client";
import type {Key} from "@heroui/react";
import {Bold, Italic, Strikethrough, Underline} from "@gravity-ui/icons";
import {ToggleButton, ToggleButtonGroup} from "@heroui/react";
import {useState} from "react";
export function Controlled() {
const [selectedKeys, setSelectedKeys] = useState(new Set(["bold"]));
return (
);
}
```
### Anatomy
Import the ListBox component and access all parts using dot notation.
```tsx
import { ListBox, Label, Description, Header } from '@heroui/react';
export default () => (
)
```
### With Sections
```tsx
"use client";
import {Pencil, SquarePlus, TrashBin} from "@gravity-ui/icons";
import {Description, Header, Kbd, Label, ListBox, Separator, Surface} from "@heroui/react";
export function WithSections() {
return (
alert(`Selected item: ${key}`)}
>
Actions
Create a new file
N
Make changes
EDanger zone
Move to trash
D
);
}
```
### Multi Select
```tsx
import {Avatar, Description, Label, ListBox, Surface} from "@heroui/react";
export function MultiSelect() {
return (
B
bob@heroui.com
F
fred@heroui.com
M
martha@heroui.com
);
}
```
### With Disabled Items
```tsx
"use client";
import {Pencil, SquarePlus, TrashBin} from "@gravity-ui/icons";
import {Description, Header, Kbd, Label, ListBox, Separator, Surface} from "@heroui/react";
export function WithDisabledItems() {
return (
alert(`Selected item: ${key}`)}
>
Actions
Create a new file
N
Make changes
EDanger zone
Move to trash
D
);
}
```
### Custom Check Icon
```tsx
"use client";
import {Check} from "@gravity-ui/icons";
import {Avatar, Description, Label, ListBox, Surface} from "@heroui/react";
export function CustomCheckIcon() {
return (
B
bob@heroui.com
{({isSelected}) => (isSelected ? : null)}
F
fred@heroui.com
{({isSelected}) => (isSelected ? : null)}
M
martha@heroui.com
{({isSelected}) => (isSelected ? : null)}
);
}
```
### Controlled
```tsx
"use client";
import type {Selection} from "@heroui/react";
import {Check} from "@gravity-ui/icons";
import {Avatar, Description, Label, ListBox, Surface} from "@heroui/react";
import {useState} from "react";
export function Controlled() {
const [selected, setSelected] = useState(new Set(["1"]));
const selectedItems = Array.from(selected);
return (
list.setSelectedKeys(keys)}
>
No team members}
>
{(user) => (
{user.fallback}
{user.name}
)}
Select team members for your project
{list.selectedKeys !== "all" && Array.from(list.selectedKeys).length > 0 && (
Selected:
{Array.from(list.selectedKeys).map((key) => {
const user = list.getItem(key);
if (!user) return null;
return (
{user.fallback}{user.name}
);
})}
)}
);
}
```
### Custom Render Function
```tsx
"use client";
import {PlanetEarth, Rocket, ShoppingBag, SquareArticle} from "@gravity-ui/icons";
import {Tag, TagGroup} from "@heroui/react";
export function CustomRenderFunction() {
return (
}
selectionMode="single"
>
News
Travel
Gaming
Shopping
);
}
```
## Related Components
* **Label**: Accessible label for form controls
* **Description**: Helper text for form fields
* **ErrorMessage**: Displays validation error messages for components with validation support
## Styling
### Passing Tailwind CSS classes
```tsx
import { TagGroup, Tag, Label } from '@heroui/react';
function CustomTagGroup() {
return (
Custom Styled
);
}
```
### Customizing the component classes
To customize the TagGroup component classes, you can use the `@layer components` directive.
[Learn more](https://tailwindcss.com/docs/adding-custom-styles#adding-component-classes).
```css
@layer components {
.tag-group {
@apply flex flex-col gap-2;
}
.tag-group__list {
@apply flex flex-wrap gap-2;
}
.tag {
@apply rounded-full px-3 py-1;
}
.tag__remove-button {
@apply ml-1;
}
}
```
HeroUI follows the [BEM](https://getbem.com/) methodology to ensure component variants and states are reusable and easy to customize.
### CSS Classes
The TagGroup component uses these CSS classes ([View source styles](https://github.com/heroui-inc/heroui/blob/v3/packages/styles/components/tag-group.css) and [tag.css](https://github.com/heroui-inc/heroui/blob/v3/packages/styles/components/tag.css)):
#### Base Classes
* `.tag-group` - Base tag group container
* `.tag-group__list` - Container for the list of tags
* `.tag` - Base tag styles
* `.tag__remove-button` - Remove button trigger
#### Slot Classes
* `.tag-group [slot="description"]` - Description slot styles
* `.tag-group [slot="errorMessage"]` - ErrorMessage slot styles
#### Size Classes
* `.tag--sm` - Small size tag
* `.tag--md` - Medium size tag (default)
* `.tag--lg` - Large size tag
#### Variant Classes
* `.tag--default` - Default variant
* `.tag--surface` - Surface variant with surface background
#### State Classes
* `.tag[data-selected="true"]` - Selected tag state
* `.tag[data-disabled="true"]` - Disabled tag state
* `.tag[data-hovered="true"]` - Hovered tag state
* `.tag[data-pressed="true"]` - Pressed tag state
* `.tag[data-focus-visible="true"]` - Focused tag state (keyboard focus)
### Interactive States
The component supports both CSS pseudo-classes and data attributes for flexibility:
* **Hover**: `:hover` or `[data-hovered="true"]` on tag
* **Focus**: `:focus-visible` or `[data-focus-visible="true"]` on tag
* **Pressed**: `:active` or `[data-pressed="true"]` on tag
* **Selected**: `[data-selected="true"]` or `[aria-selected="true"]` on tag
* **Disabled**: `:disabled` or `[data-disabled="true"]` on tag
## API Reference
### TagGroup Props
| Prop | Type | Default | Description |
| --------------------- | ----------------------------------------------------------------- | ----------- | ---------------------------------------------------------------- |
| `selectionMode` | `"none" \| "single" \| "multiple"` | `"none"` | The type of selection that is allowed |
| `selectedKeys` | `Selection` | - | The currently selected keys (controlled) |
| `defaultSelectedKeys` | `Selection` | - | The initial selected keys (uncontrolled) |
| `onSelectionChange` | `(keys: Selection) => void` | - | Handler called when the selection changes |
| `disabledKeys` | `Iterable` | - | Keys of disabled tags |
| `isDisabled` | `boolean` | - | Whether the tag group is disabled |
| `onRemove` | `(keys: Set) => void` | - | Handler called when tags are removed |
| `size` | `"sm" \| "md" \| "lg"` | `"md"` | Size of the tags in the group |
| `variant` | `"default" \| "surface"` | `"default"` | Visual variant of the tags |
| `className` | `string` | - | Additional CSS classes |
| `children` | `ReactNode \| RenderFunction` | - | TagGroup content or render function |
| `render` | `DOMRenderFunction` | - | Overrides the default DOM element with a custom render function. |
### TagGroup.List Props
| Prop | Type | Default | Description |
| ------------------ | -------------------------------------------------------------------------- | ------- | ---------------------------------------------------------------- |
| `items` | `Iterable` | - | The items to display in the tag list |
| `renderEmptyState` | `() => ReactNode` | - | Function to render when the list is empty |
| `className` | `string` | - | Additional CSS classes |
| `children` | `ReactNode \| RenderFunction` | - | TagList content or render function |
| `render` | `DOMRenderFunction` | - | Overrides the default DOM element with a custom render function. |
### Tag Props
| Prop | Type | Default | Description |
| ------------ | ---------------------------------------------------------------------- | ------- | -------------------------------------------------------------------- |
| `id` | `Key` | - | The unique identifier for the tag |
| `textValue` | `string` | - | A string representation of the tag's content, used for accessibility |
| `isDisabled` | `boolean` | - | Whether the tag is disabled |
| `className` | `string` | - | Additional CSS classes |
| `children` | `ReactNode \| RenderFunction` | - | Tag content or render function |
| `render` | `DOMRenderFunction` | - | Overrides the default DOM element with a custom render function. |
**Note**: `size`, `variant` are inherited from the parent `TagGroup` component and cannot be set directly on individual `Tag` components.
### Tag.RemoveButton Props
| Prop | Type | Default | Description |
| ----------- | ----------- | ------- | ----------------------------------------------------- |
| `className` | `string` | - | Additional CSS classes |
| `children` | `ReactNode` | - | Custom remove button content (defaults to close icon) |
**Note**: The `Tag.RemoveButton` component supports customization similar to `SearchField.ClearButton`. When `onRemove` is provided to `TagGroup`:
* **Auto-rendering**: If no custom `Tag.RemoveButton` is included in the `Tag` children, a default remove button is automatically rendered.
* **Custom button**: If a custom `Tag.RemoveButton` is provided as a child of `Tag`, it will be used instead of the auto-rendered button.
* **Custom icon**: You can pass custom content (like icons) to `Tag.RemoveButton` children to customize the appearance.
**Example - Auto-rendered (default)**:
```tsx
News
{/* Remove button is automatically rendered */}
```
**Example - Custom RemoveButton with icon**:
```tsx
News
```
**Example - Custom RemoveButton in render props**:
```tsx
{(renderProps) => (
<>
News
{!!renderProps.allowsRemoving && (
)}
>
)}
```
### RenderProps
When using render functions with TagGroup.List, these values are provided:
| Prop | Type | Description |
| ---------------- | --------- | ---------------------------------- |
| `isSelected` | `boolean` | Whether the tag is selected |
| `isDisabled` | `boolean` | Whether the tag is disabled |
| `isHovered` | `boolean` | Whether the tag is hovered |
| `isPressed` | `boolean` | Whether the tag is pressed |
| `isFocused` | `boolean` | Whether the tag is focused |
| `isFocusVisible` | `boolean` | Whether the tag has keyboard focus |
# ColorArea
**Category**: react
**URL**: https://v3.heroui.com/docs/react/components/color-area
**Source**: https://raw.githubusercontent.com/heroui-inc/heroui/refs/heads/v3/apps/docs/content/docs/react/components/(colors)/color-area.mdx
> A 2D color picker that allows users to select colors from a gradient area
## Import
```tsx
import { ColorArea } from '@heroui/react';
```
### Usage
```tsx
import {ColorArea} from "@heroui/react";
export function ColorAreaBasic() {
return (
);
}
```
### Anatomy
```tsx
import { ColorArea } from '@heroui/react';
export default () => (
);
```
### With Dots
```tsx
import {ColorArea} from "@heroui/react";
export function ColorAreaWithDots() {
return (
);
}
```
### Controlled
```tsx
"use client";
import type {Color} from "@heroui/react";
import {ColorArea, ColorSwatch, parseColor} from "@heroui/react";
import {useState} from "react";
export function ColorAreaControlled() {
const [color, setColor] = useState(parseColor("#9B80FF"));
return (
Current color:{" "}
{color ? color.toString("hex") : "(empty)"}
);
}
```
### Color Space & Channels
Use `colorSpace` to set the color space (RGB, HSL, HSB) and `xChannel`/`yChannel` props to customize which color channels are displayed on each axis.
```tsx
"use client";
import type {ColorSpace, Key} from "@heroui/react";
import {ColorArea, Label, ListBox, Select, parseColor} from "@heroui/react";
import {useState} from "react";
type ColorChannel = "hue" | "saturation" | "brightness" | "lightness" | "red" | "green" | "blue";
interface ChannelOption {
id: ColorChannel;
name: string;
}
const colorSpaces: Array<{id: ColorSpace; name: string}> = [
{id: "rgb", name: "RGB"},
{id: "hsl", name: "HSL"},
{id: "hsb", name: "HSB"},
];
const channelsBySpace: Record = {
hsb: [
{id: "hue", name: "Hue"},
{id: "saturation", name: "Saturation"},
{id: "brightness", name: "Brightness"},
],
hsl: [
{id: "hue", name: "Hue"},
{id: "saturation", name: "Saturation"},
{id: "lightness", name: "Lightness"},
],
rgb: [
{id: "red", name: "Red"},
{id: "green", name: "Green"},
{id: "blue", name: "Blue"},
],
};
export function ColorAreaSpaceAndChannels() {
const [colorSpace, setColorSpace] = useState("hsb");
const [color, setColor] = useState(() => parseColor("hsb(219, 58%, 93%)"));
const channels = channelsBySpace[colorSpace];
const defaultX = colorSpace === "rgb" ? "blue" : "saturation";
const defaultY =
colorSpace === "rgb" ? "green" : colorSpace === "hsl" ? "lightness" : "brightness";
const [xChannel, setXChannel] = useState(defaultX);
const [yChannel, setYChannel] = useState(defaultY);
const handleColorSpaceChange = (newSpace: Key | null) => {
if (!newSpace) return;
const space = newSpace as ColorSpace;
setColorSpace(space);
// Reset channels to appropriate defaults for the new color space
if (space === "rgb") {
setXChannel("blue");
setYChannel("green");
} else if (space === "hsl") {
setXChannel("saturation");
setYChannel("lightness");
} else {
setXChannel("saturation");
setYChannel("brightness");
}
};
// Filter out the other channel from options (can't have same channel on both axes)
const xChannelOptions = channels.filter((c) => c.id !== yChannel);
const yChannelOptions = channels.filter((c) => c.id !== xChannel);
return (
{/* Controls */}
{/* Color Space Select */}
{/* X Channel Select */}
{/* Y Channel Select */}
{/* Color Area */}
{/* Color Value Display */}
{color.toString(colorSpace)}
);
}
```
### Disabled
```tsx
import {ColorArea} from "@heroui/react";
export function ColorAreaDisabled() {
return (
);
}
```
### Custom Render Function
```tsx
"use client";
import {ColorArea} from "@heroui/react";
export function CustomRenderFunction() {
return (
}
>
} />
);
}
```
## Related Components
* **ColorSwatch**: Visual preview of a color value
* **ColorSwatchPicker**: Color swatch selection from a list of colors
* **ColorField**: Input for entering color values with hex format
## Styling
### Passing Tailwind CSS classes
```tsx
import { ColorArea } from '@heroui/react';
function CustomColorArea() {
return (
);
}
```
### Customizing the component classes
To customize the ColorArea component classes, you can use the `@layer components` directive.
[Learn more](https://tailwindcss.com/docs/adding-custom-styles#adding-component-classes).
```css
@layer components {
.color-area {
@apply rounded-3xl;
}
.color-area__thumb {
@apply size-5 border-4;
}
}
```
HeroUI follows the [BEM](https://getbem.com/) methodology to ensure component variants and states are reusable and easy to customize.
### CSS Classes
The ColorArea component uses these CSS classes ([View source styles](https://github.com/heroui-inc/heroui/blob/v3/packages/styles/components/color-area.css)):
#### Base Classes
* `.color-area` - Base styles with gradient background and inner shadow
* `.color-area--show-dots` - Adds dot grid overlay for precision picking
#### Element Classes
* `.color-area__thumb` - Draggable thumb indicator
### Interactive States
The component supports both CSS pseudo-classes and data attributes for flexibility:
* **Disabled**: `[data-disabled="true"]`
* **Focus**: `[data-focus-visible="true"]`
* **Dragging**: `[data-dragging="true"]` (thumb only)
## API Reference
### ColorArea Props
Inherits from [React Aria ColorArea](https://react-spectrum.adobe.com/react-aria/ColorArea.html).
| Prop | Type | Default | Description |
| -------------- | ---------------------------------------------------------------------------- | -------------- | ---------------------------------------------------------------- |
| `value` | `string \| Color` | - | The current color value (controlled) |
| `defaultValue` | `string \| Color` | - | The default color value (uncontrolled) |
| `onChange` | `(color: Color) => void` | - | Handler called when the color changes while dragging |
| `onChangeEnd` | `(color: Color) => void` | - | Handler called when the user stops dragging |
| `xChannel` | `ColorChannel` | `"saturation"` | Color channel for the horizontal axis |
| `yChannel` | `ColorChannel` | `"brightness"` | Color channel for the vertical axis |
| `colorSpace` | `ColorSpace` | - | The color space for the channels |
| `isDisabled` | `boolean` | `false` | Whether the color area is disabled |
| `showDots` | `boolean` | `false` | Whether to show the dot grid overlay |
| `className` | `string` | - | Additional CSS classes |
| `render` | `DOMRenderFunction` | - | Overrides the default DOM element with a custom render function. |
### ColorArea.Thumb Props
| Prop | Type | Default | Description |
| ----------- | ----------------------------------------------------------------------------- | ------- | ---------------------------------------------------------------- |
| `className` | `string` | - | Additional CSS classes |
| `style` | `CSSProperties \| ((renderProps) => CSSProperties)` | - | Inline styles or render props function |
| `render` | `DOMRenderFunction` | - | Overrides the default DOM element with a custom render function. |
# ColorField
**Category**: react
**URL**: https://v3.heroui.com/docs/react/components/color-field
**Source**: https://raw.githubusercontent.com/heroui-inc/heroui/refs/heads/v3/apps/docs/content/docs/react/components/(colors)/color-field.mdx
> Color input field with labels, descriptions, and validation built on React Aria ColorField
## Import
```tsx
import { ColorField, parseColor } from '@heroui/react';
```
### Usage
```tsx
"use client";
import type {Color} from "@heroui/react";
import {ColorField, ColorSwatch, Label, parseColor} from "@heroui/react";
import {useState} from "react";
export function Basic() {
const [color, setColor] = useState(parseColor("#0485F7"));
return (
);
}
```
### Anatomy
```tsx
import {ColorField, Label, ColorSwatch, Description, FieldError, parseColor} from '@heroui/react';
export default () => (
)
```
> **ColorField** combines label, color input, description, and error into a single accessible component.
### With Description
```tsx
import {ColorField, Description, Label} from "@heroui/react";
export function WithDescription() {
return (
Enter your brand's primary colorUsed for highlights and CTAs
);
}
```
### Required Field
```tsx
import {ColorField, Description, Label} from "@heroui/react";
export function Required() {
return (
Required field
);
}
```
### Validation
Use `isInvalid` together with `FieldError` to surface validation messages.
```tsx
import {ColorField, FieldError, Label} from "@heroui/react";
export function Invalid() {
return (
Please enter a valid hex colorInvalid color format. Use hex (e.g., #FF5733)
);
}
```
### Channel Editing
ColorField supports editing individual color channels (hue, saturation, lightness, red, green, blue, alpha) by setting the `colorSpace` and `channel` props.
```tsx
"use client";
import type {Color} from "@heroui/react";
import {ColorField, ColorSwatch, Label, parseColor} from "@heroui/react";
import {useState} from "react";
export function ChannelEditing() {
const [color, setColor] = useState(parseColor("#7F007F"));
return (
);
}
```
### Controlled
Control the value to synchronize with other components or state management.
```tsx
"use client";
import type {Color} from "@heroui/react";
import {Button, ColorField, ColorSwatch, Description, Label, parseColor} from "@heroui/react";
import {useState} from "react";
export function Controlled() {
const [value, setValue] = useState(parseColor("#0485F7"));
return (
Current value: {value ? value.toString("hex") : "(empty)"}
setValue(parseColor("#EF4444"))}>
Set Red
setValue(parseColor("#10B981"))}>
Set Green
setValue(null)}>
Clear
);
}
```
### Disabled State
```tsx
"use client";
import {ColorField, Description, Label} from "@heroui/react";
export function Disabled() {
return (
This color field is disabledThis color field is disabled
);
}
```
### Full Width
```tsx
import {ColorField, Label} from "@heroui/react";
export function FullWidth() {
return (
);
}
```
### Variants
The ColorField.Group component supports two visual variants:
* **`primary`** (default) - Standard styling with shadow, suitable for most use cases
* **`secondary`** - Lower emphasis variant without shadow, suitable for use in Surface components
```tsx
import {ColorField, Label} from "@heroui/react";
export function Variants() {
return (
);
}
```
### On Surface
When used inside a [Surface](/docs/components/surface) component, use `variant="secondary"` on ColorField.Group to apply the lower emphasis variant suitable for surface backgrounds.
```tsx
import {ColorField, Description, Label, Surface} from "@heroui/react";
export function OnSurface() {
return (
Select your theme color
);
}
```
### Form Example
Complete form example with validation and submission handling.
```tsx
"use client";
import type {Color} from "@heroui/react";
import {Button, ColorField, ColorSwatch, Description, Form, Label} from "@heroui/react";
import {useState} from "react";
export function FormExample() {
const [value, setValue] = useState(null);
const [isSubmitting, setIsSubmitting] = useState(false);
const handleSubmit = (e: React.FormEvent) => {
e.preventDefault();
if (!value) {
return;
}
setIsSubmitting(true);
// Simulate API call
setTimeout(() => {
console.log("Color submitted:", {color: value.toString("hex")});
setValue(null);
setIsSubmitting(false);
}, 1500);
};
return (
);
}
```
### Custom Render Function
```tsx
"use client";
import type {Color} from "@heroui/react";
import {ColorField, ColorSwatch, Label, parseColor} from "@heroui/react";
import {useState} from "react";
export function CustomRenderFunction() {
const [color, setColor] = useState(parseColor("#0485F7"));
return (
}
value={color}
onChange={setColor}
>
}>
);
}
```
## Related Components
* **ColorSwatch**: Visual preview of a color value
* **ColorSwatchPicker**: Color swatch selection from a list of colors
* **ColorPicker**: Composable color picker with popover
## Styling
### Passing Tailwind CSS classes
```tsx
import {ColorField, Label, ColorSwatch, Description} from '@heroui/react';
function CustomColorField() {
return (
Select your brand's primary color.
);
}
```
### Customizing the component classes
ColorField has minimal default styling. Override the `.color-field` class to customize the container styling.
```css
@layer components {
.color-field {
@apply flex flex-col gap-1;
&[data-invalid="true"],
&[aria-invalid="true"] {
[data-slot="description"] {
@apply hidden;
}
}
[data-slot="label"] {
@apply w-fit;
}
[data-slot="description"] {
@apply px-1;
}
}
}
```
### CSS Classes
* `.color-field` – Root container with minimal styling (`flex flex-col gap-1`)
> **Note:** Child components ([Label](/docs/components/label), [Description](/docs/components/description), [FieldError](/docs/components/field-error)) have their own CSS classes and styling. See their respective documentation for customization options. ColorField.Group styling is documented below in the API Reference section.
### Interactive States
ColorField automatically manages these data attributes based on its state:
* **Invalid**: `[data-invalid="true"]` or `[aria-invalid="true"]` - Automatically hides the description slot when invalid
* **Required**: `[data-required="true"]` - Applied when `isRequired` is true
* **Disabled**: `[data-disabled="true"]` - Applied when `isDisabled` is true
* **Focus Within**: `[data-focus-within="true"]` - Applied when any child input is focused
## API Reference
### ColorField Props
ColorField inherits all props from React Aria's [ColorField](https://react-aria.adobe.com/ColorField.md) component.
#### Base Props
| Prop | Type | Default | Description |
| ----------- | ------------------------------------------------------------------------------- | ------- | -------------------------------------------------------------------- |
| `children` | `React.ReactNode \| (values: ColorFieldRenderProps) => React.ReactNode` | - | Child components (Label, ColorField.Group, etc.) or render function. |
| `className` | `string \| (values: ColorFieldRenderProps) => string` | - | CSS classes for styling, supports render props. |
| `style` | `React.CSSProperties \| (values: ColorFieldRenderProps) => React.CSSProperties` | - | Inline styles, supports render props. |
| `fullWidth` | `boolean` | `false` | Whether the color field should take full width of its container |
| `id` | `string` | - | The element's unique identifier. |
| `render` | `DOMRenderFunction` | - | Overrides the default DOM element with a custom render function. |
#### Value Props
| Prop | Type | Default | Description |
| -------------- | -------------------------------- | ------- | -------------------------------------- |
| `value` | `Color \| null` | - | Current value (controlled). |
| `defaultValue` | `Color \| null` | - | Default value (uncontrolled). |
| `onChange` | `(color: Color \| null) => void` | - | Handler called when the value changes. |
#### Channel Props
| Prop | Type | Default | Description |
| ------------ | -------------- | ------- | ---------------------------------------------------------------------------- |
| `colorSpace` | `ColorSpace` | - | The color space that the color field operates in when `channel` is provided. |
| `channel` | `ColorChannel` | - | The color channel to edit. If not provided, edits hex value. |
#### Validation Props
| Prop | Type | Default | Description |
| -------------------- | ---------------------------------------------------------------- | ---------- | -------------------------------------------------------------- |
| `isRequired` | `boolean` | `false` | Whether user input is required before form submission. |
| `isInvalid` | `boolean` | - | Whether the value is invalid. |
| `validate` | `(value: Color) => ValidationError \| true \| null \| undefined` | - | Custom validation function. |
| `validationBehavior` | `'native' \| 'aria'` | `'native'` | Whether to use native HTML form validation or ARIA attributes. |
#### State Props
| Prop | Type | Default | Description |
| ----------------- | --------- | ------- | -------------------------------------------------- |
| `isDisabled` | `boolean` | - | Whether the input is disabled. |
| `isReadOnly` | `boolean` | - | Whether the input can be selected but not changed. |
| `isWheelDisabled` | `boolean` | - | Whether to disable changing the value with scroll. |
#### Form Props
| Prop | Type | Default | Description |
| ----------- | --------- | ------- | ---------------------------------------------------- |
| `name` | `string` | - | Name of the input element, for HTML form submission. |
| `autoFocus` | `boolean` | - | Whether the element should receive focus on render. |
#### Accessibility Props
| Prop | Type | Default | Description |
| ------------------ | -------- | ------- | ----------------------------------------------------- |
| `aria-label` | `string` | - | Accessibility label when no visible label is present. |
| `aria-labelledby` | `string` | - | ID of elements that label this field. |
| `aria-describedby` | `string` | - | ID of elements that describe this field. |
| `aria-details` | `string` | - | ID of elements with additional details. |
### Composition Components
ColorField works with these separate components that should be imported and used directly:
* **Label** - Field label component from `@heroui/react`
* **ColorField.Group** - Color input group component (documented below)
* **ColorField.Input** - Input element within ColorField.Group
* **ColorField.Prefix** / **ColorField.Suffix** - Prefix and suffix slots for the input group
* **ColorSwatch** - Color preview component from `@heroui/react`
* **Description** - Helper text component from `@heroui/react`
* **FieldError** - Validation error message from `@heroui/react`
Each of these components has its own props API. Use them directly within ColorField for composition:
```tsx
import {ColorField, Label, ColorSwatch, Description, FieldError, parseColor} from '@heroui/react';
Select your brand's primary color.Please enter a valid color.
```
### Color Types
ColorField uses `Color` objects from React Aria Components:
```tsx
import {parseColor} from '@heroui/react';
// Parse from hex string
const color = parseColor('#3B82F6');
// Get hex string from color
const hex = color.toString('hex'); // "#3b82f6"
// Get RGB values
const rgb = color.toString('rgb'); // "rgb(59, 130, 246)"
// Use in ColorField
{/* ... */}
```
### ColorFieldRenderProps
When using render props with `className`, `style`, or `children`, these values are available:
| Prop | Type | Description |
| ---------------- | --------- | ----------------------------------------------- |
| `isDisabled` | `boolean` | Whether the field is disabled. |
| `isInvalid` | `boolean` | Whether the field is currently invalid. |
| `isReadOnly` | `boolean` | Whether the field is read-only. |
| `isRequired` | `boolean` | Whether the field is required. |
| `isFocused` | `boolean` | Whether the field is currently focused. |
| `isFocusWithin` | `boolean` | Whether any child element is focused. |
| `isFocusVisible` | `boolean` | Whether focus is visible (keyboard navigation). |
### ColorField.Group Props
ColorField.Group accepts all props from React Aria's `Group` component plus the following:
| Prop | Type | Default | Description |
| ----------- | ------------------------------------------------------------------------ | ----------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
| `className` | `string` | - | Tailwind classes merged with the component styles. |
| `fullWidth` | `boolean` | `false` | Whether the color input group should take full width of its container |
| `variant` | `"primary" \| "secondary"` | `"primary"` | Visual variant of the component. `primary` is the default style with shadow. `secondary` is a lower emphasis variant without shadow, suitable for use in surfaces. |
| `render` | `DOMRenderFunction` | - | Overrides the default DOM element with a custom render function. |
### ColorField.Input Props
ColorField.Input accepts all props from React Aria's `Input` component plus the following:
| Prop | Type | Default | Description |
| ------------- | -------- | ------- | -------------------------------------------------- |
| `className` | `string` | - | Tailwind classes merged with the component styles. |
| `placeholder` | `string` | - | Placeholder text shown when empty. |
### ColorField.Prefix Props
ColorField.Prefix accepts standard HTML `div` attributes:
| Prop | Type | Default | Description |
| ----------- | ----------- | ------- | -------------------------------------------------- |
| `className` | `string` | - | Tailwind classes merged with the component styles. |
| `children` | `ReactNode` | - | Content to display in the prefix slot. |
### ColorField.Suffix Props
ColorField.Suffix accepts standard HTML `div` attributes:
| Prop | Type | Default | Description |
| ----------- | ----------- | ------- | -------------------------------------------------- |
| `className` | `string` | - | Tailwind classes merged with the component styles. |
| `children` | `ReactNode` | - | Content to display in the suffix slot. |
## ColorField.Group Styling
### Customizing the component classes
The base classes power every instance. Override them once with `@layer components`.
```css
@layer components {
.color-input-group {
@apply inline-flex h-9 items-center overflow-hidden rounded-field border bg-field text-sm text-field-foreground shadow-field outline-none;
&:hover,
&[data-hovered="true"] {
@apply bg-field-hover;
}
&[data-focus-within="true"],
&:focus-within {
@apply status-focused-field;
}
&[data-invalid="true"] {
@apply status-invalid-field;
}
&[data-disabled="true"],
&[aria-disabled="true"] {
@apply status-disabled;
}
}
.color-input-group__input {
@apply flex flex-1 items-center rounded-none border-0 bg-transparent px-3 py-2 shadow-none outline-none;
}
.color-input-group__prefix,
.color-input-group__suffix {
@apply shrink-0 text-field-placeholder flex items-center;
}
}
```
### ColorField.Group CSS Classes
* `.color-input-group` – Root container styling
* `.color-input-group__input` – Input wrapper styling
* `.color-input-group__prefix` – Prefix element styling
* `.color-input-group__suffix` – Suffix element styling
### ColorField.Group Interactive States
* **Hover**: `:hover` or `[data-hovered="true"]`
* **Focus Within**: `[data-focus-within="true"]` or `:focus-within`
* **Invalid**: `[data-invalid="true"]` (also syncs with `aria-invalid`)
* **Disabled**: `[data-disabled="true"]` or `[aria-disabled="true"]`
# ColorPicker
**Category**: react
**URL**: https://v3.heroui.com/docs/react/components/color-picker
**Source**: https://raw.githubusercontent.com/heroui-inc/heroui/refs/heads/v3/apps/docs/content/docs/react/components/(colors)/color-picker.mdx
> A composable color picker that synchronizes color value between multiple color components
## Import
```tsx
import {
ColorPicker,
ColorArea,
ColorSlider,
ColorSwatch,
ColorField,
ColorSwatchPicker,
} from '@heroui/react';
```
### Usage
```tsx
import {ColorArea, ColorPicker, ColorSlider, ColorSwatch, Label} from "@heroui/react";
export function Basic() {
return (
);
}
```
### Anatomy
The ColorPicker is a composable component that combines multiple color components:
```tsx
import { ColorPicker, ColorArea, ColorSlider, ColorSwatch, Label } from '@heroui/react';
export default () => (
);
```
### Controlled
```tsx
"use client";
import {
Button,
ColorArea,
ColorField,
ColorPicker,
ColorSlider,
ColorSwatch,
ColorSwatchPicker,
Label,
parseColor,
} from "@heroui/react";
import {Icon} from "@iconify/react";
import {useState} from "react";
export function Controlled() {
const [color, setColor] = useState(parseColor("#325578"));
const colorPresets = [
"#ef4444",
"#f97316",
"#eab308",
"#22c55e",
"#06b6d4",
"#3b82f6",
"#8b5cf6",
"#ec4899",
"#f43f5e",
];
const shuffleColor = () => {
const randomHue = Math.floor(Math.random() * 360);
const randomSaturation = 50 + Math.floor(Math.random() * 50); // 50-100%
const randomLightness = 40 + Math.floor(Math.random() * 30); // 40-70%
setColor(parseColor(`hsl(${randomHue}, ${randomSaturation}%, ${randomLightness}%)`));
};
return (
{colorPresets.map((preset) => (
))}
Selected: {color.toString("hex")}
);
}
```
### With Swatches
```tsx
import {
ColorArea,
ColorPicker,
ColorSlider,
ColorSwatch,
ColorSwatchPicker,
Label,
} from "@heroui/react";
export function WithSwatches() {
const presets = [
"#ef4444",
"#f97316",
"#eab308",
"#22c55e",
"#06b6d4",
"#3b82f6",
"#8b5cf6",
"#ec4899",
"#f43f5e",
];
return (
{presets.map((preset) => (
))}
);
}
```
### With Fields
Use `ColorField` to allow users to edit individual color channel values with a `Select` to switch between color spaces.
```tsx
"use client";
import type {ColorChannel, ColorSpace} from "@heroui/react";
import {
ColorArea,
ColorField,
ColorPicker,
ColorSlider,
ColorSwatch,
Label,
ListBox,
Select,
} from "@heroui/react";
import {useState} from "react";
export function WithFields() {
const [colorSpace, setColorSpace] = useState("hsl");
const colorChannelsByColorSpace: Record = {
hsb: ["hue", "saturation", "brightness"],
hsl: ["hue", "saturation", "lightness"],
rgb: ["red", "green", "blue"],
};
return (
);
}
```
### With Sliders
Use multiple `ColorSlider` components to adjust each channel of a color value.
```tsx
"use client";
import type {ColorChannel, ColorSpace} from "@heroui/react";
import {ColorPicker, ColorSlider, ColorSwatch, Label, ListBox, Select} from "@heroui/react";
import {useState} from "react";
export function WithSliders() {
const [colorSpace, setColorSpace] = useState("hsl");
const colorChannelsByColorSpace: Record = {
hsb: ["hue", "saturation", "brightness", "alpha"],
hsl: ["hue", "saturation", "lightness", "alpha"],
rgb: ["red", "green", "blue", "alpha"],
};
return (
{colorChannelsByColorSpace[colorSpace].map((channel: ColorChannel) => (
// @ts-expect-error - TypeScript can't correlate dynamic colorSpace with channel type
))}
);
}
```
## Related Components
* **ColorArea**: 2D color picker for selecting colors from a gradient area
* **ColorSlider**: Slider for adjusting individual color channel values
* **ColorSwatch**: Visual preview of a color value
## Styling
### Passing Tailwind CSS classes
```tsx
import { ColorPicker, ColorArea, ColorSlider, ColorSwatch, Label } from '@heroui/react';
function CustomColorPicker() {
return (
);
}
```
### Customizing the component classes
To customize the ColorPicker component classes, you can use the `@layer components` directive.
[Learn more](https://tailwindcss.com/docs/adding-custom-styles#adding-component-classes).
```css
@layer components {
.color-picker {
@apply inline-flex;
}
.color-picker__trigger {
@apply inline-flex items-center gap-4 rounded-lg;
}
.color-picker__popover {
@apply p-4 rounded-xl;
}
}
```
HeroUI follows the [BEM](https://getbem.com/) methodology to ensure component variants and states are reusable and easy to customize.
### CSS Classes
The ColorPicker component uses these CSS classes ([View source styles](https://github.com/heroui-inc/heroui/blob/v3/packages/styles/components/color-picker.css)):
#### Base Classes
* `.color-picker` - Base container
* `.color-picker__trigger` - Trigger button
* `.color-picker__popover` - Popover container
### Interactive States
The component supports both CSS pseudo-classes and data attributes for flexibility:
* **Focus**: `:focus-visible` or `[data-focus-visible="true"]`
* **Disabled**: `:disabled` or `[data-disabled="true"]`
## API Reference
### ColorPicker Props
Inherits from [React Aria ColorPicker](https://react-spectrum.adobe.com/react-aria/ColorPicker.html).
| Prop | Type | Default | Description |
| -------------- | ------------------------ | ------- | ---------------------------------------------------- |
| `value` | `string \| Color` | - | The current color value (controlled) |
| `defaultValue` | `string \| Color` | - | The default color value (uncontrolled) |
| `onChange` | `(color: Color) => void` | - | Handler called when the color changes |
| `children` | `React.ReactNode` | - | Content of the color picker (Trigger, Popover, etc.) |
| `className` | `string` | - | Additional CSS classes |
### ColorPicker.Trigger Props
| Prop | Type | Default | Description |
| ----------- | ------------------------------------------------------- | ------- | ------------------------------ |
| `children` | `React.ReactNode \| ((renderProps) => React.ReactNode)` | - | Trigger content or render prop |
| `className` | `string` | - | Additional CSS classes |
### ColorPicker.Popover Props
| Prop | Type | Default | Description |
| ----------- | ----------------- | --------------- | ------------------------ |
| `placement` | `Placement` | `"bottom left"` | Placement of the popover |
| `children` | `React.ReactNode` | - | Popover content |
| `className` | `string` | - | Additional CSS classes |
### Related Types
#### Color
Represents a color value. See [React Aria Color](https://react-spectrum.adobe.com/react-aria/ColorPicker.html#color) for full API.
| Method | Description |
| ---------------------------------- | ---------------------------------------------------------------------------- |
| `toString(format)` | Converts the color to a string in the given format (hex, rgb, hsl, hsb, css) |
| `toFormat(format)` | Converts the color to the given format and returns a new Color object |
| `getChannelValue(channel)` | Returns the numeric value for a given channel |
| `withChannelValue(channel, value)` | Sets the numeric value for a channel and returns a new Color |
#### parseColor
```tsx
import { parseColor } from 'react-aria-components';
// Parse from string
const color = parseColor('#ff0000');
const hslColor = parseColor('hsl(0, 100%, 50%)');
```
# ColorSlider
**Category**: react
**URL**: https://v3.heroui.com/docs/react/components/color-slider
**Source**: https://raw.githubusercontent.com/heroui-inc/heroui/refs/heads/v3/apps/docs/content/docs/react/components/(colors)/color-slider.mdx
> A color slider allows users to adjust an individual channel of a color value
## Import
```tsx
import { ColorSlider, Label } from '@heroui/react';
```
### Usage
```tsx
import {ColorSlider, Label} from "@heroui/react";
export function Basic() {
return (
);
}
```
### Anatomy
Import the ColorSlider component and access all parts using dot notation.
```tsx
import { ColorSlider, Label } from '@heroui/react';
export default () => (
)
```
### Vertical
```tsx
import {ColorSlider} from "@heroui/react";
export function Vertical() {
return (
);
}
```
### Disabled
```tsx
import {ColorSlider, Label} from "@heroui/react";
export function Disabled() {
return (
);
}
```
### Controlled
```tsx
"use client";
import {ColorSlider, ColorSwatch, Label} from "@heroui/react";
import {useState} from "react";
import {parseColor} from "react-aria-components";
export function Controlled() {
const [color, setColor] = useState(parseColor("hsl(200, 100%, 50%)"));
return (
Current color: {color.toString("hsl")}
);
}
```
### HSL Channels
Use multiple ColorSliders to control different channels of a color value. The sliders can share the same color value to create a complete color picker.
```tsx
"use client";
import {ColorSlider, ColorSwatch, Label} from "@heroui/react";
import {useState} from "react";
import {parseColor} from "react-aria-components";
export function Channels() {
const [color, setColor] = useState(parseColor("hsl(0, 100%, 50%)"));
return (
Current color: {color.toString("hsl")}
);
}
```
### Alpha Channel
The alpha channel slider shows a transparency checkerboard pattern to help visualize the transparency level.
```tsx
import {ColorSlider, Label} from "@heroui/react";
export function AlphaChannel() {
return (
);
}
```
### RGB Channels
You can also use RGB color space with red, green, and blue channels.
```tsx
"use client";
import {ColorSlider, ColorSwatch, Label} from "@heroui/react";
import {useState} from "react";
import {parseColor} from "react-aria-components";
export function RGBChannels() {
const [color, setColor] = useState(parseColor("rgb(255, 100, 50)"));
return (
Current color: {color.toString("rgb")}
);
}
```
### Custom Render Function
```tsx
"use client";
import {ColorSlider, Label} from "@heroui/react";
export function CustomRenderFunction() {
return (
}
>
);
}
```
## Related Components
* **ColorSwatch**: Visual preview of a color value
* **ColorSwatchPicker**: Color swatch selection from a list of colors
* **ColorPicker**: Composable color picker with popover
## Styling
### Passing Tailwind CSS classes
```tsx
import { ColorSlider, Label } from '@heroui/react';
function CustomColorSlider() {
return (
);
}
```
### Customizing the component classes
To customize the ColorSlider component classes, you can use the `@layer components` directive.
[Learn more](https://tailwindcss.com/docs/adding-custom-styles#adding-component-classes).
```css
@layer components {
.color-slider {
@apply flex flex-col gap-2;
}
.color-slider__output {
@apply text-muted text-sm;
}
.color-slider__track {
@apply relative h-5 w-full rounded-full;
}
.color-slider__thumb {
@apply size-4 rounded-full border-3 border-white shadow-overlay;
}
}
```
HeroUI follows the [BEM](https://getbem.com/) methodology to ensure component variants and states are reusable and easy to customize.
### CSS Classes
The ColorSlider component uses these CSS classes ([View source styles](https://github.com/heroui-inc/heroui/blob/v3/packages/styles/components/color-slider.css)):
#### Base Classes
* `.color-slider` - Base slider container
* `.color-slider__output` - Output element displaying current value
* `.color-slider__track` - Track element with color gradient
* `.color-slider__thumb` - Thumb element showing current color
#### State Classes
* `.color-slider[data-disabled="true"]` - Disabled slider state
* `.color-slider[data-orientation="vertical"]` - Vertical orientation
* `.color-slider__thumb[data-dragging="true"]` - Thumb being dragged
* `.color-slider__thumb[data-focus-visible="true"]` - Thumb keyboard focused
* `.color-slider__thumb[data-disabled="true"]` - Disabled thumb state
### Interactive States
The component supports both CSS pseudo-classes and data attributes for flexibility:
* **Hover**: `:hover` or `[data-hovered="true"]` on thumb
* **Focus**: `:focus-visible` or `[data-focus-visible="true"]` on thumb
* **Dragging**: `[data-dragging="true"]` on thumb
* **Disabled**: `:disabled` or `[data-disabled="true"]` on slider or thumb
## API Reference
### ColorSlider Props
Inherits from [React Aria ColorSlider](https://react-spectrum.adobe.com/react-aria/ColorSlider.html).
| Prop | Type | Default | Description |
| -------------- | ------------------------------------------------------------------------------ | -------------- | --------------------------------------------------------------------------------------------------------------- |
| `channel` | `ColorChannel` | - | The color channel that the slider manipulates (hue, saturation, lightness, brightness, alpha, red, green, blue) |
| `colorSpace` | `ColorSpace` | - | The color space (hsl, hsb, rgb). Defaults to the color space of the value |
| `value` | `string \| Color` | - | The current color value (controlled) |
| `defaultValue` | `string \| Color` | - | The default color value (uncontrolled) |
| `onChange` | `(value: Color) => void` | - | Handler called when the value changes during dragging |
| `onChangeEnd` | `(value: Color) => void` | - | Handler called when dragging ends |
| `orientation` | `"horizontal" \| "vertical"` | `"horizontal"` | The orientation of the slider |
| `isDisabled` | `boolean` | - | Whether the slider is disabled |
| `name` | `string` | - | The name of the input element for form submission |
| `aria-label` | `string` | - | Accessibility label for the slider |
| `className` | `string` | - | Additional CSS classes |
| `children` | `ReactNode \| RenderFunction` | - | Slider content or render function |
| `render` | `DOMRenderFunction` | - | Overrides the default DOM element with a custom render function. |
### ColorSlider.Output Props
| Prop | Type | Default | Description |
| ----------- | ----------------------------- | ------- | --------------------------------- |
| `className` | `string` | - | Additional CSS classes |
| `children` | `ReactNode \| RenderFunction` | - | Output content or render function |
### ColorSlider.Track Props
| Prop | Type | Default | Description |
| ----------- | --------------------------------- | ------- | -------------------------------- |
| `className` | `string` | - | Additional CSS classes |
| `style` | `CSSProperties \| RenderFunction` | - | Inline styles or render function |
| `children` | `ReactNode \| RenderFunction` | - | Track content or render function |
### ColorSlider.Thumb Props
| Prop | Type | Default | Description |
| ----------- | --------------------------------- | ------- | -------------------------------- |
| `className` | `string` | - | Additional CSS classes |
| `style` | `CSSProperties \| RenderFunction` | - | Inline styles or render function |
| `children` | `ReactNode \| RenderFunction` | - | Thumb content or render function |
### RenderProps
When using render functions, these values are provided:
| Prop | Type | Description |
| ------------- | ---------------------------- | ------------------------------ |
| `state` | `ColorSliderState` | The state of the color slider |
| `color` | `Color` | The current color value |
| `orientation` | `"horizontal" \| "vertical"` | The orientation of the slider |
| `isDisabled` | `boolean` | Whether the slider is disabled |
## Accessibility
The ColorSlider component implements the ARIA slider pattern and provides:
* Full keyboard navigation support (Arrow keys, Home, End, Page Up/Down)
* Screen reader announcements for value changes
* Proper focus management
* Support for disabled states
* HTML form integration via hidden input elements
* Internationalization support with locale-aware value formatting
For more information, see the [React Aria ColorSlider documentation](https://react-spectrum.adobe.com/react-aria/ColorSlider.html).
# ColorSwatchPicker
**Category**: react
**URL**: https://v3.heroui.com/docs/react/components/color-swatch-picker
**Source**: https://raw.githubusercontent.com/heroui-inc/heroui/refs/heads/v3/apps/docs/content/docs/react/components/(colors)/color-swatch-picker.mdx
> A list of color swatches that allows users to select a color from a predefined palette.
## Import
```tsx
import { ColorSwatchPicker, parseColor } from '@heroui/react';
```
### Usage
```tsx
import {ColorSwatchPicker} from "@heroui/react";
const colors = ["#F43F5E", "#D946EF", "#8B5CF6", "#3B82F6", "#06B6D4", "#10B981", "#84CC16"];
export function Basic() {
return (
{colors.map((color) => (
))}
);
}
```
### Anatomy
Import the ColorSwatchPicker component and access all parts using dot notation.
```tsx
import { ColorSwatchPicker } from '@heroui/react';
export default () => (
);
```
### Variants
```tsx
import {ColorSwatchPicker} from "@heroui/react";
const colors = ["#F43F5E", "#D946EF", "#8B5CF6", "#3B82F6", "#06B6D4", "#10B981", "#84CC16"];
export function Variants() {
return (
);
}
```
### Disabled
```tsx
import {ColorSwatchPicker} from "@heroui/react";
const colors = ["#F43F5E", "#D946EF", "#8B5CF6", "#3B82F6", "#06B6D4", "#10B981", "#84CC16"];
export function Disabled() {
return (
{colors.map((color) => (
))}
);
}
```
### Custom Indicator
```tsx
import {HeartFill} from "@gravity-ui/icons";
import {ColorSwatchPicker} from "@heroui/react";
export function CustomIndicator() {
const colors = ["#F43F5E", "#D946EF", "#8B5CF6", "#3B82F6", "#06B6D4", "#10B981", "#84CC16"];
return (
{colors.map((color) => (
))}
);
}
```
### Custom Render Function
```tsx
"use client";
import {ColorSwatchPicker} from "@heroui/react";
const colors = ["#F43F5E", "#D946EF", "#8B5CF6", "#3B82F6", "#06B6D4", "#10B981", "#84CC16"];
export function CustomRenderFunction() {
return (
}>
{colors.map((color) => (
))}
);
}
```
## Related Components
* **ColorSwatch**: Visual preview of a color value
* **ColorField**: Input for entering color values with hex format
* **ColorArea**: 2D color picker for selecting colors from a gradient area
## Styling
### Passing Tailwind CSS classes
You can customize the ColorSwatchPicker using className props:
```tsx
import { ColorSwatchPicker } from '@heroui/react';
function CustomColorSwatchPicker() {
return (
);
}
```
### Customizing the component classes
To customize the ColorSwatchPicker component classes, you can use the `@layer components` directive.
[Learn more](https://tailwindcss.com/docs/adding-custom-styles#adding-component-classes).
```css
@layer components {
.color-swatch-picker {
@apply gap-4;
}
.color-swatch-picker__item {
@apply shadow-md;
}
.color-swatch-picker__swatch {
@apply border-2 border-white;
}
}
```
HeroUI follows the [BEM](https://getbem.com/) methodology to ensure component variants and states are reusable and easy to customize.
### CSS Classes
The ColorSwatchPicker component uses these CSS classes ([View source styles](https://github.com/heroui-inc/heroui/blob/v3/packages/styles/components/color-swatch-picker.css)):
#### Base & Structure
* `.color-swatch-picker` - Base container (flex layout)
* `.color-swatch-picker__item` - Individual swatch item wrapper
* `.color-swatch-picker__swatch` - The color swatch visual element
#### Size Classes
* `.color-swatch-picker--xs` - Extra small (16px)
* `.color-swatch-picker--sm` - Small (24px)
* `.color-swatch-picker--md` - Medium (32px, default)
* `.color-swatch-picker--lg` - Large (36px)
* `.color-swatch-picker--xl` - Extra large (40px)
#### Shape Variants
* `.color-swatch-picker--circle` - Circle shape (default)
* `.color-swatch-picker--square` - Square shape with rounded corners
#### Layout Classes
* `.color-swatch-picker--grid` - Horizontal wrapping layout (default)
* `.color-swatch-picker--stack` - Vertical stacked layout
### Interactive States
The component supports both CSS pseudo-classes and data attributes for flexibility:
* **Hover**: `:hover` or `[data-hovered="true"]` - Scale up to 1.1 (only when not selected)
* **Focus**: `:focus-visible` or `[data-focus-visible="true"]` - Focus ring
* **Selected**: `[data-selected="true"]` - Inner border with same color as swatch
* **Disabled**: `[data-disabled="true"]` - Reduced opacity
## API Reference
### ColorSwatchPicker Props
Inherits from [React Aria ColorSwatchPicker](https://react-spectrum.adobe.com/react-aria/ColorSwatchPicker.html).
| Prop | Type | Default | Description |
| -------------- | ------------------------------------------------------------------------------------ | ---------- | ---------------------------------------------------------------- |
| `value` | `string \| Color` | - | The current selected color (controlled) |
| `defaultValue` | `string \| Color` | - | The default selected color (uncontrolled) |
| `onChange` | `(value: Color) => void` | - | Handler called when selection changes |
| `size` | `"xs" \| "sm" \| "md" \| "lg" \| "xl"` | `"md"` | Size of the swatches |
| `variant` | `"circle" \| "square"` | `"circle"` | Shape of the swatches |
| `layout` | `"grid" \| "stack"` | `"grid"` | Layout direction |
| `className` | `string` | - | Additional CSS classes |
| `children` | `React.ReactNode` | - | ColorSwatchPicker.Item elements |
| `render` | `DOMRenderFunction` | - | Overrides the default DOM element with a custom render function. |
### ColorSwatchPicker.Item Props
| Prop | Type | Default | Description |
| ------------ | ---------------------------------------------------------------------------------------- | ------------ | ---------------------------------------------------------------- |
| `color` | `string \| Color` | **Required** | The color of the swatch |
| `isDisabled` | `boolean` | `false` | Whether the item is disabled |
| `className` | `string` | - | Additional CSS classes |
| `children` | `React.ReactNode` | - | ColorSwatchPicker.Swatch element |
| `render` | `DOMRenderFunction` | - | Overrides the default DOM element with a custom render function. |
### ColorSwatchPicker.Swatch Props
| Prop | Type | Default | Description |
| ----------- | -------- | ------- | ---------------------- |
| `className` | `string` | - | Additional CSS classes |
### parseColor
The `parseColor` function is re-exported from React Aria Components for convenience:
```tsx
import { parseColor } from '@heroui/react';
// Parse hex color
const red = parseColor('#ff0000');
// Parse RGB
const green = parseColor('rgb(0, 255, 0)');
// Parse HSL
const blue = parseColor('hsl(240, 100%, 50%)');
```
# ColorSwatch
**Category**: react
**URL**: https://v3.heroui.com/docs/react/components/color-swatch
**Source**: https://raw.githubusercontent.com/heroui-inc/heroui/refs/heads/v3/apps/docs/content/docs/react/components/(colors)/color-swatch.mdx
> A visual preview of a color value with accessibility support
## Import
```tsx
import { ColorSwatch } from '@heroui/react';
```
### Usage
```tsx
import {ColorSwatch} from "@heroui/react";
export function ColorSwatchBasic() {
return (
);
}
```
### Sizes
```tsx
import {ColorSwatch} from "@heroui/react";
export function ColorSwatchSizes() {
return (
);
}
```
### Shapes
```tsx
import {ColorSwatch} from "@heroui/react";
export function ColorSwatchShapes() {
return (
);
}
```
### Transparency
```tsx
import {ColorSwatch} from "@heroui/react";
export function ColorSwatchTransparency() {
return (
);
}
```
### Custom Styles with Render Props
You can use the `style` render props to access the color value and create custom visual effects.
```tsx
"use client";
import {ColorSwatch} from "@heroui/react";
export function ColorSwatchCustomStyles() {
const colors = ["#0485F7", "#EF4444", "#F59E0B", "#10B981", "#D946EF"];
return (
);
}
```
### Accessibility
Use `colorName` to provide a custom accessible name for the color, and `aria-label` to add context about how the color is used.
```tsx
import {ColorSwatch} from "@heroui/react";
export function ColorSwatchAccessibility() {
return (
);
}
```
### Custom Render Function
```tsx
"use client";
import {ColorSwatch} from "@heroui/react";
export function CustomRenderFunction() {
return (
}
/>
}
/>
}
/>
}
/>
}
/>
);
}
```
## Related Components
* **ColorSwatchPicker**: Color swatch selection from a list of colors
* **ColorField**: Input for entering color values with hex format
* **ColorArea**: 2D color picker for selecting colors from a gradient area
## Styling
### Passing Tailwind CSS classes
```tsx
import {ColorSwatch} from '@heroui/react';
function CustomColorSwatch() {
return (
);
}
```
### Customizing the component classes
To customize the ColorSwatch component classes, you can use the `@layer components` directive.
[Learn more](https://tailwindcss.com/docs/adding-custom-styles#adding-component-classes).
```css
@layer components {
.color-swatch {
@apply border-2 border-white;
}
}
```
HeroUI follows the [BEM](https://getbem.com/) methodology to ensure component variants and states are reusable and easy to customize.
### CSS Classes
The ColorSwatch component uses these CSS classes ([View source styles](https://github.com/heroui-inc/heroui/blob/v3/packages/styles/components/color-swatch.css)):
#### Base Classes
* `.color-swatch` - Base swatch styles with checkered background for transparency
#### Shape Classes
* `.color-swatch--circle` - Circular shape (default)
* `.color-swatch--square` - Square shape with rounded corners
#### Size Classes
* `.color-swatch--xs` - Extra small (16px)
* `.color-swatch--sm` - Small (24px)
* `.color-swatch--md` - Medium (32px, default)
* `.color-swatch--lg` - Large (36px)
* `.color-swatch--xl` - Extra large (40px)
## API Reference
### ColorSwatch Props
| Prop | Type | Default | Description |
| ------------ | ------------------------------------------------------------------------------ | ---------- | -------------------------------------------------------------------- |
| `color` | `string \| Color` | - | The color value to display (hex, rgb, hsl, etc.) |
| `colorName` | `string` | - | Accessible name for the color (overrides auto-generated description) |
| `className` | `string` | - | Additional CSS classes |
| `shape` | `"circle" \| "square"` | `"circle"` | Shape of the swatch |
| `size` | `"xs" \| "sm" \| "md" \| "lg" \| "xl"` | `"md"` | Size of the swatch |
| `style` | `CSSProperties \| ((renderProps) => CSSProperties)` | - | Inline styles or render props function with access to color |
| `aria-label` | `string` | - | Accessible label for the swatch |
| `render` | `DOMRenderFunction` | - | Overrides the default DOM element with a custom render function. |
### Style Render Props
When using the `style` prop as a function, you receive render props with access to the color:
```tsx
({
boxShadow: `0 4px 14px ${color.toString("css")}80`,
})}
/>
```
The `color` object provides methods like:
* `color.toString("css")` - Returns CSS color string
* `color.toString("hex")` - Returns hex color string
* `color.getChannelValue("alpha")` - Returns alpha channel value
# Slider
**Category**: react
**URL**: https://v3.heroui.com/docs/react/components/slider
**Source**: https://raw.githubusercontent.com/heroui-inc/heroui/refs/heads/v3/apps/docs/content/docs/react/components/(controls)/slider.mdx
> A slider allows a user to select one or more values within a range
## Import
```tsx
import { Slider } from '@heroui/react';
```
### Usage
```tsx
import {Label, Slider} from "@heroui/react";
export function Default() {
return (
);
}
```
### Anatomy
Import the Slider component and access all parts using dot notation.
```tsx
import { Slider, Label } from '@heroui/react';
export default () => (
)
```
### Range Slider Anatomy
```tsx
import { Slider, Label } from '@heroui/react';
export default () => (
{({state}) => (
<>
{state.values.map((_, i) => (
))}
>
)}
)
```
### Vertical
```tsx
import {Label, Slider} from "@heroui/react";
export function Vertical() {
return (
);
}
```
### Range
```tsx
"use client";
import {Label, Slider} from "@heroui/react";
export function Range() {
return (
{({state}) => (
<>
{state.values.map((_, i) => (
))}
>
)}
);
}
```
### Disabled
```tsx
import {Label, Slider} from "@heroui/react";
export function Disabled() {
return (
);
}
```
### Custom Render Function
```tsx
"use client";
import {Label, Slider} from "@heroui/react";
export function CustomRenderFunction() {
return (
}
>
);
}
```
## Related Components
* **Label**: Accessible label for form controls
* **Form**: Form validation and submission handling
* **Description**: Helper text for form fields
## Styling
### Passing Tailwind CSS classes
```tsx
import { Slider, Label } from '@heroui/react';
function CustomSlider() {
return (
);
}
```
### Customizing the component classes
To customize the Slider component classes, you can use the `@layer components` directive.
[Learn more](https://tailwindcss.com/docs/adding-custom-styles#adding-component-classes).
```css
@layer components {
.slider {
@apply flex flex-col gap-2;
}
.slider__output {
@apply text-muted-fg text-sm;
}
.slider-track {
@apply relative h-2 w-full rounded-full bg-surface-secondary;
}
.slider-fill {
@apply absolute h-full rounded-full bg-accent;
}
.slider-thumb {
@apply size-4 rounded-full bg-accent border-2 border-background;
}
}
```
HeroUI follows the [BEM](https://getbem.com/) methodology to ensure component variants and states are reusable and easy to customize.
### CSS Classes
The Slider component uses these CSS classes ([View source styles](https://github.com/heroui-inc/heroui/blob/v3/packages/styles/components/slider.css)):
#### Base Classes
* `.slider` - Base slider container
* `.slider__output` - Output element displaying current value(s)
* `.slider-track` - Track element containing fill and thumbs
* `.slider-fill` - Fill element showing selected range
* `.slider-thumb` - Individual thumb element
#### State Classes
* `.slider[data-disabled="true"]` - Disabled slider state
* `.slider[data-orientation="vertical"]` - Vertical orientation
* `.slider-thumb[data-dragging="true"]` - Thumb being dragged
* `.slider-thumb[data-focus-visible="true"]` - Thumb keyboard focused
* `.slider-thumb[data-disabled="true"]` - Disabled thumb state
* `.slider-track[data-fill-start="true"]` - Fill starts at beginning
* `.slider-track[data-fill-end="true"]` - Fill ends at end
### Interactive States
The component supports both CSS pseudo-classes and data attributes for flexibility:
* **Hover**: `:hover` or `[data-hovered="true"]` on thumb
* **Focus**: `:focus-visible` or `[data-focus-visible="true"]` on thumb
* **Dragging**: `[data-dragging="true"]` on thumb
* **Disabled**: `:disabled` or `[data-disabled="true"]` on slider or thumb
## API Reference
### Slider Props
| Prop | Type | Default | Description |
| ----------------- | ------------------------------------------------------------------------- | -------------- | ---------------------------------------------------------------- |
| `value` | `number \| number[]` | - | The current value (controlled) |
| `defaultValue` | `number \| number[]` | - | The default value (uncontrolled) |
| `onChange` | `(value: number \| number[]) => void` | - | Handler called when the value changes |
| `onChangeEnd` | `(value: number \| number[]) => void` | - | Handler called when dragging ends |
| `minValue` | `number` | `0` | The slider's minimum value |
| `maxValue` | `number` | `100` | The slider's maximum value |
| `step` | `number` | `1` | The slider's step value |
| `formatOptions` | `Intl.NumberFormatOptions` | - | The display format of the value label |
| `orientation` | `"horizontal" \| "vertical"` | `"horizontal"` | The orientation of the slider |
| `isDisabled` | `boolean` | - | Whether the slider is disabled |
| `aria-label` | `string` | - | Accessibility label for the slider |
| `aria-labelledby` | `string` | - | ID of element that labels the slider |
| `className` | `string` | - | Additional CSS classes |
| `children` | `ReactNode \| RenderFunction` | - | Slider content or render function |
| `render` | `DOMRenderFunction` | - | Overrides the default DOM element with a custom render function. |
### Slider.Output Props
| Prop | Type | Default | Description |
| ----------- | ------------------------------------------------------------------------------- | ------- | ---------------------------------------------------------------- |
| `className` | `string` | - | Additional CSS classes |
| `children` | `ReactNode \| RenderFunction` | - | Output content or render function |
| `render` | `DOMRenderFunction` | - | Overrides the default DOM element with a custom render function. |
### Slider.Track Props
| Prop | Type | Default | Description |
| ----------- | ------------------------------------------------------------------------------ | ------- | ---------------------------------------------------------------- |
| `className` | `string` | - | Additional CSS classes |
| `children` | `ReactNode \| RenderFunction` | - | Track content or render function |
| `render` | `DOMRenderFunction` | - | Overrides the default DOM element with a custom render function. |
### Slider.Fill Props
| Prop | Type | Default | Description |
| ----------- | --------------- | ------- | ---------------------- |
| `className` | `string` | - | Additional CSS classes |
| `style` | `CSSProperties` | - | Inline styles |
### Slider.Thumb Props
| Prop | Type | Default | Description |
| ------------ | ------------------------------------------------------------------------------ | ------- | ---------------------------------------------------------------- |
| `index` | `number` | `0` | Index of the thumb within the slider |
| `isDisabled` | `boolean` | - | Whether this thumb is disabled |
| `name` | `string` | - | The name of the input element, used when submitting an HTML form |
| `className` | `string` | - | Additional CSS classes |
| `children` | `ReactNode \| RenderFunction` | - | Thumb content or render function |
| `render` | `DOMRenderFunction` | - | Overrides the default DOM element with a custom render function. |
### RenderProps
When using render functions with Slider.Output or Slider.Track, these values are provided:
| Prop | Type | Description |
| -------------------- | ---------------------------- | -------------------------------------------------------- |
| `state` | `SliderState` | The state of the slider |
| `values` | `number[]` | Values managed by the slider by thumb index |
| `getThumbValueLabel` | `(index: number) => string` | Returns the string label for the specified thumb's value |
| `orientation` | `"horizontal" \| "vertical"` | The orientation of the slider |
| `isDisabled` | `boolean` | Whether the slider is disabled |
## Examples
### Basic Usage
```tsx
import { Slider, Label } from '@heroui/react';
```
### Range Slider
```tsx
import { Slider, Label } from '@heroui/react';
{({state}) => (
<>
{state.values.map((_, i) => (
))}
>
)}
```
### Controlled Value
```tsx
import { Slider, Label } from '@heroui/react';
import { useState } from 'react';
function ControlledSlider() {
const [value, setValue] = useState(25);
return (
<>
Current value: {value}
>
);
}
```
### Custom Value Formatting
```tsx
import { Slider, Label } from '@heroui/react';
```
### Vertical Orientation
```tsx
import { Slider, Label } from '@heroui/react';
```
### Custom Output Display
```tsx
import { Slider, Label } from '@heroui/react';
{({state}) =>
state.values.map((_, i) => state.getThumbValueLabel(i)).join(' – ')
}
{({state}) => (
<>
{state.values.map((_, i) => (
))}
>
)}
```
## Accessibility
The Slider component implements the ARIA slider pattern and provides:
* Full keyboard navigation support (Arrow keys, Home, End, Page Up/Down)
* Screen reader announcements for value changes
* Proper focus management
* Support for disabled states
* HTML form integration via hidden input elements
* Internationalization support with locale-aware value formatting
* Right-to-left (RTL) language support
For more information, see the [React Aria Slider documentation](https://react-spectrum.adobe.com/react-aria/Slider.html).
# Switch
**Category**: react
**URL**: https://v3.heroui.com/docs/react/components/switch
**Source**: https://raw.githubusercontent.com/heroui-inc/heroui/refs/heads/v3/apps/docs/content/docs/react/components/(controls)/switch.mdx
> A toggle switch component for boolean states
## Import
```tsx
import { Switch, SwitchGroup, Label } from '@heroui/react';
```
### Usage
```tsx
import {Label, Switch} from "@heroui/react";
export function Basic() {
return (
);
}
```
### Anatomy
Import the Switch component and access all parts using dot notation.
```tsx
import { Switch, Label, Description } from '@heroui/react';
export default () => (
{/* Optional */}
{/* Optional */}
);
```
For grouping multiple switches, use the `SwitchGroup` component:
```tsx
import { Switch, SwitchGroup, Label } from '@heroui/react';
export default () => (
);
```
### Disabled
```tsx
import {Label, Switch} from "@heroui/react";
export function Disabled() {
return (
);
}
```
### Default Selected
```tsx
import {Label, Switch} from "@heroui/react";
export function DefaultSelected() {
return (
);
}
```
### Controlled
```tsx
"use client";
import {Label, Switch} from "@heroui/react";
import React from "react";
export function Controlled() {
const [isSelected, setIsSelected] = React.useState(false);
return (
Switch is {isSelected ? "on" : "off"}
);
}
```
### Without Label
```tsx
import {Switch} from "@heroui/react";
export function WithoutLabel() {
return (
);
}
```
### Sizes
```tsx
import {Label, Switch} from "@heroui/react";
export function Sizes() {
return (
);
}
```
### Label Position
```tsx
import {Label, Switch} from "@heroui/react";
export function LabelPosition() {
return (
);
}
```
### With Icons
```tsx
"use client";
import {
BellFill,
BellSlash,
Check,
Microphone,
MicrophoneSlash,
Moon,
Power,
Sun,
VolumeFill,
VolumeSlashFill,
} from "@gravity-ui/icons";
import {Switch} from "@heroui/react";
export function WithIcons() {
const icons = {
check: {
off: Power,
on: Check,
selectedControlClass: "bg-green-500/80",
},
darkMode: {
off: Moon,
on: Sun,
selectedControlClass: "",
},
microphone: {
off: Microphone,
on: MicrophoneSlash,
selectedControlClass: "bg-red-500/80",
},
notification: {
off: BellSlash,
on: BellFill,
selectedControlClass: "bg-purple-500/80",
},
volume: {
off: VolumeFill,
on: VolumeSlashFill,
selectedControlClass: "bg-blue-500/80",
},
};
return (
);
}
```
### Sizes
```tsx
import {Avatar, Badge} from "@heroui/react";
const AVATAR_URL = "https://heroui-assets.nyc3.cdn.digitaloceanspaces.com/avatars/green.jpg";
export function BadgeSizes() {
const sizes = ["sm", "md", "lg"] as const;
return (
{sizes.map((size) => (
JD
5
))}
);
}
```
### Variants
```tsx
import {Avatar, Badge, Separator} from "@heroui/react";
import React from "react";
const AVATAR_URL = "https://heroui-assets.nyc3.cdn.digitaloceanspaces.com/avatars/green.jpg";
export function BadgeVariants() {
const variants = ["primary", "secondary", "soft"] as const;
const colors = ["accent", "default", "success", "warning", "danger"] as const;
return (
{variants.map((variant, index) => (
{variant}
{colors.map((color) => (
JD
5
))}
{index < variants.length - 1 && }
))}
);
}
```
### Placements
```tsx
import {Avatar, Badge} from "@heroui/react";
const AVATAR_URL = "https://heroui-assets.nyc3.cdn.digitaloceanspaces.com/avatars/green.jpg";
export function BadgePlacements() {
const placements = ["top-right", "top-left", "bottom-right", "bottom-left"] as const;
return (
{placements.map((placement) => (
JD{placement}
))}
);
}
```
### With Content
Badge supports text, numbers, and icons as content. When no children are provided, it renders as a dot indicator.
```tsx
import {Bell} from "@gravity-ui/icons";
import {Avatar, Badge} from "@heroui/react";
const AVATAR_URL = "https://heroui-assets.nyc3.cdn.digitaloceanspaces.com/avatars/green.jpg";
export function BadgeWithContent() {
return (
JD
5
JD
New
JD
99+
JD
);
}
```
### Dot Badge
Empty badges act as status indicators — useful for online/offline states or activity signals.
```tsx
import {Avatar, Badge} from "@heroui/react";
const AVATAR_URL = "https://heroui-assets.nyc3.cdn.digitaloceanspaces.com/avatars/green.jpg";
export function BadgeDot() {
const colors = ["accent", "success", "warning", "danger"] as const;
return (
{colors.map((color) => (
JD
))}
);
}
```
## Related Components
* **Avatar**: Display user profile images
* **Chip**: Compact elements for tags and filters
## Styling
### Passing Tailwind CSS classes
You can style the root container and individual slots:
```tsx
import {Badge, Avatar} from '@heroui/react';
function CustomBadge() {
return (
99+
);
}
```
### Customizing the component classes
To customize the Badge component classes, you can use the `@layer components` directive.
[Learn more](https://tailwindcss.com/docs/adding-custom-styles#adding-component-classes).
```css
@layer components {
.badge {
@apply rounded-full text-xs;
}
.badge__label {
@apply font-semibold;
}
.badge--accent {
@apply shadow-sm;
}
}
```
HeroUI follows the [BEM](https://getbem.com/) methodology to ensure component variants and states are reusable and easy to customize.
### CSS Classes
The Badge component uses these CSS classes ([View source styles](https://github.com/heroui-inc/heroui/blob/v3/packages/styles/components/badge.css)):
#### Base Classes
* `.badge` - Base badge container styles
* `.badge__label` - Label text slot styles
* `.badge-anchor` - Positioning wrapper for the anchored element
#### Color Classes
* `.badge--accent` - Accent color variant
* `.badge--danger` - Danger color variant
* `.badge--default` - Default color variant
* `.badge--success` - Success color variant
* `.badge--warning` - Warning color variant
#### Variant Classes
* `.badge--primary` - Primary variant with filled background
* `.badge--secondary` - Secondary variant with default background
* `.badge--soft` - Soft variant with lighter background
#### Size Classes
* `.badge--sm` - Small size
* `.badge--md` - Medium size (default)
* `.badge--lg` - Large size
#### Placement Classes
* `.badge--top-right` - Position at top-right corner (default)
* `.badge--top-left` - Position at top-left corner
* `.badge--bottom-right` - Position at bottom-right corner
* `.badge--bottom-left` - Position at bottom-left corner
#### Compound Variant Classes
Badges support combining variant and color classes (e.g., `.badge--primary.badge--accent`). The following combinations have default styles defined:
**Primary Variants:**
* `.badge--primary.badge--accent` - Primary accent with filled background
* `.badge--primary.badge--default` - Primary default with filled background
* `.badge--primary.badge--success` - Primary success with filled background
* `.badge--primary.badge--warning` - Primary warning with filled background
* `.badge--primary.badge--danger` - Primary danger with filled background
**Soft Variants:**
* `.badge--soft.badge--accent` - Soft accent with lighter background
* `.badge--soft.badge--default` - Soft default with lighter background
* `.badge--soft.badge--success` - Soft success with lighter background
* `.badge--soft.badge--warning` - Soft warning with lighter background
* `.badge--soft.badge--danger` - Soft danger with lighter background
## API Reference
### Badge Props
| Prop | Type | Default | Description |
| ----------- | -------------------------------------------------------------- | ------------- | -------------------------------------------------------------------------------------------- |
| `children` | `React.ReactNode` | - | Content to display inside the badge (text, number, or icon). When omitted, renders as a dot. |
| `className` | `string` | - | Additional CSS classes for the root element |
| `color` | `"default" \| "accent" \| "success" \| "warning" \| "danger"` | `"default"` | Color variant of the badge |
| `variant` | `"primary" \| "secondary" \| "soft"` | `"primary"` | Visual style variant |
| `size` | `"sm" \| "md" \| "lg"` | `"md"` | Size of the badge |
| `placement` | `"top-right" \| "top-left" \| "bottom-right" \| "bottom-left"` | `"top-right"` | Position of the badge relative to its anchor |
### Badge.Anchor Props
| Prop | Type | Default | Description |
| ----------- | ----------------- | ------- | --------------------------------------------------------- |
| `children` | `React.ReactNode` | - | The element to anchor the badge to, plus the Badge itself |
| `className` | `string` | - | Additional CSS classes for the anchor wrapper |
### Badge.Label Props
| Prop | Type | Default | Description |
| ----------- | ----------------- | ------- | ----------------------------------------- |
| `children` | `React.ReactNode` | - | Label text content |
| `className` | `string` | - | Additional CSS classes for the label slot |
# Chip
**Category**: react
**URL**: https://v3.heroui.com/docs/react/components/chip
**Source**: https://raw.githubusercontent.com/heroui-inc/heroui/refs/heads/v3/apps/docs/content/docs/react/components/(data-display)/chip.mdx
> Small informational badges for displaying labels, statuses, and categories
## Import
```tsx
import { Chip } from '@heroui/react';
```
## Anatomy
Import the Chip component and access all parts using dot notation.
> Plain-text children are automatically wrapped in ``.
```tsx
Label text
```
### Usage
```tsx
import {Chip} from "@heroui/react";
export function ChipBasic() {
return (
DefaultAccentSuccessWarningDanger
);
}
```
### Variants
```tsx
import {CircleDashed} from "@gravity-ui/icons";
import {Chip, Separator} from "@heroui/react";
import React from "react";
export function ChipVariants() {
const sizes = ["lg", "md", "sm"] as const;
const variants = ["primary", "secondary", "tertiary", "soft"] as const;
const colors = ["accent", "default", "success", "warning", "danger"] as const;
return (
{sizes.map((size, index) => (
{size}
{/* Color labels header */}
{colors.map((color) => (
{color}
))}
{variants.map((variant) => (
{variant}
{colors.map((color) => (
Label
))}
))}
{index < sizes.length - 1 && }
))}
);
}
```
### With Icons
```tsx
import {ChevronDown, CircleCheckFill, CircleFill, Clock, Xmark} from "@gravity-ui/icons";
import {Chip} from "@heroui/react";
export function ChipWithIcon() {
return (
InformationCompletedPendingFailedLabel
);
}
```
### Statuses
```tsx
import {Ban, Check, CircleFill, CircleInfo, TriangleExclamation} from "@gravity-ui/icons";
import {Chip} from "@heroui/react";
export function ChipStatuses() {
return (
DefaultActivePendingInactive
New FeatureAvailableBetaDeprecated
);
}
```
## Related Components
* **Avatar**: Display user profile images
* **CloseButton**: Button for dismissing overlays
* **Separator**: Visual divider between content
## Styling
### Passing Tailwind CSS classes
You can style the root container and individual slots:
```tsx
import {Chip} from '@heroui/react';
function CustomChip() {
return (
Custom Styled
);
}
```
### Customizing the component classes
To customize the Chip component classes, you can use the `@layer components` directive.
[Learn more](https://tailwindcss.com/docs/adding-custom-styles#adding-component-classes).
```css
@layer components {
.chip {
@apply rounded-full text-xs;
}
.chip__label {
@apply font-medium;
}
.chip--accent {
@apply border-accent/20;
}
.chip--accent .chip__label {
@apply text-accent;
}
}
```
HeroUI follows the [BEM](https://getbem.com/) methodology to ensure component variants and states are reusable and easy to customize.
### CSS Classes
The Chip component uses these CSS classes ([View source styles](https://github.com/heroui-inc/heroui/blob/v3/packages/styles/components/chip.css)):
#### Base Classes
* `.chip` - Base chip container styles
* `.chip__label` - Label text slot styles
#### Color Classes
* `.chip--accent` - Accent color variant
* `.chip--danger` - Danger color variant
* `.chip--default` - Default color variant
* `.chip--success` - Success color variant
* `.chip--warning` - Warning color variant
#### Variant Classes
* `.chip--primary` - Primary variant with filled background
* `.chip--secondary` - Secondary variant with border
* `.chip--tertiary` - Tertiary variant with transparent background
* `.chip--soft` - Soft variant with lighter background
#### Size Classes
* `.chip--sm` - Small size
* `.chip--md` - Medium size (default)
* `.chip--lg` - Large size
#### Compound Variant Classes
Chips support combining variant and color classes (e.g., `.chip--secondary.chip--accent`). The following combinations have default styles defined:
**Primary Variants:**
* `.chip--primary.chip--accent` - Primary accent combination with filled background
* `.chip--primary.chip--success` - Primary success combination with filled background
* `.chip--primary.chip--warning` - Primary warning combination with filled background
* `.chip--primary.chip--danger` - Primary danger combination with filled background
**Soft Variants:**
* `.chip--accent.chip--soft` - Soft accent combination with lighter background
* `.chip--success.chip--soft` - Soft success combination with lighter background
* `.chip--warning.chip--soft` - Soft warning combination with lighter background
* `.chip--danger.chip--soft` - Soft danger combination with lighter background
**Note:** You can apply custom styles to any variant-color combination (e.g., `.chip--secondary.chip--accent`, `.chip--tertiary.chip--success`) using the `@layer components` directive in your CSS.
## API Reference
### Chip Props
| Prop | Type | Default | Description |
| ----------- | ------------------------------------------------------------- | ------------- | ------------------------------------------- |
| `children` | `React.ReactNode` | - | Content to display inside the chip |
| `className` | `string` | - | Additional CSS classes for the root element |
| `color` | `"default" \| "accent" \| "success" \| "warning" \| "danger"` | `"default"` | Color variant of the chip |
| `variant` | `"primary" \| "secondary" \| "tertiary" \| "soft"` | `"secondary"` | Visual style variant |
| `size` | `"sm" \| "md" \| "lg"` | `"md"` | Size of the chip |
### Chip.Label Props
| Prop | Type | Default | Description |
| ----------- | ----------------- | ------- | ----------------------------------------- |
| `children` | `React.ReactNode` | - | Label text content |
| `className` | `string` | - | Additional CSS classes for the label slot |
# Table
**Category**: react
**URL**: https://v3.heroui.com/docs/react/components/table
**Source**: https://raw.githubusercontent.com/heroui-inc/heroui/refs/heads/v3/apps/docs/content/docs/react/components/(data-display)/table.mdx
> Tables display structured data in rows and columns with support for sorting, selection, column resizing, and infinite scrolling.
## Import
```tsx
import { Table } from '@heroui/react';
```
### Usage
```tsx
import {Table} from "@heroui/react";
export function Basic() {
return (
);
}
```
### Anatomy
Import the Table component and access all parts using dot notation.
```tsx
import { Table } from '@heroui/react';
export default () => (