# 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 six visual variants for different emphasis levels.
```tsx
```
### Feedback Variants
Choose between highlight and ripple feedback effects for press interactions.
```tsx
{
/* Highlight feedback (default) */
}
;
{
/* Ripple feedback */
}
;
{
/* Customize ripple animation */
}
;
```
### 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.
```tsx
```
## 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 = useThemeColor('accent-foreground');
const themeColorAccentSoftForeground = useThemeColor(
'accent-soft-foreground'
);
const themeColorDangerForeground = useThemeColor('danger-foreground');
const themeColorDefaultForeground = useThemeColor('default-foreground');
return (
);
}
```
## API Reference
### Button
Button extends all props from [PressableFeedback](./pressable-feedback) component with additional button-specific props.
| prop | type | default | description |
| ------------ | -------------------------------------------------------------------------------- | ----------- | -------------------------------------------------------------- |
| `variant` | `'primary' \| 'secondary' \| 'tertiary' \| '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) |
For inherited props including `feedbackVariant`, `feedbackPosition`, `animation`, `isDisabled`, `className`, `children`, and all Pressable props, 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' \| '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.
# 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
);
}
```
## 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.
# ErrorView
**Category**: native
**URL**: https://v3.heroui.com/docs/native/components/error-view
**Source**: https://raw.githubusercontent.com/heroui-inc/heroui/refs/heads/v3/apps/docs/content/docs/native/components/(feedback)/error-view.mdx
> Displays validation error message content with smooth animations.
## Import
```tsx
import { ErrorView } from 'heroui-native';
```
## Anatomy
```tsx
Error message content
```
* **ErrorView**: 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 ErrorView component displays error messages when validation fails.
```tsx
This field is required
```
### Controlled Visibility
Control when the error appears using the `isInvalid` prop.
```tsx
const [isInvalid, setIsInvalid] = useState(false);
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 { ErrorView, TextField } from 'heroui-native';
import { useState } from 'react';
import { View } from 'react-native';
export default function ErrorViewExample() {
const [email, setEmail] = useState('');
const [showError, setShowError] = useState(false);
const isValidEmail = /^[^\s@]+@[^\s@]+\.[^\s@]+$/.test(email);
const handleBlur = () => {
setShowError(email !== '' && !isValidEmail);
};
return (
Email Address
We'll use this to contact you
Please enter a valid email address
);
}
```
## API Reference
### ErrorView
| prop | type | default | description |
| ---------------------- | ------------------------------ | ----------- | ------------------------------------------------------------------------ |
| `children` | `React.ReactNode` | `undefined` | The content of the error field. String children are wrapped with Text |
| `isInvalid` | `boolean` | `false` | Controls the visibility of the error field |
| `animation` | `ErrorViewRootAnimation` | - | Animation configuration |
| `className` | `string` | `undefined` | Additional CSS classes for the container |
| `classNames` | `ElementSlots` | `undefined` | Additional CSS classes for different parts of the component |
| `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 error view component. Available slots: `container`, `text`.
#### ErrorViewRootAnimation
Animation configuration for error view 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 |
| ---------------- | ----------------------- | ----------------------------------------------------------------------- | ---------------------------------------- |
| `entering.value` | `EntryOrExitLayoutType` | `FadeIn` `.duration(150)` `.easing(Easing.out(Easing.ease))` | Custom entering animation for error view |
| `exiting.value` | `EntryOrExitLayoutType` | `FadeOut` `.duration(100)` `.easing(Easing.out(Easing.ease))` | Custom exiting animation for error view |
# 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.
);
}
```
## 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 |
| ------------------------ | ----------------------- | --------------------------- | -------------------------------------- |
| `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
);
}
```
## 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 |
| `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 |
| ------------------------ | ----------------------- | --------------------------- | -------------------------------------- |
| `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'}
);
}
```
## 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 |
| ---------------- | ----------------------- | ---------------------------------------------------------------------- | ------------------------- |
| `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 |
| `...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 |
| ----------------- | ---------------------------- | --------------- | ------------------------------ |
| `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, Divider, FormField, 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 (
{title}
{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 && }
))}
);
}
```
## 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) |
| `isOnSurface` | `boolean` | `undefined` | Whether checkbox is on a surface background (auto-detected if not set) |
| `hitSlop` | `number` | `6` | Hit slop for the pressable area |
| `animation` | `CheckboxRootAnimation` | - | Animation configuration |
| `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 |
| -------------------- | ------------------ | ------------------- | ---------------------------------- |
| `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 |
| `...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 |
| --------------------------- | ------------------ | ------------------- | -------------------------------------------- |
| `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) |
| `isOnSurface` | `boolean \| undefined` | Whether checkbox is on a surface background |
| `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.
# FormField
**Category**: native
**URL**: https://v3.heroui.com/docs/native/components/form-field
**Source**: https://raw.githubusercontent.com/heroui-inc/heroui/refs/heads/v3/apps/docs/content/docs/native/components/(forms)/form-field.mdx
> Provides consistent layout and interaction for form controls with label, description, and error handling. Perfect for Switch and Checkbox components when you want the entire field to be pressable.
## Import
```tsx
import { FormField } from 'heroui-native';
```
## Anatomy
```tsx
............
```
* **FormField**: Root container that manages layout and state propagation
* **FormField.Label**: Primary text label for the control
* **FormField.Description**: Secondary descriptive helper text
* **FormField.Indicator**: Container for the form control component (Switch, Checkbox)
* **FormField.ErrorMessage**: Validation error message display
## Usage
### Basic Usage
FormField wraps form controls to provide consistent layout and state management.
```tsx
Label text
```
### With Description
Add helper text below the label using the Description component.
```tsx
Enable notifications
Receive push notifications about your account activity
```
### With Error Message
Display validation errors using the ErrorMessage component.
```tsx
I agree to the terms
By checking this box, you agree to our Terms of Service
This field is required
```
### Disabled State
Control interactivity with the disabled prop.
```tsx
Disabled fieldThis field is disabled
```
### Disabling All Animations
Disable all animations including children by using `"disable-all"`. This cascades down to all child components.
```tsx
Label textDescription text
```
## Example
```tsx
import { Checkbox, FormField, Switch } from 'heroui-native';
import React from 'react';
import { ScrollView, View } from 'react-native';
export default function FormFieldExample() {
const [notifications, setNotifications] = React.useState(false);
const [terms, setTerms] = React.useState(false);
const [newsletter, setNewsletter] = React.useState(true);
return (
Enable notifications
Receive push notifications about your account activity
I agree to the terms and conditions
By checking this box, you agree to our Terms of Service
This field is required
Subscribe to newsletter
);
}
```
## API Reference
### FormField
| prop | type | default | description |
| ----------------- | ----------------------------------------------------------------------- | ----------- | ----------------------------------------------------------------------------------------- |
| children | `React.ReactNode \| ((props: FormFieldRenderProps) => 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 |
| 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 |
### FormField.Label
| prop | type | default | description |
| ------------ | ----------------- | ------- | ----------------------------------------- |
| children | `React.ReactNode` | - | Label text content |
| className | `string` | - | Custom class name for the label element |
| ...TextProps | `TextProps` | - | All React Native Text props are supported |
### FormField.Description
| prop | type | default | description |
| ------------ | ----------------- | ------- | --------------------------------------------- |
| children | `React.ReactNode` | - | Description text content |
| className | `string` | - | Custom class name for the description element |
| ...TextProps | `TextProps` | - | All React Native Text props are supported |
### FormField.Indicator
| prop | type | default | description |
| ------------ | ------------------------ | ---------- | ---------------------------------------------------------- |
| children | `React.ReactNode` | - | Control component to render (Switch, Checkbox) |
| variant | `'checkbox' \| '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 FormField context if they are not already present on the child component.
### FormField.ErrorMessage
FormField.ErrorMessage extends all props from [ErrorView](./error-view) component.
**Note**: The `isInvalid` prop is automatically passed from the FormField context. The error message visibility is controlled by the `isInvalid` state of the parent FormField.
## Hooks
### useFormField
**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 |
# 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 default indicator if no children provided. Supports render function children to access state (`isSelected`, `isInvalid`, `isDisabled`).
* **RadioGroup.Label**: Optional clickable text label for the radio option. Linked to the radio for accessibility.
* **RadioGroup.Description**: Optional secondary text below the label. Provides additional context about the radio option.
* **RadioGroup.Indicator**: Optional container for the radio circle. Renders default thumb if no children provided. Manages the visual selection state.
* **RadioGroup.IndicatorThumb**: Optional inner circle that appears when selected. Animates scale based on selection. Can be replaced with custom content.
* **RadioGroup.ErrorMessage**: Error message displayed when radio group is invalid. Shown with animation below the radio group content.
## 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
Standard Shipping
Delivered in 5-7 business days
Express Shipping
Delivered in 2-3 business days
```
### Custom Indicator
Replace the default indicator thumb with custom content.
```tsx
Custom Option
{value === 'custom' && (
)}
```
### With Render Function
Use a render function on RadioGroup.Item to access state and customize the entire content.
```tsx
{({ isSelected, isInvalid, isDisabled }) => (
<>
Option 1
{isSelected && }
>
)}
```
### With Error Message
Display validation errors below the radio group.
```tsx
I agree to the termsI do not agree
Please select an option to continue
```
## Example
```tsx
import { RadioGroup, useThemeColor } from 'heroui-native';
import { Ionicons } from '@expo/vector-icons';
import React from 'react';
import { View } from 'react-native';
export default function PaymentMethodExample() {
const [paymentMethod, setPaymentMethod] = React.useState('card');
const themeColorForeground = useThemeColor('foreground');
return (
Credit/Debit Card
Pay securely with your credit or debit card
PayPal
Fast and secure payment with PayPal
Bank Transfer
Direct transfer from your bank account
);
}
```
## 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 |
| `isOnSurface` | `boolean` | `undefined` | Whether the radio group is on surface |
| `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 |
| `isOnSurface` | `boolean` | `undefined` | Whether the radio item is on surface (auto-detected if not set) |
| `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 |
### RadioGroup.Indicator
| prop | type | default | description |
| ----------------------- | -------------------------- | ----------- | ------------------------------------------------ |
| `children` | `React.ReactNode` | `undefined` | Indicator content |
| `className` | `string` | `undefined` | Custom class name |
| `...Animated.ViewProps` | `AnimatedProps` | - | All Reanimated Animated.View props are supported |
**Note:** The `isOnSurface` state is automatically provided via context from the parent RadioGroup.Item component.
### RadioGroup.IndicatorThumb
| prop | type | default | description |
| ----------------------- | ----------------------------------- | ----------- | ------------------------------------------------ |
| `className` | `string` | `undefined` | Custom class name |
| `animation` | `RadioGroupIndicatorThumbAnimation` | - | Animation configuration |
| `...Animated.ViewProps` | `AnimatedProps` | - | All Reanimated Animated.View props are supported |
#### RadioGroupIndicatorThumbAnimation
Animation configuration for RadioGroupIndicatorThumb component. Can be:
* `false` or `"disabled"`: Disable all animations
* `true` or `undefined`: Use default animations
* `object`: Custom animation configuration
| prop | type | default | description |
| -------------------- | ------------------ | ---------------------------------------------------- | ------------------------------------ |
| `scale.value` | `[number, number]` | `[1.5, 1]` | Scale values \[unselected, selected] |
| `scale.timingConfig` | `WithTimingConfig` | `{ duration: 300, easing: Easing.out(Easing.ease) }` | Animation timing configuration |
### RadioGroup.Label
| prop | type | default | description |
| ----------------------- | -------------------------- | ----------- | ------------------------------------------------ |
| `children` | `React.ReactNode` | `undefined` | Label text content |
| `className` | `string` | `undefined` | Custom class name for the label element |
| `...Animated.TextProps` | `AnimatedProps` | - | All Reanimated Animated.Text props are supported |
### RadioGroup.Description
| prop | type | default | description |
| ----------------------- | -------------------------- | ----------- | ------------------------------------------------ |
| `children` | `React.ReactNode` | `undefined` | Description text content |
| `className` | `string` | `undefined` | Custom class name for the description element |
| `...Animated.TextProps` | `AnimatedProps` | - | All Reanimated Animated.Text props are supported |
### RadioGroup.ErrorMessage
| prop | type | default | description |
| ----------------------- | ------------------------------ | ----------- | ------------------------------------------------ |
| `children` | `React.ReactNode` | `undefined` | The content of the error field |
| `isInvalid` | `boolean` | `false` | Controls the visibility of the error field |
| `className` | `string` | `undefined` | Additional CSS class for styling |
| `classNames` | `ElementSlots` | `undefined` | Additional CSS classes for different parts |
| `textProps` | `TextProps` | `undefined` | Additional props to pass to the Text component |
| `...Animated.ViewProps` | `AnimatedProps` | - | All Reanimated Animated.View props are supported |
## 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 |
| `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` | Whether the radio item is disabled |
| `isInvalid` | `boolean` | Whether the radio item is invalid |
| `isOnSurface` | `boolean` | Whether the radio item is on surface |
# 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.
* **Select.Value**: Displays the selected value or placeholder text. Automatically updates when selection changes.
* **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 that dismisses the select when pressed. Renders a default X icon if no children provided.
* **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
```
### Controlled Mode
Control the select state programmatically.
```tsx
const [value, setValue] = useState();
const [isOpen, setIsOpen] = useState(false);
;
```
## Example
```tsx
import { Button, Select } from 'heroui-native';
import { useState } from 'react';
import { ScrollView, Text, View } from 'react-native';
type CountryOption = {
value: string;
label: string;
flag: string;
code: string;
};
const COUNTRIES: CountryOption[] = [
{ value: 'US', label: 'United States', flag: '🇺🇸', code: '+1' },
{ value: 'GB', label: 'United Kingdom', flag: '🇬🇧', code: '+44' },
{ value: 'CA', label: 'Canada', flag: '🇨🇦', code: '+1' },
{ value: 'AU', label: 'Australia', flag: '🇦🇺', code: '+61' },
];
export default function SelectExample() {
const [country, setCountry] = useState();
return (
);
}
```
## API Reference
### Select
| prop | type | default | description |
| -------------------------- | ------------------------------- | ------- | ---------------------------------------------------------------------- |
| `children` | `ReactNode` | - | The content of the select |
| `value` | `SelectOption` | - | The selected value (controlled mode) |
| `onValueChange` | `(value: SelectOption) => void` | - | Callback when the value changes |
| `defaultValue` | `SelectOption` | - | The default selected value (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 |
| `closeDelay` | `number` | `400` | Delay in milliseconds before closing the select |
| `isDisabled` | `boolean` | `false` | Whether the select is disabled |
| `isDismissKeyboardOnClose` | `boolean` | `true` | Whether to dismiss keyboard when select closes |
| `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 |
| ---------------- | ------------------------------------------------ | ------- | ---------------------------------------------- |
| `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 |
| ------------------- | ---------------- | ------- | ------------------------------------------------------- |
| `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 |
### 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 |
### Select.Portal
| prop | type | default | description |
| -------------- | ----------- | ------- | -------------------------------------------------- |
| `children` | `ReactNode` | - | The portal content (required) |
| `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 |
| `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
* `object`: Custom animation configuration
| prop | type | default | description |
| --------------- | -------------------------- | ----------- | ----------------------------------- |
| `opacity.value` | `[number, number, number]` | `[0, 1, 0]` | Opacity values \[idle, open, close] |
### 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 animations
* `object`: Custom animation configuration
| prop | type | default | description |
| ----------------------- | -------------------------- | ------------------ | -------------------------------------- |
| `opacity.value` | `[number, number, number]` | `[0, 1, 0]` | Opacity values \[idle, open, close] |
| `scale.value` | `[number, number, number]` | `[0.95, 1, 0.95]` | Scale values \[idle, open, close] |
| `translateX.value` | `[number, number, number]` | Based on placement | TranslateX values \[idle, open, close] |
| `translateY.value` | `[number, number, number]` | Based on placement | TranslateY values \[idle, open, close] |
| `transformOrigin.value` | `string` | Based on placement | Transform origin value |
### Select.Content (Bottom Sheet Presentation)
| prop | type | default | description |
| -------------------------- | ------------------ | ------- | ------------------------------------------------ |
| `children` | `ReactNode` | - | The bottom sheet content |
| `presentation` | `'bottom-sheet'` | - | Presentation mode for the select |
| `bottomSheetViewClassName` | `string` | - | Additional CSS classes for the bottom sheet view |
| `...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 |
| `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 |
| `...Animated.ViewProps` | `Animated.ViewProps` | - | All Reanimated Animated.View props are supported |
#### SelectContentAnimation
Animation configuration for Select.Content component (dialog presentation). Can be:
* `false` or `"disabled"`: Disable all animations
* `true` or `undefined`: Use default animations
* `object`: Custom animation configuration
| prop | type | default | description |
| --------------- | -------------------------- | ----------------- | ----------------------------------- |
| `opacity.value` | `[number, number, number]` | `[0, 1, 0]` | Opacity values \[idle, open, close] |
| `scale.value` | `[number, number, number]` | `[0.97, 1, 0.97]` | Scale values \[idle, open, close] |
### Select.Close
| prop | type | default | description |
| ------------------- | ---------------------- | ------- | ------------------------------------------------------- |
| `children` | `ReactNode` | - | The close button content |
| `className` | `string` | - | Additional CSS classes for the close button |
| `iconProps` | `SelectCloseIconProps` | - | Close icon configuration |
| `asChild` | `boolean` | - | Whether to render as a child element |
| `...PressableProps` | `PressableProps` | - | All standard React Native Pressable props are supported |
#### SelectCloseIconProps
| prop | type | default | description |
| ------- | -------- | ---------------- | ----------------- |
| `size` | `number` | `18` | Size of the icon |
| `color` | `string` | `--colors-muted` | Color of the icon |
### 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,
triggerPosition,
setTriggerPosition,
contentLayout,
setContentLayout,
nativeID,
closeDelay,
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 |
| `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 |
| `closeDelay` | `number \| undefined` | Delay in milliseconds before the select closes |
| `value` | `SelectOption` | Currently selected option |
| `onValueChange` | `(option: 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 |
| ---------------------------------- | ----------------------------- | ---------------------------------------------------------- |
| `selectState` | `'idle' \| 'open' \| 'close'` | Extended internal state for coordinating animations |
| `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 |
# 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/(forms)/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 && (
)}
);
}
```
## 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 |
| `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 |
| ------------------------------ | ------------------ | -------------------------------------------------------------- | ----------------------------------------------- |
| `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 |
| `...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 |
| ------------------------------ | ------------------ | -------------------------------------------------------------- | ----------------------------------------------------------------------- |
| `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 FormField
The Switch component integrates seamlessly with FormField for press state sharing:
```tsx
Enable notificationsReceive push notifications
```
When wrapped in FormField, the Switch will automatically respond to press events on the entire FormField container, creating a larger touch target and better user experience.
# 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
* **TextField.Label**: Label with optional asterisk for required fields
* **TextField.Input**: Input container with animated border and background
* **TextField.InputStartContent**: Optional content at the start of the input
* **TextField.InputEndContent**: Optional content at the end of the input
* **TextField.Description**: Helper text displayed below the input
* **TextField.ErrorMessage**: Error message shown when field is invalid
## Usage
### Basic Usage
TextField provides a complete form input structure with label and description.
```tsx
EmailWe'll never share your email
```
### With Required Field
Mark fields as required to show an asterisk in the label.
```tsx
Username
```
### With Start and End Content
Add icons or other content at the beginning or end of the input.
```tsx
Password......
```
### With Validation
Display error messages when the field is invalid.
```tsx
EmailPlease enter a valid email
```
### With Local Invalid State Override
Override the context's invalid state for individual components.
```tsx
Email
This shows despite input being invalid
Email format is incorrect
```
### Multiline Input
Create text areas for longer content.
```tsx
MessageMaximum 500 characters
```
### Disabled State
Disable the entire field to prevent interaction.
```tsx
Disabled Field
```
### Custom Colors
Customize the input colors for different states using the animation prop.
```tsx
Custom Styled
```
## Example
```tsx
import { Ionicons } from '@expo/vector-icons';
import { TextField, useThemeColor } from 'heroui-native';
import React from 'react';
import { ScrollView, View } from 'react-native';
export default function TextFieldExample() {
const themeColorMuted = useThemeColor('muted');
const [email, setEmail] = React.useState('');
const isInvalidEmail =
email !== '' && !/^[^\s@]+@[^\s@]+\.[^\s@]+$/.test(email);
return (
Email Address
We'll send a confirmation to this email
Please enter a valid email address
PasswordBio
Brief description for your profile
);
}
```
## 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 |
### TextField.Label
| prop | type | default | description |
| --------------------- | -------------------------- | ----------- | ------------------------------------------------------------ |
| children | `React.ReactNode` | - | Label text content |
| isInvalid | `boolean` | `undefined` | Whether the label is in an invalid state (overrides context) |
| className | `string` | - | Custom class name for the label element |
| classNames | `ElementSlots` | - | Custom class names for different parts of the label |
| animation | `TextFieldLabelAnimation` | - | Animation configuration |
| ...Animated.TextProps | `AnimatedProps` | - | All Reanimated Animated.Text props are supported |
#### `ElementSlots`
| prop | type | description |
| -------- | -------- | ------------------------------------ |
| text | `string` | Custom class name for the label text |
| asterisk | `string` | Custom class name for the asterisk |
#### TextFieldLabelAnimation
Animation configuration for TextField.Label component. Can be:
* `false` or `"disabled"`: Disable all animations
* `true` or `undefined`: Use default animations
* `object`: Custom animation configuration
| prop | type | default | description |
| ---------------- | ----------------------- | ----------------------------------------------------------------------- | ------------------------- |
| `entering.value` | `EntryOrExitLayoutType` | `FadeIn` `.duration(150)` `.easing(Easing.out(Easing.ease))` | Custom entering animation |
| `exiting.value` | `EntryOrExitLayoutType` | `FadeOut` `.duration(150)` `.easing(Easing.out(Easing.ease))` | Custom exiting animation |
### TextField.Input
| prop | type | default | description |
| ----------------- | -------------------------- | ----------- | ------------------------------------------------------------ |
| children | `React.ReactNode` | - | Content to render inside the input container |
| isInvalid | `boolean` | `undefined` | Whether the input is in an invalid state (overrides context) |
| className | `string` | - | Custom class name for the input container |
| classNames | `ElementSlots` | - | Custom class names for different parts of the input |
| animation | `TextFieldInputAnimation` | - | Animation configuration |
| ...TextInputProps | `TextInputProps` | - | All standard React Native TextInput props are supported |
#### `ElementSlots`
| prop | type | description |
| --------- | -------- | -------------------------------------------- |
| container | `string` | Custom class name for the input container |
| input | `string` | Custom class name for the text input element |
#### TextFieldInputAnimation
Animation configuration for TextField.Input component. Can be:
* `false` or `"disabled"`: Disable all animations
* `true` or `undefined`: Use default animations
* `object`: Custom animation configuration
| prop | type | default | description |
| --------------------------------------------- | ------------------ | ---------------------------------------------------- | --------------------------------------------------------------- |
| `backgroundColor` `.value` `.blur` | `string` | Uses theme color | Background color when input is blurred |
| `backgroundColor` `.value` `.focus` | `string` | Uses theme color | Background color when input is focused |
| `backgroundColor` `.value` `.error` | `string` | Uses theme color | Background color when input is invalid |
| `backgroundColor` `.timingConfig` | `WithTimingConfig` | `{ duration: 150, easing: Easing.out(Easing.ease) }` | Animation timing configuration for background color transitions |
| `borderColor` `.value` `.blur` | `string` | Uses theme color | Border color when input is blurred |
| `borderColor` `.value` `.focus` | `string` | Uses theme color | Border color when input is focused |
| `borderColor` `.value` `.error` | `string` | Uses theme color | Border color when input is invalid |
| `borderColor` `.timingConfig` | `WithTimingConfig` | `{ duration: 150, easing: Easing.out(Easing.ease) }` | Animation timing configuration for border color transitions |
### TextField.InputStartContent
| prop | type | default | description |
| ------------ | ----------------- | ------- | -------------------------------------------------- |
| children | `React.ReactNode` | - | Content to render at the start of the input |
| className | `string` | - | Custom class name for the start content element |
| ...ViewProps | `ViewProps` | - | All standard React Native View props are supported |
### TextField.InputEndContent
| prop | type | default | description |
| ------------ | ----------------- | ------- | -------------------------------------------------- |
| children | `React.ReactNode` | - | Content to render at the end of the input |
| className | `string` | - | Custom class name for the end content element |
| ...ViewProps | `ViewProps` | - | All standard React Native View props are supported |
### TextField.Description
| prop | type | default | description |
| --------------------- | ------------------------------- | ----------- | ------------------------------------------------------------------ |
| children | `React.ReactNode` | - | Description text content |
| isInvalid | `boolean` | `undefined` | Whether the description is in an invalid state (overrides context) |
| className | `string` | - | Custom class name for the description element |
| animation | `TextFieldDescriptionAnimation` | - | Animation configuration |
| ...Animated.TextProps | `AnimatedProps` | - | All Reanimated Animated.Text props are supported |
#### TextFieldDescriptionAnimation
Animation configuration for TextField.Description component. Can be:
* `false` or `"disabled"`: Disable all animations
* `true` or `undefined`: Use default animations
* `object`: Custom animation configuration
| prop | type | default | description |
| ---------------- | ----------------------- | ----------------------------------------------------------------------- | ------------------------- |
| `entering.value` | `EntryOrExitLayoutType` | `FadeIn` `.duration(150)` `.easing(Easing.out(Easing.ease))` | Custom entering animation |
| `exiting.value` | `EntryOrExitLayoutType` | `FadeOut` `.duration(150)` `.easing(Easing.out(Easing.ease))` | Custom exiting animation |
### TextField.ErrorMessage
> **Note**: `TextField.ErrorMessage` extends `ErrorView` component. For complete API reference, see [ErrorView documentation](error-view).
## 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.
);
}
```
## API Reference
### Card
| prop | type | default | description |
| -------------- | ------------------------------------------------------------------------- | ----------- | ----------------------------------------------------------------------------------------- |
| `children` | `React.ReactNode` | - | Content to be rendered inside the card |
| `variant` | `'default' \| 'secondary' \| 'tertiary' \| 'quaternary' \| '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 |
# Divider
**Category**: native
**URL**: https://v3.heroui.com/docs/native/components/divider
**Source**: https://raw.githubusercontent.com/heroui-inc/heroui/refs/heads/v3/apps/docs/content/docs/native/components/(layout)/divider.mdx
> A simple line to separate content visually.
## Import
```tsx
import { Divider } from 'heroui-native';
```
## Anatomy
```tsx
```
* **Divider**: A simple line component that separates content visually. Can be oriented horizontally or vertically, with customizable thickness and variant styles.
## Usage
### Basic Usage
The Divider component creates a visual separation between content sections.
```tsx
```
### Orientation
Control the direction of the divider with the `orientation` prop.
```tsx
Horizontal dividerContent 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 { Divider, Surface } from 'heroui-native';
import { Text, View } from 'react-native';
export default function DividerExample() {
return (
HeroUI Native
A modern React Native component library.
ComponentsThemesExamples
);
}
```
## API Reference
### Divider
| prop | type | default | description |
| -------------- | ---------------------------- | -------------- | -------------------------------------------------------------------------------------------- |
| `variant` | `'thin' \| 'thick'` | `'thin'` | Variant style of the divider |
| `orientation` | `'horizontal' \| 'vertical'` | `'horizontal'` | Orientation of the divider |
| `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.
Surface Content
This is a quaternary surface variant. It uses bg-surface-quaternary
styling.
);
}
```
## API Reference
### Surface
| prop | type | default | description |
| -------------- | ------------------------------------------------------------------------- | ----------- | ----------------------------------------------------------------------------------------- |
| `variant` | `'default' \| 'secondary' \| 'tertiary' \| 'quaternary' \| '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('')}
))}
);
}
```
## 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 |
| `...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 |
| ---------------------- | ------------------ | --------------------------------------------------- | ----------------------------------------------------- |
| `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 |
| `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`.
#### 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 |
| ---------------- | ----------------------- | -------------------------------------------------------------------------------------- | -------------------------------------- |
| `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 Dividers
Hide the dividers between accordion items.
```tsx
............
```
### With PressableFeedback
Wrap `Accordion.Trigger` with `PressableFeedback` to add custom press feedback animations.
```tsx
import { Accordion, PressableFeedback } from 'heroui-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}
))}
);
}
```
## 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 |
| `isDividerVisible` | `boolean` | `true` | Whether to display a divider at the bottom of each accordion item |
| `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 |
| `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 |
| `divider` | `string` | Custom class name for the divider 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 |
| -------------- | ------------------ | --------------------------------------------------------------------------------------------------- | ------------------------------------------------- |
| `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 |
| `...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 |
| ----------------------- | ------------------ | -------------------------------------------- | ------------------------------------------------- |
| `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 |
| ---------------- | ----------------------- | ---------------------------------------------------------------------- | ------------------------------------- |
| `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.
# 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 (pill or line).
* **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.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......
```
### Pill Variant
Default rounded pill style for tab triggers.
```tsx
SettingsProfile......
```
### Line 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
>
)}
......
```
## Example
```tsx
import { Tabs, TextField, FormField, Checkbox, Button } 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 (
GeneralNotificationsProfileShow sidebar
Display the sidebar navigation panel
Account activity
Notifications about your account activity
Name
);
}
```
## API Reference
### Tabs
| prop | type | default | description |
| --------------- | ---------------------------- | ----------- | ----------------------------------------------------------------------------------------- |
| `children` | `React.ReactNode` | - | Children elements to be rendered inside tabs |
| `value` | `string` | - | Currently active tab value |
| `variant` | `'pill' \| 'line'` | `'pill'` | 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 |
| `...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 |
| --------------- | -------------------------------------- | ---------------------------------------------------------------------------- | ---------------------------------- |
| `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 |
| `left.type` | `'spring' \| 'timing'` | `'spring'` | Type of animation to use |
| `left.config` | `WithSpringConfig \| WithTimingConfig` | `{ stiffness: 1200, damping: 120 }` (spring) or `{ duration: 200 }` (timing) | Reanimated animation 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` | `'pill' \| 'line'` | 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.
# 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, useDialog, useDialogAnimation } 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 that dismisses the dialog when pressed.
* **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
```
### Custom Animations
Configure open and close animations with spring or timing. The `closeDelay` should typically match your closing animation duration.
```tsx
```
### Custom Backdrop
Replace the default overlay with custom content.
```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 (
);
}
```
## 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 |
| `closeDelay` | `number` | `300` | Delay in milliseconds before dialog closes (should match closing animation duration) |
| `isDismissKeyboardOnClose` | `boolean` | `true` | Whether to dismiss keyboard when dialog closes |
| `animation` | `DialogRootAnimation` | - | Animation configuration |
| `onOpenChange` | `(value: boolean) => void` | - | Callback when open state changes |
| `...ViewProps` | `ViewProps` | - | All standard React Native View props are supported |
#### DialogRootAnimation
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
* `object`: Custom animation configuration
| prop | type | default | description |
| ---------------- | ------------------------------------------------ | -------------------------------------------------------------------------------------------------- | ----------------------------------- |
| `entering.value` | `SpringAnimationConfig \| TimingAnimationConfig` | `{ type: 'timing',` `config: { duration: 200,` `easing: Easing.out(Easing.ease) } }` | Animation configuration for opening |
| `exiting.value` | `SpringAnimationConfig \| TimingAnimationConfig` | `{ type: 'timing',` `config: { duration: 150,` `easing: Easing.bezier(0.4, 0, 1, 1) } }` | Animation configuration for closing |
#### 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 |
### Dialog.Trigger
| prop | type | default | description |
| ------------------- | ----------------- | ------- | ------------------------------------------------------------ |
| `children` | `React.ReactNode` | - | Trigger element content |
| `asChild` | `boolean` | - | Render as child element without wrapper |
| `...PressableProps` | `PressableProps` | - | All standard React Native PressableProps props are supported |
### Dialog.Portal
| prop | type | default | description |
| ------------ | ---------------------- | ------- | ------------------------------------------------ |
| `children` | `React.ReactNode` | - | Portal content (overlay and dialog) |
| `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 |
| `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 |
| --------------- | -------------------------- | ----------- | ----------------------------------- |
| `opacity.value` | `[number, number, number]` | `[0, 1, 0]` | Opacity values \[idle, open, close] |
### 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 |
| `onLayout` | `(event: LayoutChangeEvent) => void` | - | Layout event handler |
| `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 |
| --------------- | -------------------------- | ----------------- | ----------------------------------- |
| `opacity.value` | `[number, number, number]` | `[0, 1, 0]` | Opacity values \[idle, open, close] |
| `scale.value` | `[number, number, number]` | `[0.97, 1, 0.97]` | Scale values \[idle, open, close] |
### Dialog.Close
| prop | type | default | description |
| -------------------------- | ----------------------- | ------- | -------------------------------------------------------------- |
| `children` | `React.ReactNode` | - | Custom close button content |
| `className` | `string` | - | Additional CSS classes for close button |
| `iconProps` | `DialogCloseIconProps` | - | Configuration for default close icon |
| `hitSlop` | `number` | `12` | Hit slop area for the close button |
| `asChild` | `boolean` | - | Render as child element without wrapper |
| `...TouchableOpacityProps` | `TouchableOpacityProps` | - | All standard React Native TouchableOpacity props are supported |
#### DialogCloseIconProps
| prop | type | description |
| ------- | -------- | --------------------------------------- |
| `size` | `number` | Icon size (default: 18) |
| `color` | `string` | Icon color (default: theme color muted) |
### 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 { dialogState, progress, isDragging, isGestureReleaseAnimationRunning } =
useDialogAnimation();
```
| property | type | description |
| ---------------------------------- | ----------------------------- | -------------------------------------------- |
| `dialogState` | `'idle' \| 'open' \| 'close'` | Internal dialog state |
| `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 |
# 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 that dismisses the popover when pressed. Renders a default X icon if no children provided.
* **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
...
...
```
### 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.
```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.
);
}
```
## 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 |
| `closeDelay` | `number` | `400` | Delay in milliseconds before closing the popover |
| `animation` | `PopoverRootAnimation` | - | Animation configuration |
| `asChild` | `boolean` | `false` | Whether to render as a child element |
| `...ViewProps` | `ViewProps` | - | All standard React Native View props are supported |
#### PopoverRootAnimation
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
* `object`: Custom animation configuration
| prop | type | default | description |
| ---------------- | ------------------------------------------------ | -------------------------------------------------------------------------------------------------- | ----------------------------------- |
| `entering.value` | `SpringAnimationConfig \| TimingAnimationConfig` | `{ type: 'timing',` `config: { duration: 200,` `easing: Easing.out(Easing.ease) } }` | Animation configuration for opening |
| `exiting.value` | `SpringAnimationConfig \| TimingAnimationConfig` | `{ type: 'timing',` `config: { duration: 150,` `easing: Easing.bezier(0.4, 0, 1, 1) } }` | Animation configuration for closing |
#### 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 |
### 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) |
| `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 |
| `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 |
| --------------- | -------------------------- | ----------- | ----------------------------------- |
| `opacity.value` | `[number, number, number]` | `[0, 1, 0]` | Opacity values \[idle, open, close] |
### Popover.Content (Popover Presentation)
| prop | type | default | description |
| ------------------------- | ------------------------------------------------ | --------------- | ------------------------------------------------------ |
| `children` | `ReactNode` | - | The popover content |
| `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` | `8` | 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 |
| `presentation` | `'popover'` | - | Presentation mode for the popover |
| `animation` | `PopupPopoverContentAnimation` | - | Animation configuration |
| `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 for the popover |
| `bottomSheetViewClassName` | `string` | - | Additional CSS classes for the bottom sheet view |
| `bottomSheetViewProps` | `BottomSheetViewProps` | - | Props for the bottom sheet view |
| `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 |
| ----------------------- | -------------------------- | ---------------------------------------------------------------- | -------------------------------------- |
| `opacity.value` | `[number, number, number]` | `[0, 1, 0]` | Opacity values \[idle, open, close] |
| `scale.value` | `[number, number, number]` | `[0.95, 1, 0.95]` | Scale values \[idle, open, close] |
| `translateX.value` | `[number, number, number]` | Based on placement `(4, 0, 4)` or `(-4, 0, -4)` | TranslateX values \[idle, open, close] |
| `translateY.value` | `[number, number, number]` | Based on placement `(4, 0, 4)` or `(-4, 0, -4)` | TranslateY values \[idle, open, close] |
| `transformOrigin.value` | `string` | Based on placement `'top'`, `'bottom'`, `'left'`, `'right'` | Transform origin value |
### Popover.Arrow
| prop | type | default | description |
| --------------------- | ---------------------------------------- | ------- | --------------------------------------------------------------------- |
| `className` | `string` | - | Additional CSS classes for the arrow |
| `height` | `number` | `8` | Height of the arrow in pixels |
| `width` | `number` | `16` | 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
| prop | type | default | description |
| ------------------- | ----------------------- | ------- | ------------------------------------------------------- |
| `children` | `ReactNode` | - | The close button content |
| `className` | `string` | - | Additional CSS classes for the close button |
| `iconProps` | `PopoverCloseIconProps` | - | Close icon configuration |
| `hitSlop` | `number \| Insets` | `12` | Additional touch area around the button |
| `asChild` | `boolean` | - | Whether to render as a child element |
| `...PressableProps` | `PressableProps` | - | All standard React Native Pressable props are supported |
#### PopoverCloseIconProps
| prop | type | default | description |
| ------- | -------- | ---------------- | ----------------- |
| `size` | `number` | `18` | Size of the icon |
| `color` | `string` | `--colors.muted` | Color of the icon |
### 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 |
| `closeDelay` | `number \| undefined` | Delay in milliseconds before the popover closes |
**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 { popoverState, progress, isDragging } = usePopoverAnimation();
// ... your implementation
};
```
**Returns:** `UsePopoverAnimationReturn`
| property | type | description |
| -------------- | ----------------------------- | ------------------------------------------------------------------ |
| `popoverState` | `'idle' \| 'open' \| 'close'` | Extended internal state for coordinating animations |
| `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.
# 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 (
);
}
```
## 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 |
| `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 |
| ------------------------- | ----------------------- | ---------------------------------------------------------------------------------------------------------------------------- | -------------------------------------------------------------------------------- |
| `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 |
| `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
### Styling Notes
#### Border as Padding
Toast uses `border-[16px]` class which serves as padding. This is intentional because when visible toasts have different heights, the toast adapts to the last visible toast height. In cases where a toast originally has one height and gets smaller when a new toast comes to stack, content might be visible behind the last toast without proper padding. The border ensures consistent spacing regardless of toast height changes.
For padding, use `border` classes. For actual borders, use `outline` classes.
# 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';
```
## Usage
### Basic Usage
The PressableFeedback component wraps content to provide press feedback effects. By default, it applies a subtle scale animation when pressed.
```tsx
...
```
### Highlight Variant
Default iOS-style highlight feedback effect with automatic scale animation.
```tsx
...
```
### Ripple Variant
Android-style ripple feedback effect that emanates from the press point, combined with scale animation.
```tsx
...
```
### Custom Highlight Animation
Configure highlight overlay opacity and background color while maintaining the default scale effect.
```tsx
...
```
### Custom Ripple Animation
Configure ripple effect color, opacity, and duration along with scale animation.
```tsx
...
```
### Feedback Position
Control whether the feedback effect renders above or below content.
```tsx
...
...
```
### Custom Scale Animation
Customize or disable the default scale animation on press.
```tsx
...
...
```
### Disabled State
Disable press interactions and all feedback animations.
```tsx
...
```
## Example
```tsx
import { PressableFeedback, Card } from 'heroui-native';
import { View, Text, Image } from 'react-native';
export default function PressableFeedbackExample() {
return (
Indie Hackers
148 members
@indiehackers
AI Builders
362 members
@aibuilders
);
}
```
## API Reference
### PressableFeedback
| prop | type | default | description |
| ------------------ | --------------------------------------------------------------------------------- | ------------- | -------------------------------------------------------------------- |
| `children` | `React.ReactNode` | - | Content to be wrapped with press feedback |
| `feedbackVariant` | `'highlight' \| 'ripple'` | `'highlight'` | Type of feedback effect to display |
| `feedbackPosition` | `'behind' \| 'top'` | `'top'` | Controls z-index positioning of feedback effect relative to children |
| `isDisabled` | `boolean` | `false` | Whether the pressable component is disabled |
| `className` | `string` | - | Additional CSS classes |
| `animation` | `PressableFeedbackHighlightRootAnimation \| PressableFeedbackRippleRootAnimation` | - | Animation configuration |
| `...AnimatedProps` | `AnimatedProps` | - | All Reanimated Animated Pressable props are supported |
#### PressableFeedbackHighlightRootAnimation
Animation configuration for PressableFeedback component with highlight variant. 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 |
| ------------------------------------------------- | ------------------ | ---------------------------------------------------- | -------------------------------------------------------------------------- |
| `scale` `.value` | `number` | `0.985` | Scale value when pressed (automatically adjusted based on container width) |
| `scale` `.timingConfig` | `WithTimingConfig` | `{ duration: 300, easing: Easing.out(Easing.ease) }` | Animation timing configuration |
| `scale` `.ignoreScaleCoefficient` | `boolean` | `false` | Ignore automatic scale coefficient and use the scale value directly |
| `highlight` `.opacity` `.value` | `[number, number]` | `[0, 0.1]` | Opacity values \[unpressed, pressed] |
| `highlight` `.opacity` `.timingConfig` | `WithTimingConfig` | `{ duration: 200 }` | Animation timing configuration |
| `highlight` `.backgroundColor` `.value` | `string` | Computed based on theme | Background color of highlight overlay |
#### PressableFeedbackRippleRootAnimation
Animation configuration for PressableFeedback component with ripple variant. 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 |
| ----------------------------------------------------------- | -------------------------- | ---------------------------------------------------- | ---------------------------------------------------------------------------- |
| `scale` `.value` | `number` | `0.985` | Scale value when pressed (automatically adjusted based on container width) |
| `scale` `.timingConfig` | `WithTimingConfig` | `{ duration: 300, easing: Easing.out(Easing.ease) }` | Animation timing configuration |
| `scale` `.ignoreScaleCoefficient` | `boolean` | `false` | Ignore automatic scale coefficient and use the scale value directly |
| `ripple` `.backgroundColor` `.value` | `string` | Computed based on theme | Background color of ripple effect |
| `ripple` `.progress` `.baseDuration` | `number` | `1000` | Base duration for ripple progress (automatically adjusted based on diagonal) |
| `ripple` `.progress` `.minBaseDuration` | `number` | - | Minimum base duration for the ripple progress animation |
| `ripple` `.progress` `.ignoreDurationCoefficient` | `boolean` | `false` | Ignore automatic duration coefficient and use base duration directly |
| `ripple` `.opacity` `.value` | `[number, number, number]` | `[0, 0.1, 0]` | Opacity values \[start, peak, end] for ripple animation |
| `ripple` `.opacity` `.timingConfig` | `WithTimingConfig` | `{ duration: 30 }` | Animation timing configuration |
| `ripple` `.scale` `.value` | `[number, number, number]` | `[0, 1, 1]` | Scale values \[start, peak, end] for ripple animation |
| `ripple` `.scale` `.timingConfig` | `WithTimingConfig` | `{ duration: 30 }` | Animation timing configuration |
# 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.
);
}
```
## 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 |
| --------------- | ------------------ | -------- | ------------------------------------------------------------------------------------ |
| `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.
# 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 } 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
```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
Ghost
Danger
);
}
```
### Sizes
```tsx
import {Button, ButtonGroup} from "@heroui/react";
export function Sizes() {
return (
Small
Medium (default)
Large
);
}
```
### 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
```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 } 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;
}
}
```
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
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
Separators are automatically added between buttons using a pseudo-element (`:before`) on buttons that are not the first child.
## 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 |
| `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) |
| `hideSeparator` | `boolean` | `false` | Hide separator lines between buttons |
| `className` | `string` | - | Additional CSS classes |
| `children` | `React.ReactNode` | - | Button components to group together |
### Notes
* ButtonGroup uses React Context to pass `size`, `variant`, and `isDisabled` props to all child Button components
* Individual Button components can override the group's `isDisabled` prop by setting `isDisabled={false}`
* The component automatically handles border radius and separators 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 (
);
}
```
## 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 (
);
}
```
### 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;
}
```
### 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--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' \| '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 |
### 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 |
# Dropdown
**Category**: react
**URL**: https://v3.heroui.com/docs/react/components/dropdown
**Source**: https://raw.githubusercontent.com/heroui-inc/heroui/refs/heads/v3/apps/docs/content/docs/react/components/(collections)/dropdown.mdx
> A dropdown displays a list of actions or options that a user can choose
## Import
```tsx
import { Dropdown } from '@heroui/react';
```
### Usage
```tsx
"use client";
import {Button, Dropdown, Label} from "@heroui/react";
export function Default() {
return (
console.log(`Selected: ${key}`)}>
);
}
```
### Anatomy
Import the Dropdown component and access all parts using dot notation.
```tsx
import { Dropdown, Button, Label, Description, Header, Kbd, Separator } from '@heroui/react';
export default () => (
)
```
### With Single Selection
```tsx
"use client";
import type {Selection} from "@heroui/react";
import {Button, Dropdown, Header, Label} from "@heroui/react";
import {useState} from "react";
export function WithSingleSelection() {
const [selected, setSelected] = useState(new Set(["apple"]));
return (
Select a fruit
);
}
```
### Single With Custom Indicator
```tsx
"use client";
import type {Selection} from "@heroui/react";
import {Button, Dropdown, Header, Label} from "@heroui/react";
import {useState} from "react";
export function SingleWithCustomIndicator() {
const [selected, setSelected] = useState(new Set(["apple"]));
const CustomCheckmarkIcon = (
);
return (
Select a fruit
{({isSelected}) => (isSelected ? CustomCheckmarkIcon : null)}
{({isSelected}) => (isSelected ? CustomCheckmarkIcon : null)}
{({isSelected}) => (isSelected ? CustomCheckmarkIcon : null)}
{({isSelected}) => (isSelected ? CustomCheckmarkIcon : null)}
{({isSelected}) => (isSelected ? CustomCheckmarkIcon : null)}
);
}
```
### With Multiple Selection
```tsx
"use client";
import type {Selection} from "@heroui/react";
import {Button, Dropdown, Header, Label} from "@heroui/react";
import {useState} from "react";
export function WithMultipleSelection() {
const [selected, setSelected] = useState(new Set(["apple"]));
return (
Select a fruit
);
}
```
### With Section Level Selection
```tsx
"use client";
import type {Selection} from "@heroui/react";
import {Button, Dropdown, Header, Kbd, Label, Separator} from "@heroui/react";
import {useState} from "react";
export function WithSectionLevelSelection() {
const [textStyles, setTextStyles] = useState(new Set(["bold", "italic"]));
const [textAlignment, setTextAlignment] = useState(new Set(["left"]));
return (
ActionsXCUText StyleBIUText AlignmentAHD
);
}
```
### With Keyboard Shortcuts
```tsx
"use client";
import {Button, Dropdown, Kbd, Label} from "@heroui/react";
export function WithKeyboardShortcuts() {
return (
console.log(`Selected: ${key}`)}>
NOSD
);
}
```
### With Icons
```tsx
"use client";
import {FloppyDisk, FolderOpen, SquarePlus, TrashBin} from "@gravity-ui/icons";
import {Button, Dropdown, Kbd, Label} from "@heroui/react";
export function WithIcons() {
return (
console.log(`Selected: ${key}`)}>
NOSD
);
}
```
### Long Press Trigger
```tsx
import {Button, Dropdown, Label} from "@heroui/react";
export function LongPressTrigger() {
return (
);
}
```
### With Descriptions
```tsx
"use client";
import {FloppyDisk, FolderOpen, SquarePlus, TrashBin} from "@gravity-ui/icons";
import {Button, Description, Dropdown, Kbd, Label} from "@heroui/react";
export function WithDescriptions() {
return (
console.log(`Selected: ${key}`)}>
);
}
```
### 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}
);
})}
)}
);
}
```
## 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 with field-on-background styling
* `.tag--surface` - Surface variant with surface background
* `.tag--on-surface` - On-surface variant for use on surface components
#### Modifier Classes
* `.tag__remove-button--on-surface` - Remove button modifier for on-surface variant
#### 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 |
| `isOnSurface` | `boolean` | - | Whether tags are displayed on a surface component |
| `className` | `string` | - | Additional CSS classes |
| `children` | `ReactNode \| RenderFunction` | - | TagGroup content or 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 |
### 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 |
**Note**: `size`, `variant`, and `isOnSurface` 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) |
### 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 |
# 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 (
);
}
```
## 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 |
### Slider.Output Props
| Prop | Type | Default | Description |
| ----------- | ----------------------------- | ------- | --------------------------------- |
| `className` | `string` | - | Additional CSS classes |
| `children` | `ReactNode \| RenderFunction` | - | Output content or render function |
### Slider.Track Props
| Prop | Type | Default | Description |
| ----------- | ----------------------------- | ------- | -------------------------------- |
| `className` | `string` | - | Additional CSS classes |
| `children` | `ReactNode \| RenderFunction` | - | Track content or 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 |
### 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 } 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 (
);
}
```
### With Description
```tsx
import {Description, Label, Switch} from "@heroui/react";
export function WithDescription() {
return (
Allow others to see your profile information
);
}
```
### Group
```tsx
import {Label, Switch, SwitchGroup} from "@heroui/react";
export function Group() {
return (
);
}
```
### Group Horizontal
```tsx
import {Label, Switch, SwitchGroup} from "@heroui/react";
export function GroupHorizontal() {
return (
);
}
```
### Render Props
```tsx
"use client";
import {Label, Switch} from "@heroui/react";
export function RenderProps() {
return (
{({isSelected}) => (
<>
>
)}
);
}
```
### Form Integration
```tsx
"use client";
import {Button, Label, Switch, SwitchGroup} from "@heroui/react";
import React from "react";
export function Form() {
const handleSubmit = (e: React.FormEvent) => {
e.preventDefault();
const formData = new FormData(e.target as HTMLFormElement);
alert(
`Form submitted with:\n${Array.from(formData.entries())
.map(([key, value]) => `${key}: ${value}`)
.join("\n")}`,
);
};
return (
);
}
```
### Custom Styles
```tsx
"use client";
import {Check, Power} from "@gravity-ui/icons";
import {Switch} from "@heroui/react";
export function CustomStyles() {
return (
{({isSelected}) => (
<>
{isSelected ? (
) : (
)}
>
)}
);
}
```
## Related Components
* **Label**: Accessible label for form controls
* **Description**: Helper text for form fields
* **Button**: Allows a user to perform an action
## Styling
### Passing Tailwind CSS classes
You can customize individual Switch components:
```tsx
import { Switch, Label } from '@heroui/react';
function CustomSwitch() {
return (
{({isSelected}) => (
<>
>
)}
);
}
```
Or customize the SwitchGroup layout:
```tsx
import { Switch, SwitchGroup, Label } from '@heroui/react';
function CustomSwitchGroup() {
return (
);
}
```
### Customizing the component classes
To customize the Switch component classes, you can use the `@layer components` directive.
[Learn more](https://tailwindcss.com/docs/adding-custom-styles#adding-component-classes).
```css
@layer components {
.switch {
@apply inline-flex gap-3 items-center;
}
.switch__control {
@apply h-5 w-8 bg-gray-400 data-[selected=true]:bg-blue-500;
}
.switch__thumb {
@apply bg-white shadow-sm;
}
.switch__icon {
@apply h-3 w-3 text-current;
}
}
```
HeroUI follows the [BEM](https://getbem.com/) methodology to ensure component variants and states are reusable and easy to customize.
### CSS Classes
#### Switch Classes
The Switch component uses these CSS classes ([View source styles](https://github.com/heroui-inc/heroui/blob/v3/packages/styles/components/switch.css)):
* `.switch` - Base switch container
* `.switch__control` - Switch control track
* `.switch__thumb` - Switch thumb that moves
* `.switch__icon` - Optional icon inside the thumb
* `.switch--sm` - Small size variant
* `.switch--md` - Medium size variant (default)
* `.switch--lg` - Large size variant
#### SwitchGroup Classes
The SwitchGroup component uses these CSS classes ([View source styles](https://github.com/heroui-inc/heroui/blob/v3/packages/styles/components/switch-group.css)):
* `.switch-group` - Switch group container
* `.switch-group__items` - Container for switch items
* `.switch-group--horizontal` - Horizontal layout
* `.switch-group--vertical` - Vertical layout (default)
### Interactive States
The switch supports both CSS pseudo-classes and data attributes for flexibility:
* **Selected**: `[data-selected="true"]` (thumb position and background color change)
* **Hover**: `:hover` or `[data-hovered="true"]`
* **Focus**: `:focus-visible` or `[data-focus-visible="true"]` (shows focus ring)
* **Disabled**: `:disabled` or `[aria-disabled="true"]` (reduced opacity, no pointer events)
* **Pressed**: `:active` or `[data-pressed="true"]`
## API Reference
### Switch Props
Inherits from [React Aria Switch](https://react-spectrum.adobe.com/react-aria/Switch.html).
| Prop | Type | Default | Description |
| ----------------- | ------------------------------------------------------------------- | ------- | ----------------------------------------------------------------- |
| `size` | `'sm' \| 'md' \| 'lg'` | `'md'` | The size of the switch |
| `isSelected` | `boolean` | `false` | Whether the switch is on |
| `defaultSelected` | `boolean` | `false` | Whether the switch is on by default (uncontrolled) |
| `isDisabled` | `boolean` | `false` | Whether the switch is disabled |
| `name` | `string` | - | The name of the input element, used when submitting an HTML form |
| `value` | `string` | - | The value of the input element, used when submitting an HTML form |
| `onChange` | `(isSelected: boolean) => void` | - | Handler called when the switch value changes |
| `onPress` | `(e: PressEvent) => void` | - | Handler called when the switch is pressed |
| `children` | `React.ReactNode \| (values: SwitchRenderProps) => React.ReactNode` | - | Switch content or render prop |
### SwitchRenderProps
When using the render prop pattern, these values are provided:
| Prop | Type | Description |
| ---------------- | --------- | --------------------------------------- |
| `isSelected` | `boolean` | Whether the switch is currently on |
| `isHovered` | `boolean` | Whether the switch is hovered |
| `isPressed` | `boolean` | Whether the switch is currently pressed |
| `isFocused` | `boolean` | Whether the switch is focused |
| `isFocusVisible` | `boolean` | Whether the switch is keyboard focused |
| `isDisabled` | `boolean` | Whether the switch is disabled |
| `isReadOnly` | `boolean` | Whether the switch is read only |
| `state` | `-` | State of the switch. |
### SwitchGroup Props
| Prop | Type | Default | Description |
| ------------- | ---------------------------- | ------------ | ----------------------------------- |
| `orientation` | `'horizontal' \| 'vertical'` | `'vertical'` | The orientation of the switch group |
| `children` | `React.ReactNode` | - | The switch items to render |
| `className` | `string` | - | Additional CSS class names |
# 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';
```
### 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 (
Information
Completed
Pending
Failed
Label
);
}
```
### Statuses
```tsx
import {Ban, Check, CircleFill, CircleInfo, TriangleExclamation} from "@gravity-ui/icons";
import {Chip} from "@heroui/react";
export function ChipStatuses() {
return (
Default
Active
Pending
Inactive
New Feature
Available
Beta
Deprecated
);
}
```
## Related Components
* **Avatar**: Display user profile images
* **CloseButton**: Button for dismissing overlays
* **Separator**: Visual divider between content
## Styling
### Passing Tailwind CSS classes
```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--accent {
@apply border-accent/20;
}
}
```
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 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 |
| `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 |
# Alert
**Category**: react
**URL**: https://v3.heroui.com/docs/react/components/alert
**Source**: https://raw.githubusercontent.com/heroui-inc/heroui/refs/heads/v3/apps/docs/content/docs/react/components/(feedback)/alert.mdx
> Display important messages and notifications to users with status indicators
## Import
```tsx
import { Alert } from '@heroui/react';
```
### Usage
```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.
);
}
```
### Anatomy
Import the Alert component and access all parts using dot notation.
```tsx
import { Alert } from '@heroui/react';
export default () => (
)
```
## Related Components
* **CloseButton**: Button for dismissing overlays
* **Button**: Allows a user to perform an action
* **Spinner**: Loading indicator
## Styling
### Passing Tailwind CSS classes
```tsx
import { Alert } from "@heroui/react";
function CustomAlert() {
return (
Custom Alert
This alert has custom styling applied
);
}
```
### Customizing the component classes
To customize the Alert component classes, you can use the `@layer components` directive.
[Learn more](https://tailwindcss.com/docs/adding-custom-styles#adding-component-classes).
```css
@layer components {
.alert {
@apply rounded-2xl shadow-lg;
}
.alert__title {
@apply font-bold text-lg;
}
.alert--danger {
@apply border-l-4 border-red-600;
}
}
```
HeroUI follows the [BEM](https://getbem.com/) methodology to ensure component variants and states are reusable and easy to customize.
### CSS Classes
The Alert component uses these CSS classes ([View source styles](https://github.com/heroui-inc/heroui/blob/v3/packages/styles/components/alert.css)):
#### Base Classes
* `.alert` - Base alert container
* `.alert__indicator` - Icon/indicator container
* `.alert__content` - Content wrapper for title and description
* `.alert__title` - Alert title text
* `.alert__description` - Alert description text
#### Status Variant Classes
* `.alert--default` - Default gray status
* `.alert--accent` - Accent blue status
* `.alert--success` - Success green status
* `.alert--warning` - Warning yellow/orange status
* `.alert--danger` - Danger red status
### Interactive States
The Alert component is primarily informational and doesn't have interactive states on the base component. However, it can contain interactive elements like buttons or close buttons.
## API Reference
### Alert Props
| Prop | Type | Default | Description |
| ----------- | ------------------------------------------------------------- | ----------- | ------------------------------ |
| `status` | `"default" \| "accent" \| "success" \| "warning" \| "danger"` | `"default"` | The visual status of the alert |
| `className` | `string` | - | Additional CSS classes |
| `children` | `ReactNode` | - | The alert content |
### Alert.Indicator Props
| Prop | Type | Default | Description |
| ----------- | ----------- | ------- | ----------------------------------------------- |
| `className` | `string` | - | Additional CSS classes |
| `children` | `ReactNode` | - | Custom indicator icon (defaults to status icon) |
### Alert.Content Props
| Prop | Type | Default | Description |
| ----------- | ----------- | ------- | ----------------------------------------- |
| `className` | `string` | - | Additional CSS classes |
| `children` | `ReactNode` | - | Content (typically Title and Description) |
### Alert.Title Props
| Prop | Type | Default | Description |
| ----------- | ----------- | ------- | ---------------------- |
| `className` | `string` | - | Additional CSS classes |
| `children` | `ReactNode` | - | The alert title text |
### Alert.Description Props
| Prop | Type | Default | Description |
| ----------- | ----------- | ------- | -------------------------- |
| `className` | `string` | - | Additional CSS classes |
| `children` | `ReactNode` | - | The alert description text |
# Skeleton
**Category**: react
**URL**: https://v3.heroui.com/docs/react/components/skeleton
**Source**: https://raw.githubusercontent.com/heroui-inc/heroui/refs/heads/v3/apps/docs/content/docs/react/components/(feedback)/skeleton.mdx
> Skeleton is a placeholder to show a loading state and the expected shape of a component.
## Import
```tsx
import { Skeleton } from '@heroui/react';
```
### Usage
```tsx
import {Skeleton} from "@heroui/react";
export function Basic() {
return (
);
}
```
### Text Content
```tsx
import {Skeleton} from "@heroui/react";
export function TextContent() {
return (
);
}
```
### User Profile
```tsx
import {Skeleton} from "@heroui/react";
export function UserProfile() {
return (
);
}
```
### List Items
```tsx
import {Skeleton} from "@heroui/react";
export function List() {
return (
{Array.from({length: 3}).map((_, index) => (
))}
);
}
```
### Animation Types
```tsx
import {Skeleton} from "@heroui/react";
export function AnimationTypes() {
return (
Shimmer
Pulse
None
);
}
```
### Grid
```tsx
import {Skeleton} from "@heroui/react";
export function Grid() {
return (
);
}
```
### Single Shimmer
A synchronized shimmer effect that passes over all skeleton elements at once. Apply the `skeleton--shimmer` class to a parent container and set `animationType="none"` on child skeletons.
```tsx
import {Skeleton} from "@heroui/react";
export function SingleShimmer() {
return (
);
}
```
## Related Components
* **Card**: Content container with header, body, and footer
* **Avatar**: Display user profile images
## Styling
### Global Animation Configuration
You can set a default animation type for all Skeleton components in your application by defining the `--skeleton-animation` CSS variable:
```css
/* In your global CSS file */
:root {
/* Possible values: shimmer, pulse, none */
--skeleton-animation: pulse;
}
/* You can also set different values for light/dark themes */
.light, [data-theme="light"] {
--skeleton-animation: shimmer;
}
.dark, [data-theme="dark"] {
--skeleton-animation: pulse;
}
```
This global setting will be overridden by the `animationType` prop when specified on individual components.
### Passing Tailwind CSS classes
```tsx
import { Skeleton } from '@heroui/react';
function CustomSkeleton() {
return (
);
}
```
### Customizing the component classes
To customize the Skeleton component classes, you can use the `@layer components` directive.
[Learn more](https://tailwindcss.com/docs/adding-custom-styles#adding-component-classes).
```css
@layer components {
/* Base skeleton styles */
.skeleton {
@apply bg-surface-secondary/50; /* Change base background */
}
/* Shimmer animation gradient */
.skeleton--shimmer:before {
@apply viasurface; /* Change shimmer gradient color */
}
/* Pulse animation */
.skeleton--pulse {
@apply animate-pulse opacity-75; /* Customize pulse animation */
}
/* No animation variant */
.skeleton--none {
@apply opacity-50; /* Style for static skeleton */
}
}
```
HeroUI follows the [BEM](https://getbem.com/) methodology to ensure component variants and states are reusable and easy to customize.
### CSS Classes
The Skeleton component uses these CSS classes ([View source styles](https://github.com/heroui-inc/heroui/blob/v3/packages/styles/components/skeleton.css)):
#### Base Class
`.skeleton` - Base skeleton styles with background and rounded corners
#### Animation Variant Classes
* `.skeleton--shimmer` - Adds shimmer animation with gradient effect (default)
* `.skeleton--pulse` - Adds pulse animation using Tailwind's animate-pulse
* `.skeleton--none` - No animation, static skeleton
### Animation
The Skeleton component supports three animation types, each with different visual effects:
#### Shimmer Animation
The shimmer effect creates a gradient that moves across the skeleton element:
```css
.skeleton--shimmer:before {
@apply animate-skeleton via-surface-3 absolute inset-0 -translate-x-full
bg-gradient-to-r from-transparent to-transparent content-[''];
}
```
The shimmer animation is defined in the theme using:
```css
@theme inline {
--animate-skeleton: skeleton 2s linear infinite;
@keyframes skeleton {
100% {
transform: translateX(200%);
}
}
}
```
#### Pulse Animation
The pulse animation uses Tailwind's built-in `animate-pulse` utility:
```css
.skeleton--pulse {
@apply animate-pulse;
}
```
#### No Animation
For static skeletons without any animation:
```css
.skeleton--none {
/* No animation styles applied */
}
```
## API Reference
### Skeleton Props
| Prop | Type | Default | Description |
| --------------- | -------------------------------- | --------------------------- | ------------------------------------------------------------------------------------------------------- |
| `animationType` | `"shimmer" \| "pulse" \| "none"` | `"shimmer"` or CSS variable | The animation type for the skeleton. Can be globally configured via `--skeleton-animation` CSS variable |
| `className` | `string` | - | Additional CSS classes |
# Spinner
**Category**: react
**URL**: https://v3.heroui.com/docs/react/components/spinner
**Source**: https://raw.githubusercontent.com/heroui-inc/heroui/refs/heads/v3/apps/docs/content/docs/react/components/(feedback)/spinner.mdx
> A loading indicator component to show pending states
## Import
```tsx
import { Spinner } from '@heroui/react';
```
### Usage
```tsx
import {Spinner} from "@heroui/react";
export function SpinnerBasic() {
return (
);
}
```
### Colors
```tsx
import {Spinner} from "@heroui/react";
export function SpinnerColors() {
return (
Current
Accent
Success
Warning
Danger
);
}
```
### Sizes
```tsx
import {Spinner} from "@heroui/react";
export function SpinnerSizes() {
return (
Small
Medium
Large
Extra Large
);
}
```
## Styling
### Passing Tailwind CSS classes
```tsx
import {Spinner} from '@heroui/react';
function CustomSpinner() {
return (
);
}
```
### Customizing the component classes
To customize the Spinner component classes, you can use the `@layer components` directive.
[Learn more](https://tailwindcss.com/docs/adding-custom-styles#adding-component-classes).
```css
@layer components {
.spinner {
@apply animate-spin;
}
.spinner--accent {
color: var(--accent);
}
}
```
HeroUI follows the [BEM](https://getbem.com/) methodology to ensure component variants and states are reusable and easy to customize.
### CSS Classes
The Spinner component uses these CSS classes ([View source styles](https://github.com/heroui-inc/heroui/blob/v3/packages/styles/components/spinner.css)):
#### Base & Size Classes
* `.spinner` - Base spinner styles with default size
* `.spinner--sm` - Small size variant
* `.spinner--md` - Medium size variant (default)
* `.spinner--lg` - Large size variant
* `.spinner--xl` - Extra large size variant
#### Color Classes
* `.spinner--current` - Inherits current text color
* `.spinner--accent` - Accent color variant
* `.spinner--danger` - Danger color variant
* `.spinner--success` - Success color variant
* `.spinner--warning` - Warning color variant
## API Reference
### Spinner Props
| Prop | Type | Default | Description |
| ----------- | ------------------------------------------------------------- | ----------- | ---------------------------- |
| `size` | `"sm" \| "md" \| "lg" \| "xl"` | `"md"` | Size of the spinner |
| `color` | `"current" \| "accent" \| "success" \| "warning" \| "danger"` | `"current"` | Color variant of the spinner |
| `className` | `string` | - | Additional CSS classes |
# CheckboxGroup
**Category**: react
**URL**: https://v3.heroui.com/docs/react/components/checkbox-group
**Source**: https://raw.githubusercontent.com/heroui-inc/heroui/refs/heads/v3/apps/docs/content/docs/react/components/(forms)/checkbox-group.mdx
> A checkbox group component for managing multiple checkbox selections
## Import
```tsx
import { CheckboxGroup, Checkbox, Label, Description } from '@heroui/react';
```
### Usage
```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
);
}
```
### Anatomy
Import the CheckboxGroup component and access all parts using dot notation.
```tsx
import {CheckboxGroup, Checkbox, Label, Description, FieldError} from '@heroui/react';
export default () => (
{/* Optional */}
{/* Optional */}
{/* Optional */}
);
```
### On Surface
When used inside a [Surface](/docs/components/surface) component, CheckboxGroup automatically applies on-surface styling.
```tsx
import {Checkbox, CheckboxGroup, Description, Label, Surface} from "@heroui/react";
export function OnSurface() {
return (
Choose all that applyLove building softwareEnjoy creating beautiful interfacesPassionate about content creation
);
}
```
### With Custom Indicator
```tsx
"use client";
import {Checkbox, CheckboxGroup, Description, Label} from "@heroui/react";
export function WithCustomIndicator() {
return (
Select the features you want
{({isSelected}) =>
isSelected ? (
) : null
}
Receive updates via email
{({isSelected}) =>
isSelected ? (
) : null
}
Get weekly newsletters
);
}
```
### Indeterminate
```tsx
"use client";
import {Checkbox, CheckboxGroup, Label} from "@heroui/react";
import {useState} from "react";
export function Indeterminate() {
const [selected, setSelected] = useState(["coding"]);
const allOptions = ["coding", "design", "writing"];
return (
);
}
```
### Controlled
```tsx
"use client";
import {Checkbox, CheckboxGroup, Label} from "@heroui/react";
import {useState} from "react";
export function Controlled() {
const [selected, setSelected] = useState(["coding", "design"]);
return (
);
}
```
### Validation
```tsx
"use client";
import {Button, Checkbox, CheckboxGroup, FieldError, Form, Label} from "@heroui/react";
export function Validation() {
return (
);
}
```
### Disabled
```tsx
import {Checkbox, CheckboxGroup, Description, Label} from "@heroui/react";
export function Disabled() {
return (
Feature selection is temporarily disabledThis feature is coming soonThis feature is coming soon
);
}
```
### Features and Add-ons Example
```tsx
import {Bell, Comment, Envelope} from "@gravity-ui/icons";
import {Checkbox, CheckboxGroup, Description, Label} from "@heroui/react";
import clsx from "clsx";
export function FeaturesAndAddOns() {
const addOns = [
{
description: "Receive updates via email",
icon: Envelope,
title: "Email Notifications",
value: "email",
},
{
description: "Get instant SMS notifications",
icon: Comment,
title: "SMS Alerts",
value: "sms",
},
{
description: "Browser and mobile push alerts",
icon: Bell,
title: "Push Notifications",
value: "push",
},
];
return (
Choose how you want to receive updates
{addOns.map((addon) => (
{addon.description}
))}
);
}
```
## Related Components
* **Checkbox**: Binary choice input control
* **Label**: Accessible label for form controls
* **Fieldset**: Group related form controls with legends
## Styling
### Passing Tailwind CSS classes
You can customize the CheckboxGroup component:
```tsx
import { CheckboxGroup, Checkbox, Label } from '@heroui/react';
function CustomCheckboxGroup() {
return (
);
}
```
### Customizing the component classes
To customize the CheckboxGroup component classes, you can use the `@layer components` directive.
[Learn more](https://tailwindcss.com/docs/adding-custom-styles#adding-component-classes).
```css
@layer components {
.checkbox-group {
@apply flex flex-col gap-2;
}
}
```
HeroUI follows the [BEM](https://getbem.com/) methodology to ensure component variants and states are reusable and easy to customize.
### CSS Classes
The CheckboxGroup component uses these CSS classes ([View source styles](https://github.com/heroui-inc/heroui/blob/v3/packages/styles/components/checkbox-group.css)):
* `.checkbox-group` - Base checkbox group container
## API Reference
### CheckboxGroup Props
Inherits from [React Aria CheckboxGroup](https://react-spectrum.adobe.com/react-aria/CheckboxGroup.html).
| Prop | Type | Default | Description |
| -------------- | -------------------------------------------------------------------------- | ------- | ----------------------------------------------------------------- |
| `value` | `string[]` | - | The current selected values (controlled) |
| `defaultValue` | `string[]` | - | The default selected values (uncontrolled) |
| `onChange` | `(value: string[]) => void` | - | Handler called when the selected values change |
| `isDisabled` | `boolean` | `false` | Whether the checkbox group is disabled |
| `isRequired` | `boolean` | `false` | Whether the checkbox group is required |
| `isReadOnly` | `boolean` | `false` | Whether the checkbox group is read only |
| `isInvalid` | `boolean` | `false` | Whether the checkbox group is in an invalid state |
| `name` | `string` | - | The name of the checkbox group, used when submitting an HTML form |
| `children` | `React.ReactNode \| (values: CheckboxGroupRenderProps) => React.ReactNode` | - | Checkbox group content or render prop |
### CheckboxGroupRenderProps
When using the render prop pattern, these values are provided:
| Prop | Type | Description |
| ------------ | ---------- | ------------------------------------------------- |
| `value` | `string[]` | The currently selected values |
| `isDisabled` | `boolean` | Whether the checkbox group is disabled |
| `isReadOnly` | `boolean` | Whether the checkbox group is read only |
| `isInvalid` | `boolean` | Whether the checkbox group is in an invalid state |
| `isRequired` | `boolean` | Whether the checkbox group is required |
# Checkbox
**Category**: react
**URL**: https://v3.heroui.com/docs/react/components/checkbox
**Source**: https://raw.githubusercontent.com/heroui-inc/heroui/refs/heads/v3/apps/docs/content/docs/react/components/(forms)/checkbox.mdx
> Checkboxes allow users to select multiple items from a list of individual items, or to mark one individual item as selected.
## Import
```tsx
import { Checkbox, Label } from '@heroui/react';
```
### Usage
```tsx
import {Checkbox, Label} from "@heroui/react";
export function Basic() {
return (
);
}
```
### Anatomy
Import the Checkbox component and access all parts using dot notation.
```tsx
import { Checkbox, Label, Description } from '@heroui/react';
export default () => (
{/* Optional */}
);
```
### Disabled
```tsx
import {Checkbox, Description, Label} from "@heroui/react";
export function Disabled() {
return (
This feature is coming soon
);
}
```
### Default Selected
```tsx
import {Checkbox, Label} from "@heroui/react";
export function DefaultSelected() {
return (
);
}
```
### Controlled
```tsx
"use client";
import {Checkbox, Label} from "@heroui/react";
import {useState} from "react";
export function Controlled() {
const [isSelected, setIsSelected] = useState(true);
return (
);
}
```
### Full Rounded
```tsx
import {Checkbox, Label} from "@heroui/react";
export function FullRounded() {
return (
);
}
```
## Related Components
* **Label**: Accessible label for form controls
* **CheckboxGroup**: Group of checkboxes with shared state
* **Description**: Helper text for form fields
## Styling
### Passing Tailwind CSS classes
You can customize individual Checkbox components:
```tsx
import { Checkbox, Label } from '@heroui/react';
function CustomCheckbox() {
return (
);
}
```
### Customizing the component classes
To customize the Checkbox component classes, you can use the `@layer components` directive.
[Learn more](https://tailwindcss.com/docs/adding-custom-styles#adding-component-classes).
```css
@layer components {
.checkbox {
@apply inline-flex gap-3 items-center;
}
.checkbox__control {
@apply size-5 border-2 border-gray-400 rounded data-[selected=true]:bg-blue-500 data-[selected=true]:border-blue-500;
/* Animated background indicator */
&::before {
@apply bg-accent pointer-events-none absolute inset-0 z-0 origin-center scale-50 rounded-md opacity-0 content-[''];
transition:
scale 200ms linear,
opacity 200ms linear,
background-color 200ms ease-out;
}
/* Show indicator when selected */
&[data-selected="true"]::before {
@apply scale-100 opacity-100;
}
}
.checkbox__indicator {
@apply text-white;
}
.checkbox__content {
@apply flex flex-col gap-1;
}
}
```
HeroUI follows the [BEM](https://getbem.com/) methodology to ensure component variants and states are reusable and easy to customize.
### CSS Classes
The Checkbox component uses these CSS classes ([View source styles](https://github.com/heroui-inc/heroui/blob/v3/packages/styles/components/checkbox.css)):
* `.checkbox` - Base checkbox container
* `.checkbox__control` - Checkbox control box
* `.checkbox__indicator` - Checkbox checkmark indicator
* `.checkbox__content` - Optional content container
### Interactive States
The checkbox supports both CSS pseudo-classes and data attributes for flexibility:
* **Selected**: `[data-selected="true"]` or `[aria-checked="true"]` (shows checkmark and background color change)
* **Indeterminate**: `[data-indeterminate="true"]` (shows indeterminate state with dash)
* **Invalid**: `[data-invalid="true"]` or `[aria-invalid="true"]` (shows error state with danger colors)
* **Hover**: `:hover` or `[data-hovered="true"]`
* **Focus**: `:focus-visible` or `[data-focus-visible="true"]` (shows focus ring)
* **Disabled**: `:disabled` or `[aria-disabled="true"]` (reduced opacity, no pointer events)
* **Pressed**: `:active` or `[data-pressed="true"]`
## API Reference
### Checkbox Props
Inherits from [React Aria Checkbox](https://react-spectrum.adobe.com/react-aria/Checkbox.html).
| Prop | Type | Default | Description |
| ----------------- | --------------------------------------------------------------------- | ------- | ----------------------------------------------------------------- |
| `isSelected` | `boolean` | `false` | Whether the checkbox is checked |
| `defaultSelected` | `boolean` | `false` | Whether the checkbox is checked by default (uncontrolled) |
| `isIndeterminate` | `boolean` | `false` | Whether the checkbox is in an indeterminate state |
| `isDisabled` | `boolean` | `false` | Whether the checkbox is disabled |
| `isInvalid` | `boolean` | `false` | Whether the checkbox is invalid |
| `isReadOnly` | `boolean` | `false` | Whether the checkbox is read only |
| `isOnSurface` | `boolean` | `false` | Whether the checkbox is displayed on a surface (affects styling) |
| `name` | `string` | - | The name of the input element, used when submitting an HTML form |
| `value` | `string` | - | The value of the input element, used when submitting an HTML form |
| `onChange` | `(isSelected: boolean) => void` | - | Handler called when the checkbox value changes |
| `children` | `React.ReactNode \| (values: CheckboxRenderProps) => React.ReactNode` | - | Checkbox content or render prop |
### CheckboxRenderProps
When using the render prop pattern, these values are provided:
| Prop | Type | Description |
| ----------------- | --------- | ------------------------------------------------- |
| `isSelected` | `boolean` | Whether the checkbox is currently checked |
| `isIndeterminate` | `boolean` | Whether the checkbox is in an indeterminate state |
| `isHovered` | `boolean` | Whether the checkbox is hovered |
| `isPressed` | `boolean` | Whether the checkbox is currently pressed |
| `isFocused` | `boolean` | Whether the checkbox is focused |
| `isFocusVisible` | `boolean` | Whether the checkbox is keyboard focused |
| `isDisabled` | `boolean` | Whether the checkbox is disabled |
| `isReadOnly` | `boolean` | Whether the checkbox is read only |
# DateField
**Category**: react
**URL**: https://v3.heroui.com/docs/react/components/date-field
**Source**: https://raw.githubusercontent.com/heroui-inc/heroui/refs/heads/v3/apps/docs/content/docs/react/components/(forms)/date-field.mdx
> Date input field with labels, descriptions, and validation built on React Aria DateField
## Import
```tsx
import { DateField } from '@heroui/react';
```
### Usage
```tsx
"use client";
import {DateField, DateInputGroup, Label} from "@heroui/react";
export function Basic() {
return (
{(segment) => }
);
}
```
### Anatomy
```tsx
import {DateField, Label, DateInputGroup, Description, FieldError} from '@heroui/react';
export default () => (
{(segment) => }
)
```
> **DateField** combines label, date input, description, and error into a single accessible component.
### With Description
```tsx
"use client";
import {DateField, DateInputGroup, Description, Label} from "@heroui/react";
export function WithDescription() {
return (
{(segment) => }
Enter your date of birth
{(segment) => }
Enter a date for your appointment
);
}
```
### Required Field
```tsx
"use client";
import {DateField, DateInputGroup, Description, Label} from "@heroui/react";
export function Required() {
return (
{(segment) => }
{(segment) => }
Required field
);
}
```
### Validation
Use `isInvalid` together with `FieldError` to surface validation messages.
```tsx
"use client";
import {DateField, DateInputGroup, FieldError, Label} from "@heroui/react";
export function Invalid() {
return (
{(segment) => }
Please enter a valid date
{(segment) => }
Date must be in the future
);
}
```
### With Validation
DateField supports validation with `minValue`, `maxValue`, and custom validation logic.
```tsx
"use client";
import type {DateValue} from "@internationalized/date";
import {DateField, DateInputGroup, Description, FieldError, Label} from "@heroui/react";
import {getLocalTimeZone, today} from "@internationalized/date";
import {useState} from "react";
export function WithValidation() {
const [value, setValue] = useState(null);
const todayDate = today(getLocalTimeZone());
const isInvalid = value !== null && value.compare(todayDate) < 0;
return (
{(segment) => }
{isInvalid ? (
Date must be today or in the future
) : (
Enter a date from today onwards
)}
);
}
```
### Controlled
Control the value to synchronize with other components or state management.
```tsx
"use client";
import type {DateValue} from "@internationalized/date";
import {Button, DateField, DateInputGroup, Description, Label} from "@heroui/react";
import {getLocalTimeZone, today} from "@internationalized/date";
import {useState} from "react";
export function Controlled() {
const [value, setValue] = useState(null);
return (
{(segment) => }
Current value: {value ? value.toString() : "(empty)"}
);
}
```
### Disabled State
```tsx
"use client";
import {DateField, DateInputGroup, Description, Label} from "@heroui/react";
import {getLocalTimeZone, today} from "@internationalized/date";
export function Disabled() {
return (
{(segment) => }
This date field is disabled
{(segment) => }
This date field is disabled
);
}
```
### With Icons
Add prefix or suffix icons to enhance the date field.
```tsx
"use client";
import {Calendar} from "@gravity-ui/icons";
import {DateField, DateInputGroup, Label} from "@heroui/react";
export function WithPrefixIcon() {
return (
{(segment) => }
);
}
```
```tsx
"use client";
import {Calendar} from "@gravity-ui/icons";
import {DateField, DateInputGroup, Label} from "@heroui/react";
export function WithSuffixIcon() {
return (
{(segment) => }
);
}
```
```tsx
"use client";
import {Calendar, ChevronDown} from "@gravity-ui/icons";
import {DateField, DateInputGroup, Description, Label} from "@heroui/react";
export function WithPrefixAndSuffix() {
return (
{(segment) => }
Enter a date
);
}
```
### Full Width
```tsx
"use client";
import {Calendar, ChevronDown} from "@gravity-ui/icons";
import {DateField, DateInputGroup, Label} from "@heroui/react";
export function FullWidth() {
return (
{(segment) => }
{(segment) => }
);
}
```
### On Surface
When used inside a [Surface](/docs/components/surface) component, DateField and its child DateInputGroup automatically apply on-surface styling.
```tsx
"use client";
import {Calendar} from "@gravity-ui/icons";
import {DateField, DateInputGroup, Description, Label, Surface} from "@heroui/react";
export function OnSurface() {
return (
{(segment) => }
Enter a date
{(segment) => }
Enter a date for your appointment
);
}
```
### Form Example
Complete form example with validation and submission handling.
```tsx
"use client";
import type {DateValue} from "@internationalized/date";
import {Calendar} from "@gravity-ui/icons";
import {
Button,
DateField,
DateInputGroup,
Description,
FieldError,
Form,
Label,
} from "@heroui/react";
import {getLocalTimeZone, today} from "@internationalized/date";
import {useState} from "react";
export function FormExample() {
const [value, setValue] = useState(null);
const [isSubmitting, setIsSubmitting] = useState(false);
const todayDate = today(getLocalTimeZone());
const isInvalid = value !== null && value.compare(todayDate) < 0;
const handleSubmit = (e: React.FormEvent) => {
e.preventDefault();
if (!value || isInvalid) {
return;
}
setIsSubmitting(true);
// Simulate API call
setTimeout(() => {
console.log("Date submitted:", {date: value});
setValue(null);
setIsSubmitting(false);
}, 1500);
};
return (
);
}
```
## Related Components
* **Label**: Accessible label for form controls
* **FieldError**: Inline validation messages for form fields
* **Description**: Helper text for form fields
## Styling
### Passing Tailwind CSS classes
```tsx
import {DateField, Label, DateInputGroup, Description} from '@heroui/react';
function CustomDateField() {
return (
{(segment) => }
Select a date for your appointment.
);
}
```
### Customizing the component classes
DateField has minimal default styling. Override the `.date-field` class to customize the container styling.
```css
@layer components {
.date-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
* `.date-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. DateInputGroup styling is documented below in the API Reference section.
### Interactive States
DateField 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
### DateField Props
DateField inherits all props from React Aria's [DateField](https://react-aria.adobe.com/DateField.md) component.
#### Base Props
| Prop | Type | Default | Description |
| ----------- | ------------------------------------------------------------------------------ | ------- | ------------------------------------------------------------------ |
| `children` | `React.ReactNode \| (values: DateFieldRenderProps) => React.ReactNode` | - | Child components (Label, DateInputGroup, etc.) or render function. |
| `className` | `string \| (values: DateFieldRenderProps) => string` | - | CSS classes for styling, supports render props. |
| `style` | `React.CSSProperties \| (values: DateFieldRenderProps) => React.CSSProperties` | - | Inline styles, supports render props. |
| `fullWidth` | `boolean` | `false` | Whether the date field should take full width of its container |
| `id` | `string` | - | The element's unique identifier. |
#### Value Props
| Prop | Type | Default | Description |
| ------------------ | ------------------------------------ | ------- | --------------------------------------------------------------------------------------------------------------------------- |
| `value` | `DateValue \| null` | - | Current value (controlled). Uses [`@internationalized/date`](https://react-aria.adobe.com/internationalized/date/) types. |
| `defaultValue` | `DateValue \| null` | - | Default value (uncontrolled). Uses [`@internationalized/date`](https://react-aria.adobe.com/internationalized/date/) types. |
| `onChange` | `(value: DateValue \| null) => void` | - | Handler called when the value changes. |
| `placeholderValue` | `DateValue \| null` | - | Placeholder date that influences the format of the placeholder. |
#### Validation Props
| Prop | Type | Default | Description |
| -------------------- | -------------------------------------------------------------------- | ---------- | ---------------------------------------------------------------------------------------------------------------------------------------------- |
| `isRequired` | `boolean` | `false` | Whether user input is required before form submission. |
| `isInvalid` | `boolean` | - | Whether the value is invalid. |
| `minValue` | `DateValue \| null` | - | The minimum allowed date that a user may select. Uses [`@internationalized/date`](https://react-aria.adobe.com/internationalized/date/) types. |
| `maxValue` | `DateValue \| null` | - | The maximum allowed date that a user may select. Uses [`@internationalized/date`](https://react-aria.adobe.com/internationalized/date/) types. |
| `isDateUnavailable` | `(date: DateValue) => boolean` | - | Callback that is called for each date. If it returns true, the date is unavailable. |
| `validate` | `(value: DateValue) => ValidationError \| true \| null \| undefined` | - | Custom validation function. |
| `validationBehavior` | `'native' \| 'aria'` | `'native'` | Whether to use native HTML form validation or ARIA attributes. |
#### Format Props
| Prop | Type | Default | Description |
| ------------------------- | ------------- | ------- | -------------------------------------------------------------------------------------------- |
| `granularity` | `Granularity` | - | Determines the smallest unit displayed. Defaults to `"day"` for dates, `"minute"` for times. |
| `hourCycle` | `12 \| 24` | - | Whether to display time in 12 or 24 hour format. By default, determined by locale. |
| `hideTimeZone` | `boolean` | `false` | Whether to hide the time zone abbreviation. |
| `shouldForceLeadingZeros` | `boolean` | - | Whether to always show leading zeros in month, day, and hour fields. |
#### State Props
| Prop | Type | Default | Description |
| ------------ | --------- | ------- | -------------------------------------------------- |
| `isDisabled` | `boolean` | - | Whether the input is disabled. |
| `isReadOnly` | `boolean` | - | Whether the input can be selected but not changed. |
#### Form Props
| Prop | Type | Default | Description |
| -------------- | --------- | ------- | -------------------------------------------------------------------------------- |
| `name` | `string` | - | Name of the input element, for HTML form submission. Submits as ISO 8601 string. |
| `autoFocus` | `boolean` | - | Whether the element should receive focus on render. |
| `autoComplete` | `string` | - | Type of autocomplete functionality the input should provide. |
#### 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
DateField works with these separate components that should be imported and used directly:
* **Label** - Field label component from `@heroui/react`
* **DateInputGroup** - Date input component with segmented editing from `@heroui/react` (documented below)
* **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 DateField for composition:
```tsx
import {parseDate} from '@internationalized/date';
import {DateField, Label, DateInputGroup, Description, FieldError} from '@heroui/react';
{(segment) => }
Select a date from today onwards.Please select a valid date.
```
### DateValue Types
DateField uses types from [`@internationalized/date`](https://react-aria.adobe.com/internationalized/date/):
* `CalendarDate` - Date without time or timezone
* `CalendarDateTime` - Date with time but no timezone
* `ZonedDateTime` - Date with time and timezone
* `Time` - Time only
Example:
```tsx
import {parseDate, today, getLocalTimeZone} from '@internationalized/date';
// Parse from string
const date = parseDate('2024-01-15');
// Today's date
const todayDate = today(getLocalTimeZone());
// Use in DateField
{/* ... */}
```
> **Note:** DateField uses the [`@internationalized/date`](https://react-aria.adobe.com/internationalized/date/) package for date manipulation, parsing, and type definitions. See the [Internationalized Date documentation](https://react-aria.adobe.com/internationalized/date/) for more information about available types and functions.
### DateFieldRenderProps
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). |
### DateInputGroup Props
DateInputGroup 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 date input group should take full width of its container |
| `isOnSurface` | `boolean` | `false` | Whether the input is displayed on a surface (affects styling) |
### DateInputGroup.Input Props
DateInputGroup.Input accepts all props from React Aria's `DateInput` component plus the following:
| Prop | Type | Default | Description |
| ------------- | --------- | ------- | ------------------------------------------------------------- |
| `className` | `string` | - | Tailwind classes merged with the component styles. |
| `isOnSurface` | `boolean` | `false` | Whether the input is displayed on a surface (affects styling) |
The `DateInput` component accepts a render prop function that receives date segments. Each segment represents a part of the date (year, month, day, etc.).
### DateInputGroup.Segment Props
DateInputGroup.Segment accepts all props from React Aria's `DateSegment` component:
| Prop | Type | Default | Description |
| ----------- | ------------- | ------- | ------------------------------------------------------- |
| `segment` | `DateSegment` | - | The date segment object from the DateInput render prop. |
| `className` | `string` | - | Tailwind classes merged with the component styles. |
### DateInputGroup.Prefix Props
DateInputGroup.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. |
### DateInputGroup.Suffix Props
DateInputGroup.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. |
## DateInputGroup Styling
### Customizing the component classes
The base classes power every instance. Override them once with `@layer components`.
```css
@layer components {
.date-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;
}
}
.date-input-group__input {
@apply flex flex-1 items-center gap-px rounded-none border-0 bg-transparent px-3 py-2 shadow-none outline-none;
}
.date-input-group__segment {
@apply inline-block rounded-md px-0.5 text-end tabular-nums outline-none;
&:focus,
&[data-focused="true"] {
@apply bg-accent-soft text-accent-soft-foreground;
}
}
.date-input-group__prefix,
.date-input-group__suffix {
@apply pointer-events-none shrink-0 text-field-placeholder flex items-center;
}
}
```
### DateInputGroup CSS Classes
* `.date-input-group` – Root container styling
* `.date-input-group__input` – Input wrapper styling
* `.date-input-group__segment` – Individual date segment styling
* `.date-input-group__prefix` – Prefix element styling
* `.date-input-group__suffix` – Suffix element styling
### DateInputGroup 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"]`
* **Segment Focus**: `:focus` or `[data-focused="true"]` on segment elements
* **Segment Placeholder**: `[data-placeholder="true"]` on segment elements
# Description
**Category**: react
**URL**: https://v3.heroui.com/docs/react/components/description
**Source**: https://raw.githubusercontent.com/heroui-inc/heroui/refs/heads/v3/apps/docs/content/docs/react/components/(forms)/description.mdx
> Provides supplementary text for form fields and other components
## Import
```tsx
import { Description } from '@heroui/react';
```
## Usage
```tsx
import {Description, Input, Label} from "@heroui/react";
export function Basic() {
return (
We'll never share your email with anyone else.
);
}
```
## Related Components
* **TextField**: Composition-friendly fields with labels and validation
* **Input**: Single-line text input built on React Aria
* **TextArea**: Multiline text input with focus management
## API
### Description Props
| Prop | Type | Default | Description |
| ----------- | ----------- | ------- | ------------------------------ |
| `className` | `string` | - | Additional CSS classes |
| `children` | `ReactNode` | - | The content of the description |
## Accessibility
The Description component enhances accessibility by:
* Using semantic HTML that screen readers can identify
* Providing the `slot="description"` attribute for React Aria integration
* Supporting proper text contrast ratios
## Styling
The Description component uses the following CSS classes:
* `.description` - Base description styles with `muted` text color
## Examples
### With Form Fields
```tsx
Must be at least 8 characters with one uppercase letter
```
### Integration with TextField
```tsx
import {TextField, Label, Input, Description} from '@heroui/react';
We'll never share your email
```
When using the [TextField](./text-field) component, accessibility attributes are automatically applied to the label and description.
# ErrorMessage
**Category**: react
**URL**: https://v3.heroui.com/docs/react/components/error-message
**Source**: https://raw.githubusercontent.com/heroui-inc/heroui/refs/heads/v3/apps/docs/content/docs/react/components/(forms)/error-message.mdx
> A low-level error message component for displaying errors
## Import
```tsx
import { ErrorMessage } from '@heroui/react';
```
## Usage
`ErrorMessage` is a low-level component built on React Aria's `Text` component with an `errorMessage` slot. It's designed for displaying error messages in **non-form components** such as `TagGroup`, `Calendar`, and other collection-based components.
```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>}
);
}
```
### Anatomy
```tsx
import { TagGroup, Tag, Label, Description, ErrorMessage } from '@heroui/react';
```
## Related Components
* **TagGroup**: Focusable list of tags with selection and removal support
## When to Use
`ErrorMessage` is **not tied to forms**. It's a generic error display component for non-form contexts.
* **Recommended for** non-form components (e.g., `TagGroup`, `Calendar`, collection components)
* **For form fields**, we recommend using [`FieldError`](/docs/components/field-error) instead, which provides form-specific validation features and automatic error handling, following standardized form validation patterns.
## ErrorMessage vs FieldError
| Component | Use Case | Form Integration | Example Components |
| -------------- | ------------------------- | ---------------- | ------------------------------------ |
| `ErrorMessage` | Non-form components | No | `TagGroup`, `Calendar` |
| `FieldError` | Form fields (recommended) | Yes | `TextField`, `NumberField`, `Select` |
For form validation, we recommend using `FieldError` as it follows standardized form validation patterns and provides form-specific features. See the [FieldError documentation](/docs/components/field-error) and the [Form guide](/docs/components/form) for examples and best practices.
## API Reference
### ErrorMessage Props
| Prop | Type | Default | Description |
| ----------- | ----------- | ------- | ------------------------- |
| `className` | `string` | - | Additional CSS classes |
| `children` | `ReactNode` | - | The error message content |
**Note**: `ErrorMessage` is built on React Aria's `Text` component with `slot="errorMessage"`. It can be targeted using the `[slot=errorMessage]` CSS selector.
## Accessibility
The ErrorMessage component enhances accessibility by:
* Using semantic HTML that screen readers can identify
* Providing the `slot="errorMessage"` attribute for React Aria integration
* Supporting proper text contrast ratios for error states
* Following WAI-ARIA best practices for error messaging
## Styling
### Passing Tailwind CSS classes
```tsx
import { ErrorMessage } from '@heroui/react';
function CustomErrorMessage() {
return (
Custom styled error message
);
}
```
### Customizing the component classes
To customize the ErrorMessage component classes, you can use the `@layer components` directive.
[Learn more](https://tailwindcss.com/docs/adding-custom-styles#adding-component-classes).
```css
@layer components {
.error-message {
@apply text-red-600 text-sm font-medium;
}
}
```
HeroUI follows the [BEM](https://getbem.com/) methodology to ensure component variants and states are reusable and easy to customize.
### CSS Classes
The ErrorMessage component uses these CSS classes ([View source styles](https://github.com/heroui-inc/heroui/blob/v3/packages/styles/components/error-message.css)):
#### Base Classes
* `.error-message` - Base error message styles with danger color and text truncation
#### Slot Classes
* `[slot="errorMessage"]` - ErrorMessage slot styles for React Aria integration
# FieldError
**Category**: react
**URL**: https://v3.heroui.com/docs/react/components/field-error
**Source**: https://raw.githubusercontent.com/heroui-inc/heroui/refs/heads/v3/apps/docs/content/docs/react/components/(forms)/field-error.mdx
> Displays validation error messages for form fields
## Import
```tsx
import { FieldError } from '@heroui/react';
```
## Usage
The FieldError component displays validation error messages for form fields. It automatically appears when the parent field is marked as invalid and provides smooth opacity transitions.
```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
);
}
```
## Related Components
* **TextField**: Composition-friendly fields with labels and validation
* **Input**: Single-line text input built on React Aria
* **TextArea**: Multiline text input with focus management
## API
### FieldError Props
| Prop | Type | Default | Description |
| ----------- | ------------------------------------------------------------ | ------- | ---------------------------------------- |
| `className` | `string` | - | Additional CSS classes |
| `children` | `ReactNode \| ((validation: ValidationResult) => ReactNode)` | - | Error message content or render function |
## Accessibility
The FieldError component ensures accessibility by:
* Using proper ARIA attributes for error announcement
* Supporting screen readers with semantic HTML
* Providing visual and programmatic error indication
* Automatically managing visibility based on validation state
## Styling
The FieldError component uses the following CSS classes:
* `.field-error` - Base error styles with danger color
* Only shows when the `data-visible` attribute is present
* Text is truncated with ellipsis for long messages
## Examples
### Basic Validation
```tsx
export function Basic() {
const [value, setValue] = useState("");
const isInvalid = value.length > 0 && value.length < 3;
return (
setValue(e.target.value)}
/>
Username must be at least 3 characters
);
}
```
### With Dynamic Messages
```tsx
0}>
{(validation) => validation.validationErrors.join(', ')}
```
### Custom Validation Logic
```tsx
function EmailField() {
const [email, setEmail] = useState('');
const isInvalid = email.length > 0 && !email.includes('@');
return (
setEmail(e.target.value)}
/>
Email must include @ symbol
);
}
```
### Multiple Error Messages
```tsx
{errors.map((error, i) => (
{error}
))}
```
# Fieldset
**Category**: react
**URL**: https://v3.heroui.com/docs/react/components/fieldset
**Source**: https://raw.githubusercontent.com/heroui-inc/heroui/refs/heads/v3/apps/docs/content/docs/react/components/(forms)/fieldset.mdx
> Group related form controls with legends, descriptions, and actions
## Import
```tsx
import { Fieldset } from '@heroui/react';
```
### Usage
```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 (
);
}
```
### On Surface
When used inside a [Surface](/docs/components/surface) component, form controls within Fieldset automatically apply on-surface styling.
```tsx
"use client";
import {FloppyDisk} from "@gravity-ui/icons";
import {
Button,
Description,
FieldError,
Fieldset,
Form,
Input,
Label,
Surface,
TextArea,
TextField,
} from "@heroui/react";
import React from "react";
export function OnSurface() {
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 (
);
}
```
### Anatomy
Import the Fieldset component and access all parts using dot notation.
```tsx
import { Fieldset } from '@heroui/react';
export default () => (
)
```
## Related Components
* **TextField**: Composition-friendly fields with labels and validation
* **Label**: Accessible label for form controls
* **CheckboxGroup**: Group of checkboxes with shared state
## Styling
### Passing Tailwind CSS classes
```tsx
import { Fieldset, TextField, Label, Input } from '@heroui/react';
function CustomFieldset() {
return (
);
}
```
### Customizing the component classes
Use the `@layer components` directive to target Fieldset [BEM](https://getbem.com/)-style classes.
```css
@layer components {
.fieldset {
@apply gap-5 rounded-xl border border-border/60 bg-surface p-6 shadow-field;
}
.fieldset__legend {
@apply text-lg font-semibold;
}
.fieldset_field_group {
@apply gap-3 md:grid md:grid-cols-2;
}
.fieldset_actions {
@apply flex justify-end gap-2 pt-2;
}
}
```
### CSS Classes
The Fieldset compound component exposes these CSS selectors:
* `.fieldset` – Root container
* `.fieldset__legend` – Legend element
* `.fieldset_field_group` – Wrapper for grouped fields
* `.fieldset_actions` – Action bar below the fields
## API Reference
### Fieldset Props
| Prop | Type | Default | Description |
| ------------- | ------------------------------------------- | ----------------------------------------------- | --------------------------------------------------------- |
| `className` | `string` | - | Tailwind CSS classes applied to the root element. |
| `children` | `React.ReactNode` | - | Fieldset content (legend, groups, descriptions, actions). |
| `nativeProps` | `React.HTMLAttributes` | Supports native fieldset attributes and events. | |
### Fieldset.Legend Props
| Prop | Type | Default | Description |
| ------------- | ----------------------------------------- | ------- | ---------------------------------------- |
| `className` | `string` | - | Tailwind classes for the legend element. |
| `children` | `React.ReactNode` | - | Legend content, usually plain text. |
| `nativeProps` | `React.HTMLAttributes` | - | Native legend attributes. |
### Fieldset.Group Props
| Prop | Type | Default | Description |
| ------------- | -------------------------------------- | ------- | ---------------------------------------------- |
| `className` | `string` | - | Layout and spacing classes for grouped fields. |
| `children` | `React.ReactNode` | - | Form controls to group inside the fieldset. |
| `nativeProps` | `React.HTMLAttributes` | - | Native div attributes. |
### Fieldset.Actions Props
| Prop | Type | Default | Description |
| ------------- | -------------------------------------- | ------- | ------------------------------------------------- |
| `className` | `string` | - | Tailwind classes to align action buttons or text. |
| `children` | `React.ReactNode` | - | Action buttons or helper text. |
| `nativeProps` | `React.HTMLAttributes` | - | Native div attributes. |
# Form
**Category**: react
**URL**: https://v3.heroui.com/docs/react/components/form
**Source**: https://raw.githubusercontent.com/heroui-inc/heroui/refs/heads/v3/apps/docs/content/docs/react/components/(forms)/form.mdx
> Wrapper component for form validation and submission handling
## Import
```tsx
import { Form } from '@heroui/react';
```
### Usage
```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 (
);
}
```
### Anatomy
Import all parts and piece them together.
```tsx
import {Form, Button} from '@heroui/react';
export default () => (
)
```
## Related Components
* **Button**: Allows a user to perform an action
* **Fieldset**: Group related form controls with legends
* **TextField**: Composition-friendly fields with labels and validation
## Styling
### Passing Tailwind CSS classes
```tsx
import {Form, TextField, Label, Input, FieldError, Button} from '@heroui/react';
function CustomForm() {
return (
);
}
```
## API Reference
### Form Props
The Form component is a wrapper around React Aria's Form primitive that provides form validation and submission handling capabilities.
| Prop | Type | Default | Description |
| -------------------- | ------------------------------------------------------------------------------ | ---------- | ------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `action` | `string \| FormHTMLAttributes['action']` | - | The URL to submit the form data to. |
| `className` | `string` | - | Tailwind CSS classes applied to the form element. |
| `children` | `React.ReactNode` | - | Form content (fields, buttons, etc.). |
| `encType` | `'application/x-www-form-urlencoded' \| 'multipart/form-data' \| 'text/plain'` | - | The encoding type for form data submission. |
| `method` | `'get' \| 'post'` | - | The HTTP method to use when submitting the form. |
| `onInvalid` | `(event: FormEvent) => void` | - | Handler called when the form validation fails. By default, the first invalid field will be focused. Use `preventDefault()` to customize focus behavior. |
| `onReset` | `(event: FormEvent) => void` | - | Handler called when the form is reset. |
| `onSubmit` | `(event: FormEvent) => void` | - | Handler called when the form is submitted. |
| `target` | `'_self' \| '_blank' \| '_parent' \| '_top'` | - | Where to display the response after submitting the form. |
| `validationBehavior` | `'native' \| 'aria'` | `'native'` | Whether to use native HTML validation or ARIA validation. 'native' blocks form submission, 'aria' displays errors in realtime. |
| `validationErrors` | `ValidationErrors` | - | Server-side validation errors mapped by field name. Displayed immediately and cleared when user modifies the field. |
| `aria-label` | `string` | - | Accessibility label for the form. |
| `aria-labelledby` | `string` | - | ID of element that labels the form. Creates a form landmark when provided. |
### Form Validation
The Form component integrates with React Aria's validation system, allowing you to:
* Use built-in HTML5 validation attributes (`required`, `minLength`, `pattern`, etc.)
* Provide custom validation functions on TextField components
* Display validation errors with FieldError components
* Handle form submission with proper validation
* Provide server-side validation errors via `validationErrors` prop
#### Validation Behavior
The `validationBehavior` prop controls how validation is displayed:
* **`native`** (default): Uses native HTML validation, blocks form submission on errors
* **`aria`**: Uses ARIA attributes for validation, displays errors in realtime as user types, doesn't block submission
This behavior can be set at the form level or overridden at individual field level.
### Form Submission
Forms can be submitted in several ways:
* **Traditional submission**: Set the `action` prop to submit to a URL
* **JavaScript handling**: Use the `onSubmit` handler to process form data
* **FormData API**: Access form data using the FormData API in your submit handler
Example with FormData:
```tsx
function handleSubmit(e: FormEvent) {
e.preventDefault();
const formData = new FormData(e.currentTarget);
const data = Object.fromEntries(formData);
console.log('Form data:', data);
}
```
### Integration with Form Fields
The Form component works seamlessly with HeroUI's form field components:
* **TextField**: For text inputs with labels and validation
* **Checkbox**: For boolean selections
* **RadioGroup**: For single selection from multiple options
* **Switch**: For toggle controls
* **Button**: For form submission and reset actions
All field components automatically integrate with the Form's validation and submission behavior when placed inside it.
### Accessibility
Forms are accessible by default when using React Aria components. Key features include:
* Native `
# InputGroup
**Category**: react
**URL**: https://v3.heroui.com/docs/react/components/input-group
**Source**: https://raw.githubusercontent.com/heroui-inc/heroui/refs/heads/v3/apps/docs/content/docs/react/components/(forms)/input-group.mdx
> Group related input controls with prefix and suffix elements for enhanced form fields
## Import
```tsx
import { InputGroup } from '@heroui/react';
```
### Usage
```tsx
"use client";
import {Envelope} from "@gravity-ui/icons";
import {InputGroup, Label, TextField} from "@heroui/react";
export function Default() {
return (
);
}
```
### Anatomy
```tsx
import {InputGroup, TextField, Label} from '@heroui/react';
export default () => (
)
```
> **InputGroup** wraps an input field with optional prefix and suffix elements, creating a visually cohesive group. It's typically used within **[TextField](/docs/components/text-field)** to add icons, text, buttons, or other elements before or after the input.
### With Prefix Icon
Add an icon before the input field.
```tsx
"use client";
import {Envelope} from "@gravity-ui/icons";
import {Description, InputGroup, Label, TextField} from "@heroui/react";
export function WithPrefixIcon() {
return (
We'll never share this with anyone else
);
}
```
### With Suffix Icon
Add an icon after the input field.
```tsx
"use client";
import {Envelope} from "@gravity-ui/icons";
import {Description, InputGroup, Label, TextField} from "@heroui/react";
export function WithSuffixIcon() {
return (
We don't send spam
);
}
```
### With Prefix and Suffix
Combine both prefix and suffix elements.
```tsx
"use client";
import {Description, InputGroup, Label, TextField} from "@heroui/react";
export function WithPrefixAndSuffix() {
return (
$USDWhat customers would pay
);
}
```
### Text Prefix
Use text as a prefix, such as currency symbols or protocol prefixes.
```tsx
"use client";
import {InputGroup, Label, TextField} from "@heroui/react";
export function WithTextPrefix() {
return (
https://
);
}
```
### Text Suffix
Use text as a suffix, such as domain extensions or units.
```tsx
"use client";
import {InputGroup, Label, TextField} from "@heroui/react";
export function WithTextSuffix() {
return (
.com
);
}
```
### Icon Prefix and Text Suffix
Combine an icon prefix with a text suffix.
```tsx
"use client";
import {Globe} from "@gravity-ui/icons";
import {InputGroup, Label, TextField} from "@heroui/react";
export function WithIconPrefixAndTextSuffix() {
return (
.com
);
}
```
### Copy Button Suffix
Add an interactive button in the suffix, such as a copy button.
```tsx
"use client";
import {Copy} from "@gravity-ui/icons";
import {Button, InputGroup, Label, TextField} from "@heroui/react";
export function WithCopySuffix() {
return (
);
}
```
### Icon Prefix and Copy Button
Combine an icon prefix with an interactive button suffix.
```tsx
"use client";
import {Copy, Globe} from "@gravity-ui/icons";
import {Button, InputGroup, Label, TextField} from "@heroui/react";
export function WithIconPrefixAndCopySuffix() {
return (
);
}
```
### Password Toggle
Use a button in the suffix to toggle password visibility.
```tsx
"use client";
import {Eye, EyeSlash} from "@gravity-ui/icons";
import {Button, InputGroup, Label, TextField} from "@heroui/react";
import {useState} from "react";
export function PasswordWithToggle() {
const [isVisible, setIsVisible] = useState(false);
return (
);
}
```
### Loading State
Show a loading spinner in the suffix to indicate processing.
```tsx
"use client";
import {InputGroup, Spinner, TextField} from "@heroui/react";
export function WithLoadingSuffix() {
return (
);
}
```
### Keyboard Shortcut
Display keyboard shortcuts using the [Kbd](/docs/components/kbd) component.
```tsx
"use client";
import {InputGroup, Kbd, TextField} from "@heroui/react";
export function WithKeyboardShortcut() {
return (
K
);
}
```
### Badge Suffix
Add a badge or chip in the suffix to show status or labels.
```tsx
"use client";
import {Chip, InputGroup, TextField} from "@heroui/react";
export function WithBadgeSuffix() {
return (
Pro
);
}
```
### Required Field
InputGroup respects the required state from its parent TextField.
```tsx
"use client";
import {Envelope} from "@gravity-ui/icons";
import {Description, InputGroup, Label, TextField} from "@heroui/react";
export function Required() {
return (
$USDWhat customers would pay
);
}
```
### Validation
InputGroup automatically reflects invalid state from its parent TextField.
```tsx
"use client";
import {Envelope} from "@gravity-ui/icons";
import {FieldError, InputGroup, Label, TextField} from "@heroui/react";
export function Invalid() {
return (
Please enter a valid email address$USDPrice must be greater than 0
);
}
```
### Disabled State
InputGroup respects the disabled state from its parent TextField.
```tsx
"use client";
import {Envelope} from "@gravity-ui/icons";
import {InputGroup, Label, TextField} from "@heroui/react";
export function Disabled() {
return (
$USD
);
}
```
### Full Width
```tsx
import {Envelope, Eye} from "@gravity-ui/icons";
import {InputGroup, Label, TextField} from "@heroui/react";
export function FullWidth() {
return (
);
}
```
### On Surface
When used inside a [Surface](/docs/components/surface) component, InputGroup automatically applies on-surface styling. You can also manually control this with the `isOnSurface` prop.
```tsx
"use client";
import {Envelope} from "@gravity-ui/icons";
import {Description, InputGroup, Label, Surface, TextField} from "@heroui/react";
export function OnSurface() {
return (
We'll never share this with anyone else
);
}
```
## Related Components
* **TextField**: Composition-friendly fields with labels and validation
* **Input**: Single-line text input built on React Aria
* **Label**: Accessible label for form controls
## Styling
### Passing Tailwind CSS classes
```tsx
import {InputGroup, TextField, Label} from '@heroui/react';
function CustomInputGroup() {
return (
https://
.com
);
}
```
### Customizing the component classes
InputGroup uses CSS classes that can be customized. Override the component classes to match your design system.
```css
@layer components {
.input-group {
@apply bg-field text-field-foreground shadow-field rounded-field inline-flex h-9 items-center overflow-hidden border text-sm outline-none;
}
.input-group__input {
@apply flex-1 rounded-none border-0 bg-transparent px-3 py-2 shadow-none outline-none;
}
.input-group__prefix {
@apply text-field-placeholder rounded-l-field flex h-full items-center justify-center rounded-r-none bg-transparent px-3;
}
.input-group__suffix {
@apply text-field-placeholder rounded-r-field flex h-full items-center justify-center rounded-l-none bg-transparent px-3;
}
/* On surface variant */
.input-group--on-surface {
@apply bg-on-surface shadow-none;
}
}
```
### CSS Classes
* `.input-group` – Root container with border, background, and flex layout
* `.input-group__input` – Input element with transparent background and no border
* `.input-group__prefix` – Prefix container with left border radius
* `.input-group__suffix` – Suffix container with right border radius
* `.input-group--on-surface` – Variant for use on surface backgrounds
### Interactive States
InputGroup automatically manages these data attributes based on its state:
* **Hover**: `[data-hovered]` - Applied when hovering over the group
* **Focus Within**: `[data-focus-within]` - Applied when the input is focused
* **Invalid**: `[data-invalid]` - Applied when parent TextField is invalid
* **Disabled**: `[data-disabled]` or `[aria-disabled]` - Applied when parent TextField is disabled
## API Reference
### InputGroup Props
InputGroup inherits all props from React Aria's [Group](https://react-spectrum.adobe.com/react-aria/Group.html) component.
#### Base Props
| Prop | Type | Default | Description |
| ----------- | -------------------------------------------------------------------------- | ------- | --------------------------------------------------------------- |
| `children` | `React.ReactNode \| (values: GroupRenderProps) => React.ReactNode` | - | Child components (Input, Prefix, Suffix) or render function. |
| `className` | `string \| (values: GroupRenderProps) => string` | - | CSS classes for styling, supports render props. |
| `style` | `React.CSSProperties \| (values: GroupRenderProps) => React.CSSProperties` | - | Inline styles, supports render props. |
| `fullWidth` | `boolean` | `false` | Whether the input group should take full width of its container |
| `id` | `string` | - | The element's unique identifier. |
#### Variant Props
| Prop | Type | Default | Description |
| ------------- | --------- | ------- | --------------------------------------------------------------------------------------------------------------- |
| `isOnSurface` | `boolean` | - | Whether the group is displayed on a surface background. Automatically detected when inside a Surface component. |
#### 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 group. |
| `aria-describedby` | `string` | - | ID of elements that describe this group. |
| `aria-details` | `string` | - | ID of elements with additional details. |
| `role` | `'group' \| 'region' \| 'presentation'` | `'group'` | Accessibility role for the group. Use 'region' for important content, 'presentation' for visual-only grouping. |
### Composition Components
InputGroup works with these subcomponents:
* **InputGroup.Root** - Root container (also available as `InputGroup`)
* **InputGroup.Input** - Input element component
* **InputGroup.Prefix** - Prefix container component
* **InputGroup.Suffix** - Suffix container component
#### InputGroup.Input Props
InputGroup.Input inherits all props from React Aria's [Input](https://react-spectrum.adobe.com/react-aria/Input.html) component.
| Prop | Type | Default | Description |
| -------------- | --------- | -------- | ------------------------------------------------------- |
| `className` | `string` | - | CSS classes for styling. |
| `isOnSurface` | `boolean` | - | Whether the input is displayed on a surface background. |
| `type` | `string` | `'text'` | Input type (text, password, email, etc.). |
| `value` | `string` | - | Current value (controlled). |
| `defaultValue` | `string` | - | Default value (uncontrolled). |
| `placeholder` | `string` | - | Placeholder text. |
| `disabled` | `boolean` | - | Whether the input is disabled. |
| `readOnly` | `boolean` | - | Whether the input is read-only. |
#### InputGroup.Prefix Props
| Prop | Type | Default | Description |
| ----------- | ----------------- | ------- | ----------------------------------------------------- |
| `children` | `React.ReactNode` | - | Content to display in the prefix (icons, text, etc.). |
| `className` | `string` | - | CSS classes for styling. |
#### InputGroup.Suffix Props
| Prop | Type | Default | Description |
| ----------- | ----------------- | ------- | ---------------------------------------------------------------- |
| `children` | `React.ReactNode` | - | Content to display in the suffix (icons, buttons, badges, etc.). |
| `className` | `string` | - | CSS classes for styling. |
### Usage Example
```tsx
import {InputGroup, TextField, Label, Button} from '@heroui/react';
import {Icon} from '@iconify/react';
function Example() {
return (
);
}
```
# InputOTP
**Category**: react
**URL**: https://v3.heroui.com/docs/react/components/input-otp
**Source**: https://raw.githubusercontent.com/heroui-inc/heroui/refs/heads/v3/apps/docs/content/docs/react/components/(forms)/input-otp.mdx
> A one-time password input component for verification codes and secure authentication
## Import
```tsx
import { InputOTP } from '@heroui/react';
```
### Usage
```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
);
}
```
### Anatomy
Import the InputOTP component and access all parts using dot notation.
```tsx
import { InputOTP } from '@heroui/react';
export default () => (
{/* ...rest of the slots */}
{/* ...rest of the slots */}
)
```
> **InputOTP** is built on top of [input-otp](https://github.com/guilhermerodz/input-otp) by [@guilherme\_rodz](https://twitter.com/guilherme_rodz), providing a flexible and accessible foundation for OTP input components.
### Four Digits
```tsx
import {InputOTP, Label} from "@heroui/react";
export function FourDigits() {
return (
);
}
```
### Disabled State
```tsx
import {Description, InputOTP, Label} from "@heroui/react";
export function Disabled() {
return (
Code verification is currently disabled
);
}
```
### With Pattern
Use the `pattern` prop to restrict input to specific characters. HeroUI exports common patterns like `REGEXP_ONLY_CHARS` and `REGEXP_ONLY_DIGITS`.
```tsx
import {Description, InputOTP, Label, REGEXP_ONLY_CHARS} from "@heroui/react";
export function WithPattern() {
return (
Only alphabetic characters are allowed
);
}
```
### Controlled
Control the value to synchronize with state, clear the input, or implement custom validation.
```tsx
"use client";
import {Description, InputOTP, Label} from "@heroui/react";
import React from "react";
export function Controlled() {
const [value, setValue] = React.useState("");
return (
);
}
```
### With Validation
Use `isInvalid` together with validation messages to surface errors.
```tsx
"use client";
import {Button, Description, Form, InputOTP, Label} from "@heroui/react";
import React from "react";
export function WithValidation() {
const [value, setValue] = React.useState("");
const [isInvalid, setIsInvalid] = React.useState(false);
const onSubmit = (e: React.FormEvent) => {
e.preventDefault();
const formData = new FormData(e.currentTarget);
const code = formData.get("code");
if (code !== "123456") {
setIsInvalid(true);
return;
}
setIsInvalid(false);
setValue("");
alert("Code verified successfully!");
};
const handleChange = (val: string) => {
setValue(val);
setIsInvalid(false);
};
return (
);
}
```
### On Complete
Use the `onComplete` callback to trigger actions when all slots are filled.
```tsx
"use client";
import {Button, Form, InputOTP, Label, Spinner} from "@heroui/react";
import React from "react";
export function OnComplete() {
const [value, setValue] = React.useState("");
const [isComplete, setIsComplete] = React.useState(false);
const [isSubmitting, setIsSubmitting] = React.useState(false);
const handleComplete = (code: string) => {
setIsComplete(true);
console.log("Code complete:", code);
};
const handleSubmit = (e: React.FormEvent) => {
e.preventDefault();
setIsSubmitting(true);
// Simulate API call
setTimeout(() => {
setIsSubmitting(false);
setValue("");
setIsComplete(false);
}, 2000);
};
return (
);
}
```
### Form Example
A complete two-factor authentication form with validation and submission.
```tsx
"use client";
import {Button, Description, Form, InputOTP, Label, Link, Spinner} from "@heroui/react";
import React from "react";
export function FormExample() {
const [value, setValue] = React.useState("");
const [error, setError] = React.useState("");
const [isSubmitting, setIsSubmitting] = React.useState(false);
const handleSubmit = (e: React.FormEvent) => {
e.preventDefault();
setError("");
if (value.length !== 6) {
setError("Please enter all 6 digits");
return;
}
setIsSubmitting(true);
// Simulate API call
setTimeout(() => {
if (value === "123456") {
console.log("Code verified successfully!");
setValue("");
} else {
setError("Invalid code. Please try again.");
}
setIsSubmitting(false);
}, 1500);
};
return (
);
}
```
### On Surface
When used inside a [Surface](/docs/components/surface) component, InputOTP automatically applies on-surface styling.
```tsx
import {InputOTP, Label, Link, Surface} from "@heroui/react";
export function OnSurface() {
return (
We've sent a code to a****@gmail.com
Didn't receive a code?
Resend
);
}
```
## Related Components
* **Input**: Single-line text input built on React Aria
* **Form**: Form validation and submission handling
* **Surface**: Base container surface
## Styling
### Passing Tailwind CSS classes
```tsx
import {InputOTP, Label} from '@heroui/react';
function CustomInputOTP() {
return (
);
}
```
### Customizing the component classes
To customize the InputOTP component classes, you can use the `@layer components` directive.
[Learn more](https://tailwindcss.com/docs/adding-custom-styles#adding-component-classes).
```css
@layer components {
.input-otp {
@apply gap-3;
}
.input-otp__slot {
@apply size-12 rounded-xl border-2 font-bold;
}
.input-otp__slot[data-active="true"] {
@apply border-primary-500 ring-2 ring-primary-200;
}
.input-otp__separator {
@apply w-2 h-1 bg-border-strong rounded-full;
}
}
```
HeroUI follows the [BEM](https://getbem.com/) methodology to ensure component variants and states are reusable and easy to customize.
### CSS Classes
The InputOTP component uses these CSS classes ([View source styles](https://github.com/heroui-inc/heroui/blob/v3/packages/styles/components/input-otp.css)):
#### Base Classes
* `.input-otp` - Base container
* `.input-otp__container` - Inner container from input-otp library
* `.input-otp__group` - Group of slots
* `.input-otp__slot` - Individual input slot
* `.input-otp__slot-value` - The character inside a slot
* `.input-otp__caret` - Blinking caret indicator
* `.input-otp__separator` - Visual separator between groups
#### State Classes
* `.input-otp__slot[data-active="true"]` - Currently active slot
* `.input-otp__slot[data-filled="true"]` - Slot with a character
* `.input-otp__slot[data-disabled="true"]` - Disabled slot
* `.input-otp__slot[data-invalid="true"]` - Invalid slot
* `.input-otp__container[data-disabled="true"]` - Disabled container
### Interactive States
The component supports both CSS pseudo-classes and data attributes for flexibility:
* **Hover**: `:hover` or `[data-hovered="true"]` on slot
* **Active**: `[data-active="true"]` on slot (currently focused)
* **Filled**: `[data-filled="true"]` on slot (contains a character)
* **Disabled**: `[data-disabled="true"]` on container and slots
* **Invalid**: `[data-invalid="true"]` on slots
## API Reference
### InputOTP Props
InputOTP is built on top of the [input-otp](https://github.com/guilhermerodz/input-otp) library with additional features.
#### Base Props
| Prop | Type | Default | Description |
| -------------------- | ------------------------- | ------- | ----------------------------------------------------------------- |
| `maxLength` | `number` | - | **Required.** Number of input slots. |
| `value` | `string` | - | Controlled value (uncontrolled if not provided). |
| `onChange` | `(value: string) => void` | - | Handler called when the value changes. |
| `onComplete` | `(value: string) => void` | - | Handler called when all slots are filled. |
| `className` | `string` | - | Additional CSS classes for the container. |
| `containerClassName` | `string` | - | CSS classes for the inner container. |
| `isOnSurface` | `boolean` | `false` | Whether the input is displayed on a surface (affects styling) |
| `children` | `React.ReactNode` | - | InputOTP.Group, InputOTP.Slot, and InputOTP.Separator components. |
#### Validation Props
| Prop | Type | Default | Description |
| ------------------- | --------------- | ------- | ----------------------------------------- |
| `isDisabled` | `boolean` | `false` | Whether the input is disabled. |
| `isInvalid` | `boolean` | `false` | Whether the input is in an invalid state. |
| `validationErrors` | `string[]` | - | Server-side or custom validation errors. |
| `validationDetails` | `ValidityState` | - | HTML5 validation details. |
#### Input Props
| Prop | Type | Default | Description |
| ------------------ | --------------------------------------------------------------------------- | ----------- | ------------------------------------------------------------------ |
| `pattern` | `string` | - | Regex pattern for allowed characters (e.g., `REGEXP_ONLY_DIGITS`). |
| `textAlign` | `'left' \| 'center' \| 'right'` | `'left'` | Text alignment within slots. |
| `inputMode` | `'numeric' \| 'text' \| 'decimal' \| 'tel' \| 'search' \| 'email' \| 'url'` | `'numeric'` | Virtual keyboard type on mobile devices. |
| `placeholder` | `string` | - | Placeholder text for empty slots. |
| `pasteTransformer` | `(text: string) => string` | - | Transform pasted text (e.g., remove hyphens). |
#### Form Props
| Prop | Type | Default | Description |
| ----------- | --------- | ------- | ----------------------------------------- |
| `name` | `string` | - | Name attribute for form submission. |
| `autoFocus` | `boolean` | - | Whether to focus the first slot on mount. |
### InputOTP.Group Props
| Prop | Type | Default | Description |
| ----------- | ----------------- | ------- | ------------------------------------- |
| `className` | `string` | - | Additional CSS classes for the group. |
| `children` | `React.ReactNode` | - | InputOTP.Slot components. |
### InputOTP.Slot Props
| Prop | Type | Default | Description |
| ----------- | -------- | ------- | ------------------------------------------- |
| `index` | `number` | - | **Required.** Zero-based index of the slot. |
| `className` | `string` | - | Additional CSS classes for the slot. |
### InputOTP.Separator Props
| Prop | Type | Default | Description |
| ----------- | -------- | ------- | ----------------------------------------- |
| `className` | `string` | - | Additional CSS classes for the separator. |
### Exported Patterns
HeroUI re-exports common regex patterns from input-otp for convenience:
```tsx
import { REGEXP_ONLY_DIGITS, REGEXP_ONLY_CHARS, REGEXP_ONLY_DIGITS_AND_CHARS } from '@heroui/react';
// Use with pattern prop
{/* ... */}
```
* **REGEXP\_ONLY\_DIGITS** - Only numeric characters (0-9)
* **REGEXP\_ONLY\_CHARS** - Only alphabetic characters (a-z, A-Z)
* **REGEXP\_ONLY\_DIGITS\_AND\_CHARS** - Alphanumeric characters (0-9, a-z, A-Z)
# Input
**Category**: react
**URL**: https://v3.heroui.com/docs/react/components/input
**Source**: https://raw.githubusercontent.com/heroui-inc/heroui/refs/heads/v3/apps/docs/content/docs/react/components/(forms)/input.mdx
> Primitive single-line text input component that accepts standard HTML attributes
## Import
```tsx
import { Input } from '@heroui/react';
```
For validation, labels, and error messages, see **[TextField](/docs/components/text-field)**.
### Usage
```tsx
import {Input} from "@heroui/react";
export function Basic() {
return ;
}
```
### Input Types
```tsx
import {Input, Label} from "@heroui/react";
export function Types() {
return (
);
}
```
### Controlled
```tsx
"use client";
import {Input} from "@heroui/react";
import React from "react";
export function Controlled() {
const [value, setValue] = React.useState("heroui.com");
return (
);
}
```
### Full Width
```tsx
import {Input} from "@heroui/react";
export function FullWidth() {
return (
);
}
```
### On Surface
When used inside a [Surface](/docs/components/surface) component, Input automatically applies on-surface styling.
```tsx
import {Input, Surface} from "@heroui/react";
export function OnSurface() {
return (
);
}
```
## Related Components
* **TextField**: Composition-friendly fields with labels and validation
* **TextArea**: Multiline text input with focus management
* **Label**: Accessible label for form controls
## Styling
### Passing Tailwind CSS classes
```tsx
import {Input, Label} from '@heroui/react';
function CustomInput() {
return (
);
}
```
### Customizing the component classes
The base class `.input` powers every instance. Override it once with `@layer components`.
```css
@layer components {
.input {
@apply rounded-lg border border-border bgsurface px-4 py-2 text-sm shadow-sm transition-colors;
&:hover,
&[data-hovered="true"] {
@apply bg-surface-secondary border-border/80;
}
&:focus-visible,
&[data-focus-visible="true"] {
@apply border-primary ring-2 ring-primary/20;
}
&[data-invalid="true"] {
@apply border-danger bg-danger-50/10 text-danger;
}
}
}
```
### CSS Classes
* `.input` – Native input element styling
### Interactive States
* **Hover**: `:hover` or `[data-hovered="true"]`
* **Focus Visible**: `:focus-visible` or `[data-focus-visible="true"]`
* **Invalid**: `[data-invalid="true"]` (also syncs with `aria-invalid`)
* **Disabled**: `:disabled` or `[aria-disabled="true"]`
* **Read Only**: `[aria-readonly="true"]`
## API Reference
### Input Props
Input accepts all standard HTML `` attributes plus the following:
| Prop | Type | Default | Description |
| -------------- | ------------------------------------------------------ | -------- | ------------------------------------------------------------- |
| `className` | `string` | - | Tailwind classes merged with the component styles. |
| `type` | `string` | `"text"` | Input type (text, email, password, number, etc.). |
| `value` | `string` | - | Controlled value. |
| `defaultValue` | `string` | - | Uncontrolled initial value. |
| `onChange` | `(event: React.ChangeEvent) => void` | - | Change handler. |
| `placeholder` | `string` | - | Placeholder text. |
| `disabled` | `boolean` | `false` | Disables the input. |
| `readOnly` | `boolean` | `false` | Makes the input read-only. |
| `required` | `boolean` | `false` | Marks the input as required. |
| `name` | `string` | - | Name for form submission. |
| `autoComplete` | `string` | - | Autocomplete hint for the browser. |
| `maxLength` | `number` | - | Maximum number of characters. |
| `minLength` | `number` | - | Minimum number of characters. |
| `pattern` | `string` | - | Regex pattern for validation. |
| `min` | `number \| string` | - | Minimum value (for number/date inputs). |
| `max` | `number \| string` | - | Maximum value (for number/date inputs). |
| `step` | `number \| string` | - | Stepping interval (for number inputs). |
| `fullWidth` | `boolean` | `false` | Whether the input should take full width of its container |
| `isOnSurface` | `boolean` | `false` | Whether the input is displayed on a surface (affects styling) |
> For validation props like `isInvalid`, `isRequired`, and error handling, use **[TextField](/docs/components/text-field)** with Input as a child component.
# Label
**Category**: react
**URL**: https://v3.heroui.com/docs/react/components/label
**Source**: https://raw.githubusercontent.com/heroui-inc/heroui/refs/heads/v3/apps/docs/content/docs/react/components/(forms)/label.mdx
> Renders an accessible label associated with form controls
## Import
```tsx
import { Label } from '@heroui/react';
```
## Usage
```tsx
import {Input, Label} from "@heroui/react";
export function Basic() {
return (
);
}
```
## Related Components
* **Input**: Single-line text input built on React Aria
* **TextArea**: Multiline text input with focus management
* **Fieldset**: Group related form controls with legends
## API
### Label Props
| Prop | Type | Default | Description |
| ------------ | ----------- | ------- | -------------------------------------------------- |
| `htmlFor` | `string` | - | The id of the element the label is associated with |
| `isRequired` | `boolean` | `false` | Whether to display a required indicator |
| `isDisabled` | `boolean` | `false` | Whether the label is in a disabled state |
| `isInvalid` | `boolean` | `false` | Whether the label is in an invalid state |
| `className` | `string` | - | Additional CSS classes |
| `children` | `ReactNode` | - | The content of the label |
## Accessibility
The Label component is built on the native HTML `
# NumberField
**Category**: react
**URL**: https://v3.heroui.com/docs/react/components/number-field
**Source**: https://raw.githubusercontent.com/heroui-inc/heroui/refs/heads/v3/apps/docs/content/docs/react/components/(forms)/number-field.mdx
> Number input fields with increment/decrement buttons, validation, and internationalized formatting
## Import
```tsx
import { NumberField } from '@heroui/react';
```
### Usage
```tsx
import {Label, NumberField} from "@heroui/react";
export function Basic() {
return (
Width
);
}
```
### Anatomy
```tsx
import {NumberField, Label, Description, FieldError} from '@heroui/react';
export default () => (
)
```
> **NumberField** allows users to enter numeric values with optional increment/decrement buttons. It supports internationalized formatting, validation, and keyboard navigation.
### With Description
```tsx
import {Description, Label, NumberField} from "@heroui/react";
export function WithDescription() {
return (
WidthEnter the width in pixelsPercentageValue must be between 0 and 100
);
}
```
### Required Field
```tsx
import {Description, Label, NumberField} from "@heroui/react";
export function Required() {
return (
QuantityRatingRate from 1 to 10
);
}
```
### Validation
Use `isInvalid` together with `FieldError` to surface validation messages.
```tsx
import {FieldError, Label, NumberField} from "@heroui/react";
export function Validation() {
return (
QuantityQuantity must be greater than or equal to 0PercentagePercentage must be between 0 and 100
);
}
```
### Controlled
Control the value to synchronize with other components or perform custom formatting.
```tsx
"use client";
import {Button, Description, Label, NumberField} from "@heroui/react";
import React from "react";
export function Controlled() {
const [value, setValue] = React.useState(1024);
return (
WidthCurrent value: {value}
);
}
```
### With Validation
Implement custom validation logic with controlled values.
```tsx
"use client";
import {Description, FieldError, Label, NumberField} from "@heroui/react";
import React from "react";
export function WithValidation() {
const [value, setValue] = React.useState(undefined);
const isInvalid = value !== undefined && (value < 0 || value > 100);
return (
Percentage
{isInvalid ? (
Percentage must be between 0 and 100
) : (
Enter a value between 0 and 100
)}
);
}
```
### Step Values
Configure increment/decrement step values for precise control.
```tsx
import {Description, Label, NumberField} from "@heroui/react";
export function WithStep() {
return (
Step: 1Increments by 1Step: 5Increments by 5Step: 10Increments by 10
);
}
```
### Format Options
Format numbers as currency, percentages, decimals, or units with internationalization support.
```tsx
import {Description, Label, NumberField} from "@heroui/react";
export function WithFormatOptions() {
return (
Currency (EUR - Accounting)Accounting format with EUR currencyCurrency (USD)Standard USD currency formatPercentagePercentage format (0-1, where 0.5 = 50%)Decimal (2 decimal places)Decimal format with 2 decimal placesUnit (Kilograms)Unit format with kilograms
);
}
```
### Custom Icons
Customize the increment and decrement button icons.
```tsx
import {Description, Label, NumberField} from "@heroui/react";
export function CustomIcons() {
return (
Width (Custom Icons)Custom icon children
);
}
```
### With Chevrons
Use chevron icons in a vertical layout for a different visual style.
```tsx
import {Label, NumberField} from "@heroui/react";
export function WithChevrons() {
return (
Number field with chevrons
);
}
```
### Disabled State
```tsx
import {Description, Label, NumberField} from "@heroui/react";
export function Disabled() {
return (
WidthEnter the width in pixelsPercentageValue must be between 0 and 100
);
}
```
### Full Width
```tsx
import {Label, NumberField} from "@heroui/react";
export function FullWidth() {
return (
Width
);
}
```
### On Surface
When used inside a [Surface](/docs/components/surface) component, NumberField automatically applies on-surface styling.
```tsx
import {Description, Label, NumberField, Surface} from "@heroui/react";
export function OnSurface() {
return (
WidthEnter the width in pixelsPercentageValue must be between 0 and 100
);
}
```
### Form Example
Complete form integration with validation and submission handling.
```tsx
"use client";
import {Button, Description, FieldError, Form, Label, NumberField, Spinner} from "@heroui/react";
import React from "react";
export function FormExample() {
const [value, setValue] = React.useState(undefined);
const [isSubmitting, setIsSubmitting] = React.useState(false);
const STOCK_AVAILABLE = 3;
const isOutOfStock = value !== undefined && value > STOCK_AVAILABLE;
const handleSubmit = (e: React.FormEvent) => {
e.preventDefault();
if (value === undefined || value === null || value < 1 || value > STOCK_AVAILABLE) {
return;
}
setIsSubmitting(true);
// Simulate API call
setTimeout(() => {
console.log("Order submitted:", {quantity: value});
setValue(undefined);
setIsSubmitting(false);
}, 1500);
};
return (
);
}
```
## Related Components
* **Label**: Accessible label for form controls
* **Description**: Helper text for form fields
* **FieldError**: Inline validation messages for form fields
## Styling
### Passing Tailwind CSS classes
```tsx
import {NumberField, Label} from '@heroui/react';
function CustomNumberField() {
return (
Quantity
);
}
```
### Customizing the component classes
NumberField uses CSS classes that can be customized. Override the component classes to match your design system.
```css
@layer components {
.number-field {
@apply flex flex-col gap-1;
}
/* When invalid, the description is hidden automatically */
.number-field[data-invalid="true"] [data-slot="description"],
.number-field[aria-invalid="true"] [data-slot="description"] {
@apply hidden;
}
.number-field__group {
@apply bg-field text-field-foreground shadow-field rounded-field inline-flex h-9 items-center overflow-hidden border;
}
.number-field__input {
@apply flex-1 rounded-none border-0 bg-transparent px-3 py-2 tabular-nums;
}
.number-field__increment-button,
.number-field__decrement-button {
@apply flex h-full w-10 items-center justify-center rounded-none bg-transparent;
}
}
```
### CSS Classes
* `.number-field` – Root container with minimal styling (`flex flex-col gap-1`)
* `.number-field__group` – Container for input and buttons with border and background styling
* `.number-field__input` – The numeric input field
* `.number-field__increment-button` – Button to increment the value
* `.number-field__decrement-button` – Button to decrement the value
* `.number-field__group--on-surface` – Applied when used inside a Surface component
> **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.
### Interactive States
NumberField automatically manages these data attributes based on its state:
* **Invalid**: `[data-invalid="true"]` or `[aria-invalid="true"]` - Automatically hides the description slot when invalid
* **Disabled**: `[data-disabled="true"]` - Applied when `isDisabled` is true
* **Focus Within**: `[data-focus-within="true"]` - Applied when the input or buttons are focused
* **Focus Visible**: `[data-focus-visible="true"]` - Applied when focus is visible (keyboard navigation)
* **Hovered**: `[data-hovered="true"]` - Applied when hovering over buttons
Additional attributes are available through render props (see NumberFieldRenderProps below).
## API Reference
### NumberField Props
NumberField inherits all props from React Aria's [NumberField](https://react-spectrum.adobe.com/react-aria/NumberField.html) component.
#### Base Props
| Prop | Type | Default | Description |
| ------------- | -------------------------------------------------------------------------------- | ------- | ---------------------------------------------------------------------- |
| `children` | `React.ReactNode \| (values: NumberFieldRenderProps) => React.ReactNode` | - | Child components (Label, Group, Input, etc.) or render function. |
| `className` | `string \| (values: NumberFieldRenderProps) => string` | - | CSS classes for styling, supports render props. |
| `style` | `React.CSSProperties \| (values: NumberFieldRenderProps) => React.CSSProperties` | - | Inline styles, supports render props. |
| `fullWidth` | `boolean` | `false` | Whether the number field should take full width of its container |
| `id` | `string` | - | The element's unique identifier. |
| `isOnSurface` | `boolean` | - | Whether the field is on a surface (auto-detected when inside Surface). |
#### Value Props
| Prop | Type | Default | Description |
| -------------- | -------------------------------------- | ------- | -------------------------------------- |
| `value` | `number` | - | Current value (controlled). |
| `defaultValue` | `number` | - | Default value (uncontrolled). |
| `onChange` | `(value: number \| undefined) => void` | - | Handler called when the value changes. |
#### Formatting Props
| Prop | Type | Default | Description |
| --------------- | -------------------------- | ------- | ------------------------------------------------------------------ |
| `formatOptions` | `Intl.NumberFormatOptions` | - | Options for formatting numbers (currency, percent, decimal, unit). |
| `locale` | `string` | - | Locale for number formatting. |
#### 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: number) => ValidationError \| true \| null \| undefined` | - | Custom validation function. |
| `validationBehavior` | `'native' \| 'aria'` | `'native'` | Whether to use native HTML form validation or ARIA attributes. |
| `validationErrors` | `string[]` | - | Server-side validation errors. |
#### Range Props
| Prop | Type | Default | Description |
| ---------- | -------- | ------- | ---------------------------------------------- |
| `minValue` | `number` | - | Minimum allowed value. |
| `maxValue` | `number` | - | Maximum allowed value. |
| `step` | `number` | `1` | Step value for increment/decrement operations. |
#### State Props
| Prop | Type | Default | Description |
| ------------ | --------- | ------- | -------------------------------------------------- |
| `isDisabled` | `boolean` | - | Whether the input is disabled. |
| `isReadOnly` | `boolean` | - | Whether the input can be selected but not changed. |
#### 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
NumberField works with these separate components that should be imported and used directly:
* **NumberField.Group** - Container for input and buttons
* **NumberField.Input** - The numeric input field
* **NumberField.IncrementButton** - Button to increment the value
* **NumberField.DecrementButton** - Button to decrement the value
* **Label** - Field label 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 NumberField for composition:
```tsx
QuantityEnter a value between 0 and 100Value must be between 0 and 100
```
#### NumberField.Group Props
NumberField.Group inherits props from React Aria's [Group](https://react-spectrum.adobe.com/react-aria/Group.html) component.
| Prop | Type | Default | Description |
| ----------- | ------------------------------------------------------------------ | ------- | ----------------------------------------------------- |
| `children` | `React.ReactNode \| (values: GroupRenderProps) => React.ReactNode` | - | Child components (Input, Buttons) or render function. |
| `className` | `string \| (values: GroupRenderProps) => string` | - | CSS classes for styling. |
#### NumberField.Input Props
NumberField.Input inherits props from React Aria's [Input](https://react-spectrum.adobe.com/react-aria/Input.html) component.
| Prop | Type | Default | Description |
| ------------- | --------- | ------- | ---------------------------------------------------------------------- |
| `className` | `string` | - | CSS classes for styling. |
| `isOnSurface` | `boolean` | - | Whether the input is on a surface (auto-detected when inside Surface). |
#### NumberField.IncrementButton Props
NumberField.IncrementButton inherits props from React Aria's [Button](https://react-spectrum.adobe.com/react-aria/Button.html) component.
| Prop | Type | Default | Description |
| ----------- | ----------------- | -------------- | ------------------------------------------------------ |
| `children` | `React.ReactNode` | `` | Icon or content for the button. Defaults to plus icon. |
| `className` | `string` | - | CSS classes for styling. |
| `slot` | `"increment"` | `"increment"` | Must be set to "increment" (automatically set). |
#### NumberField.DecrementButton Props
NumberField.DecrementButton inherits props from React Aria's [Button](https://react-spectrum.adobe.com/react-aria/Button.html) component.
| Prop | Type | Default | Description |
| ----------- | ----------------- | --------------- | ------------------------------------------------------- |
| `children` | `React.ReactNode` | `` | Icon or content for the button. Defaults to minus icon. |
| `className` | `string` | - | CSS classes for styling. |
| `slot` | `"decrement"` | `"decrement"` | Must be set to "decrement" (automatically set). |
### NumberFieldRenderProps
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 (DEPRECATED - use `isFocusWithin`). |
| `isFocusWithin` | `boolean` | Whether any child element is focused. |
| `isFocusVisible` | `boolean` | Whether focus is visible (keyboard navigation). |
| `value` | `number \| undefined` | Current value. |
| `minValue` | `number \| undefined` | Minimum allowed value. |
| `maxValue` | `number \| undefined` | Maximum allowed value. |
| `step` | `number` | Step value for increment/decrement. |
# RadioGroup
**Category**: react
**URL**: https://v3.heroui.com/docs/react/components/radio-group
**Source**: https://raw.githubusercontent.com/heroui-inc/heroui/refs/heads/v3/apps/docs/content/docs/react/components/(forms)/radio-group.mdx
> Radio group for selecting a single option from a list
## Import
```tsx
import { RadioGroup, Radio } from '@heroui/react';
```
### Usage
```tsx
import {Description, Label, Radio, RadioGroup} from "@heroui/react";
export function Basic() {
return (
Plan selectionChoose the plan that suits you bestBasic PlanIncludes 100 messages per monthPremium PlanIncludes 200 messages per monthBusiness PlanUnlimited messages
);
}
```
### Anatomy
Import the RadioGroup component and access all parts using dot notation.
```tsx
import {RadioGroup, Radio, Label, Description, FieldError} from '@heroui/react';
export default () => (
✓ {/* Custom indicator (optional) */}
)
```
### Custom Indicator
```tsx
"use client";
import {Description, Label, Radio, RadioGroup} from "@heroui/react";
export function CustomIndicator() {
return (
Plan selectionChoose the plan that suits you best
{({isSelected}) =>
isSelected ? ✓ : null
}
Basic PlanIncludes 100 messages per month
{({isSelected}) =>
isSelected ? ✓ : null
}
Premium PlanIncludes 200 messages per month
{({isSelected}) =>
isSelected ? ✓ : null
}
Business PlanUnlimited messages
);
}
```
### Horizontal Orientation
```tsx
import {Description, Label, Radio, RadioGroup} from "@heroui/react";
export function Horizontal() {
return (
Subscription planStarterFor side projectsProAdvanced reportingTeamsUp to 10 teammates
);
}
```
### Controlled
```tsx
"use client";
import {Description, Label, Radio, RadioGroup} from "@heroui/react";
import React from "react";
export function Controlled() {
const [value, setValue] = React.useState("pro");
return (
Subscription planStarterFor side projects and small teamsProAdvanced reporting and analyticsTeamsShare access with up to 10 teammates
Selected plan: {value}
);
}
```
### Uncontrolled
Combine `defaultValue` with `onChange` when you only need to react to updates.
```tsx
"use client";
import {Description, Label, Radio, RadioGroup} from "@heroui/react";
import React from "react";
export function Uncontrolled() {
const [selection, setSelection] = React.useState("pro");
return (
setSelection(nextValue)}
>
Subscription planStarterFor side projects and small teamsProAdvanced reporting and analyticsTeamsShare access with up to 10 teammates
Last chosen plan: {selection}
);
}
```
### Validation
```tsx
"use client";
import {Button, Description, FieldError, Form, Label, Radio, RadioGroup} from "@heroui/react";
import React from "react";
export function Validation() {
const [message, setMessage] = React.useState(null);
return (
);
}
```
### Disabled
```tsx
import {Description, Label, Radio, RadioGroup} from "@heroui/react";
export function Disabled() {
return (
Subscription planPlan changes are temporarily paused while we roll out updates.StarterFor side projects and small teamsProAdvanced reporting and analyticsTeamsShare access with up to 10 teammates
);
}
```
### On Surface
When used inside a [Surface](/docs/components/surface) component, RadioGroup automatically applies on-surface styling.
```tsx
import {Description, Label, Radio, RadioGroup, Surface} from "@heroui/react";
export function OnSurface() {
return (
Plan selectionChoose the plan that suits you bestBasic PlanIncludes 100 messages per monthPremium PlanIncludes 200 messages per monthBusiness PlanUnlimited messages
);
}
```
### Delivery & Payment
## Related Components
* **Fieldset**: Group related form controls with legends
* **Surface**: Base container surface
* **Description**: Helper text for form fields
## Styling
### Passing Tailwind CSS classes
```tsx
import { RadioGroup, Radio } from '@heroui/react';
export default () => (
Basic Plan
Premium Plan
Business Plan
);
```
### Customizing the component classes
To customize the RadioGroup component classes, you can use the `@layer components` directive.
[Learn more](https://tailwindcss.com/docs/adding-custom-styles#adding-component-classes).
```css
@layer components {
.radio-group {
@apply gap-2;
}
.radio {
@apply gap-4 rounded-lg border border-border p-3 hover:bg-surface-hovered;
}
.radio__control {
@apply border-2 border-primary;
}
.radio__indicator {
@apply bg-primary;
}
.radio__content {
@apply gap-1;
}
}
```
HeroUI follows the [BEM](https://getbem.com/) methodology to ensure component variants and states are reusable and easy to customize.
### CSS Classes
The RadioGroup component uses these CSS classes ([View source styles](https://github.com/heroui-inc/heroui/blob/v3/packages/styles/components/radio-group.css)):
#### Base Classes
* `.radio-group` - Base radio group container
* `.radio` - Individual radio item
* `.radio__control` - Radio control (circular button)
* `.radio__indicator` - Radio indicator (inner dot)
* `.radio__content` - Radio content wrapper
#### Modifier Classes
* `.radio--disabled` - Disabled radio state
### Interactive States
The radio supports both CSS pseudo-classes and data attributes for flexibility:
* **Selected**: `[aria-checked="true"]` or `[data-selected="true"]` (indicator appears)
* **Hover**: `:hover` or `[data-hovered="true"]` (border color changes)
* **Focus**: `:focus-visible` or `[data-focus-visible="true"]` (shows focus ring)
* **Pressed**: `:active` or `[data-pressed="true"]` (scale transform)
* **Disabled**: `:disabled` or `[aria-disabled="true"]` (reduced opacity, no pointer events)
* **Invalid**: `[data-invalid="true"]` or `[aria-invalid="true"]` (error border color)
## API Reference
### RadioGroup Props
| Prop | Type | Default | Description |
| -------------- | ----------------------------------------------------------------------- | ------------ | ------------------------------------------------------------------- |
| `value` | `string` | - | The current value (controlled) |
| `defaultValue` | `string` | - | The default value (uncontrolled) |
| `onChange` | `(value: string) => void` | - | Handler called when the value changes |
| `isDisabled` | `boolean` | `false` | Whether the radio group is disabled |
| `isRequired` | `boolean` | `false` | Whether the radio group is required |
| `isReadOnly` | `boolean` | `false` | Whether the radio group is read only |
| `isInvalid` | `boolean` | `false` | Whether the radio group is in an invalid state |
| `isOnSurface` | `boolean` | `false` | Whether the radio group is displayed on a surface (affects styling) |
| `name` | `string` | - | The name of the radio group, used when submitting an HTML form |
| `orientation` | `'horizontal' \| 'vertical'` | `'vertical'` | The orientation of the radio group |
| `children` | `React.ReactNode \| (values: RadioGroupRenderProps) => React.ReactNode` | - | Radio group content or render prop |
### Radio Props
| Prop | Type | Default | Description |
| ------------ | ------------------------------------------------------------------ | ------- | --------------------------------------------------------------- |
| `value` | `string` | - | The value of the radio button |
| `isDisabled` | `boolean` | `false` | Whether the radio button is disabled |
| `name` | `string` | - | The name of the radio button, used when submitting an HTML form |
| `children` | `React.ReactNode \| (values: RadioRenderProps) => React.ReactNode` | - | Radio content or render prop |
### Radio.Control Props
Extends `React.HTMLAttributes`.
| Prop | Type | Default | Description |
| ---------- | ----------------- | ------- | ---------------------------------------------------------------------------- |
| `children` | `React.ReactNode` | - | The content to render inside the control wrapper (typically Radio.Indicator) |
### Radio.Indicator Props
Extends `React.HTMLAttributes`.
| Prop | Type | Default | Description |
| ---------- | ------------------------------------------------------------------ | ------- | ---------------------------------------------------------------------- |
| `children` | `React.ReactNode \| (values: RadioRenderProps) => React.ReactNode` | - | Optional content or render prop that receives the current radio state. |
### Radio.Content Props
Extends `React.HTMLAttributes`.
| Prop | Type | Default | Description |
| ---------- | ----------------- | ------- | ---------------------------------------------------------------------------------- |
| `children` | `React.ReactNode` | - | The content to render inside the content wrapper (typically Label and Description) |
### RadioRenderProps
When using the render prop pattern, these values are provided:
| Prop | Type | Description |
| ---------------- | --------- | ---------------------------------------- |
| `isSelected` | `boolean` | Whether the radio is currently selected |
| `isHovered` | `boolean` | Whether the radio is hovered |
| `isPressed` | `boolean` | Whether the radio is currently pressed |
| `isFocused` | `boolean` | Whether the radio is focused |
| `isFocusVisible` | `boolean` | Whether the radio is keyboard focused |
| `isDisabled` | `boolean` | Whether the radio is disabled |
| `isReadOnly` | `boolean` | Whether the radio is read only |
| `isInvalid` | `boolean` | Whether the radio is in an invalid state |
# SearchField
**Category**: react
**URL**: https://v3.heroui.com/docs/react/components/search-field
**Source**: https://raw.githubusercontent.com/heroui-inc/heroui/refs/heads/v3/apps/docs/content/docs/react/components/(forms)/search-field.mdx
> Search input field with clear button and search icon
## Import
```tsx
import { SearchField } from '@heroui/react';
```
### Usage
```tsx
import {Label, SearchField} from "@heroui/react";
export function Basic() {
return (
Search
);
}
```
### Anatomy
```tsx
import {SearchField, Label, Description, FieldError} from '@heroui/react';
export default () => (
)
```
> **SearchField** allows users to enter and clear a search query. It includes a search icon and an optional clear button for easy reset.
### With Description
```tsx
import {Description, Label, SearchField} from "@heroui/react";
export function WithDescription() {
return (
Search productsEnter keywords to search for productsSearch usersSearch by name, email, or username
);
}
```
### Required Field
```tsx
import {Description, Label, SearchField} from "@heroui/react";
export function Required() {
return (
SearchSearch queryMinimum 3 characters required
);
}
```
### Validation
Use `isInvalid` together with `FieldError` to surface validation messages.
```tsx
import {FieldError, Label, SearchField} from "@heroui/react";
export function Validation() {
return (
SearchSearch query must be at least 3 charactersSearchInvalid characters in search query
);
}
```
### Disabled State
```tsx
import {Description, Label, SearchField} from "@heroui/react";
export function Disabled() {
return (
SearchThis search field is disabledSearchThis search field is disabled
);
}
```
### Controlled
Control the value to synchronize with other components or perform custom formatting.
```tsx
"use client";
import {Button, Description, Label, SearchField} from "@heroui/react";
import React from "react";
export function Controlled() {
const [value, setValue] = React.useState("");
return (
SearchCurrent value: {value || "(empty)"}
);
}
```
### With Validation
Implement custom validation logic with controlled values.
```tsx
"use client";
import {Description, FieldError, Label, SearchField} from "@heroui/react";
import React from "react";
export function WithValidation() {
const [value, setValue] = React.useState("");
const isInvalid = value.length > 0 && value.length < 3;
return (
Search
{isInvalid ? (
Search query must be at least 3 characters
) : (
Enter at least 3 characters to search
)}
);
}
```
### Custom Icons
Customize the search icon and clear button icons.
```tsx
import {Description, Label, SearchField} from "@heroui/react";
export function CustomIcons() {
return (
Search (Custom Icons)Custom icon children
);
}
```
### Full Width
```tsx
import {Label, SearchField} from "@heroui/react";
export function FullWidth() {
return (
Search
);
}
```
### On Surface
When used inside a [Surface](/docs/components/surface) component, SearchField automatically applies on-surface styling.
```tsx
import {Description, Label, SearchField, Surface} from "@heroui/react";
export function OnSurface() {
return (
SearchEnter keywords to searchAdvanced searchUse filters to refine your search
);
}
```
### Form Example
Complete form integration with validation and submission handling.
```tsx
"use client";
import {Button, Description, FieldError, Form, Label, SearchField, Spinner} from "@heroui/react";
import React from "react";
export function FormExample() {
const [value, setValue] = React.useState("");
const [isSubmitting, setIsSubmitting] = React.useState(false);
const MIN_LENGTH = 3;
const isInvalid = value.length > 0 && value.length < MIN_LENGTH;
const handleSubmit = (e: React.FormEvent) => {
e.preventDefault();
if (value.length < MIN_LENGTH) {
return;
}
setIsSubmitting(true);
// Simulate API call
setTimeout(() => {
console.log("Search submitted:", {query: value});
setValue("");
setIsSubmitting(false);
}, 1500);
};
return (
);
}
```
### With Keyboard Shortcut
Add keyboard shortcuts to quickly focus the search field.
```tsx
"use client";
import {Description, Kbd, Label, SearchField} from "@heroui/react";
import React from "react";
export function WithKeyboardShortcut() {
const inputRef = React.useRef(null);
const [value, setValue] = React.useState("");
React.useEffect(() => {
const handleKeyDown = (e: KeyboardEvent) => {
// Check for Shift+S
if (e.shiftKey && e.key === "S" && !e.metaKey && !e.ctrlKey && !e.altKey) {
e.preventDefault();
inputRef.current?.focus();
}
// Check for ESC key to blur the input
if (e.key === "Escape" && document.activeElement === inputRef.current) {
inputRef.current?.blur();
}
};
// Add global event listener
window.addEventListener("keydown", handleKeyDown);
// Cleanup on unmount
return () => {
window.removeEventListener("keydown", handleKeyDown);
};
}, []);
return (
SearchUse keyboard shortcut to quickly focus this field
PressSto focus the search field
);
}
```
## Related Components
* **Label**: Accessible label for form controls
* **Description**: Helper text for form fields
* **FieldError**: Inline validation messages for form fields
## Styling
### Passing Tailwind CSS classes
```tsx
import {SearchField, Label} from '@heroui/react';
function CustomSearchField() {
return (
Search
);
}
```
### Customizing the component classes
SearchField uses CSS classes that can be customized. Override the component classes to match your design system.
```css
@layer components {
.search-field {
@apply flex flex-col gap-1;
}
/* When invalid, the description is hidden automatically */
.search-field[data-invalid],
.search-field[aria-invalid] {
[data-slot="description"] {
@apply hidden;
}
}
.search-field__group {
@apply bg-field text-field-foreground shadow-field rounded-field inline-flex h-9 items-center overflow-hidden border;
}
.search-field__input {
@apply flex-1 rounded-none border-0 bg-transparent px-3 py-2 shadow-none outline-none;
}
.search-field__search-icon {
@apply text-field-placeholder pointer-events-none shrink-0 ml-3 mr-0 size-4;
}
.search-field__clear-button {
@apply mr-1 shrink-0;
}
}
```
### CSS Classes
* `.search-field` – Root container with minimal styling (`flex flex-col gap-1`)
* `.search-field__group` – Container for search icon, input, and clear button with border and background styling
* `.search-field__input` – The search input field
* `.search-field__search-icon` – The search icon displayed on the left
* `.search-field__clear-button` – Button to clear the search field
* `.search-field__group--on-surface` – Applied when used inside a Surface component
> **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.
### Interactive States
SearchField automatically manages these data attributes based on its state:
* **Invalid**: `[data-invalid="true"]` or `[aria-invalid="true"]` - Automatically hides the description slot when invalid
* **Disabled**: `[data-disabled="true"]` - Applied when `isDisabled` is true
* **Focus Within**: `[data-focus-within="true"]` - Applied when the input is focused
* **Focus Visible**: `[data-focus-visible="true"]` - Applied when focus is visible (keyboard navigation)
* **Hovered**: `[data-hovered="true"]` - Applied when hovering over the group
* **Empty**: `[data-empty="true"]` - Applied when the field is empty (hides clear button)
Additional attributes are available through render props (see SearchFieldRenderProps below).
## API Reference
### SearchField Props
SearchField inherits all props from React Aria's [SearchField](https://react-spectrum.adobe.com/react-aria/SearchField.html) component.
#### Base Props
| Prop | Type | Default | Description |
| ------------- | -------------------------------------------------------------------------------- | ------- | ---------------------------------------------------------------------- |
| `children` | `React.ReactNode \| (values: SearchFieldRenderProps) => React.ReactNode` | - | Child components (Label, Group, Input, etc.) or render function. |
| `className` | `string \| (values: SearchFieldRenderProps) => string` | - | CSS classes for styling, supports render props. |
| `style` | `React.CSSProperties \| (values: SearchFieldRenderProps) => React.CSSProperties` | - | Inline styles, supports render props. |
| `fullWidth` | `boolean` | `false` | Whether the search field should take full width of its container |
| `id` | `string` | - | The element's unique identifier. |
| `isOnSurface` | `boolean` | - | Whether the field is on a surface (auto-detected when inside Surface). |
#### Value Props
| Prop | Type | Default | Description |
| -------------- | ------------------------- | ------- | -------------------------------------- |
| `value` | `string` | - | Current value (controlled). |
| `defaultValue` | `string` | - | Default value (uncontrolled). |
| `onChange` | `(value: string) => void` | - | Handler called when the value changes. |
#### 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: string) => ValidationError \| true \| null \| undefined` | - | Custom validation function. |
| `validationBehavior` | `'native' \| 'aria'` | `'native'` | Whether to use native HTML form validation or ARIA attributes. |
| `validationErrors` | `string[]` | - | Server-side validation errors. |
#### State Props
| Prop | Type | Default | Description |
| ------------ | --------- | ------- | -------------------------------------------------- |
| `isDisabled` | `boolean` | - | Whether the input is disabled. |
| `isReadOnly` | `boolean` | - | Whether the input can be selected but not changed. |
#### 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. |
#### Event Props
| Prop | Type | Default | Description |
| ---------- | ------------------------- | ------- | ------------------------------------------------------------ |
| `onSubmit` | `(value: string) => void` | - | Handler called when the user submits the search (Enter key). |
| `onClear` | `() => void` | - | Handler called when the clear button is pressed. |
#### 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
SearchField works with these separate components that should be imported and used directly:
* **SearchField.Group** - Container for search icon, input, and clear button
* **SearchField.Input** - The search input field
* **SearchField.SearchIcon** - The search icon displayed on the left
* **SearchField.ClearButton** - Button to clear the search field
* **Label** - Field label 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 SearchField for composition:
```tsx
SearchEnter keywords to searchSearch query is required
```
#### SearchField.Group Props
SearchField.Group inherits props from React Aria's [Group](https://react-spectrum.adobe.com/react-aria/Group.html) component.
| Prop | Type | Default | Description |
| ----------- | ------------------------------------------------------------------ | ------- | --------------------------------------------------------------------- |
| `children` | `React.ReactNode \| (values: GroupRenderProps) => React.ReactNode` | - | Child components (SearchIcon, Input, ClearButton) or render function. |
| `className` | `string \| (values: GroupRenderProps) => string` | - | CSS classes for styling. |
#### SearchField.Input Props
SearchField.Input inherits props from React Aria's [Input](https://react-spectrum.adobe.com/react-aria/Input.html) component.
| Prop | Type | Default | Description |
| ------------- | --------- | ---------- | ---------------------------------------------------------------------- |
| `className` | `string` | - | CSS classes for styling. |
| `isOnSurface` | `boolean` | - | Whether the input is on a surface (auto-detected when inside Surface). |
| `placeholder` | `string` | - | Placeholder text displayed when the input is empty. |
| `type` | `string` | `"search"` | Input type (automatically set to "search"). |
#### SearchField.SearchIcon Props
SearchField.SearchIcon is a custom component that renders the search icon.
| Prop | Type | Default | Description |
| ----------- | ----------------- | ---------------- | --------------------------------------------- |
| `children` | `React.ReactNode` | `` | Custom icon element. Defaults to search icon. |
| `className` | `string` | - | CSS classes for styling. |
#### SearchField.ClearButton Props
SearchField.ClearButton inherits props from React Aria's [Button](https://react-spectrum.adobe.com/react-aria/Button.html) component.
| Prop | Type | Default | Description |
| ----------- | ----------------- | ---------------------- | ------------------------------------------------------- |
| `children` | `React.ReactNode` | `` | Icon or content for the button. Defaults to close icon. |
| `className` | `string` | - | CSS classes for styling. |
| `slot` | `"clear"` | `"clear"` | Must be set to "clear" (automatically set). |
### SearchFieldRenderProps
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 (DEPRECATED - use `isFocusWithin`). |
| `isFocusWithin` | `boolean` | Whether any child element is focused. |
| `isFocusVisible` | `boolean` | Whether focus is visible (keyboard navigation). |
| `value` | `string` | Current value. |
| `isEmpty` | `boolean` | Whether the field is empty. |
# TextField
**Category**: react
**URL**: https://v3.heroui.com/docs/react/components/text-field
**Source**: https://raw.githubusercontent.com/heroui-inc/heroui/refs/heads/v3/apps/docs/content/docs/react/components/(forms)/text-field.mdx
> Composition-friendly text fields with labels, descriptions, and inline validation
## Import
```tsx
import { TextField } from '@heroui/react';
```
### Usage
```tsx
import {Input, Label, TextField} from "@heroui/react";
export function Basic() {
return (
Email
);
}
```
### Anatomy
```tsx
import {TextField, Label, Input, Description, FieldError} from '@heroui/react';
export default () => (
)
```
> **TextField** combines label, input, description, and error into a single accessible component.
> For standalone inputs, use **[Input](/docs/components/input)** or **[TextArea](/docs/components/textarea)**.
### With Description
```tsx
import {Description, Input, Label, TextField} from "@heroui/react";
export function WithDescription() {
return (
UsernameChoose a unique username for your account
);
}
```
### Required Field
```tsx
import {Description, Input, Label, TextField} from "@heroui/react";
export function Required() {
return (
Full NameThis field is required
);
}
```
### Validation
Use `isInvalid` together with `FieldError` to surface validation messages.
```tsx
"use client";
import {Description, FieldError, Input, Label, TextArea, TextField} from "@heroui/react";
import React from "react";
export function Validation() {
const [username, setUsername] = React.useState("");
const [bio, setBio] = React.useState("");
const isUsernameInvalid = username.length > 0 && username.length < 3;
const isBioInvalid = bio.length > 0 && bio.length < 20;
return (
Username
{isUsernameInvalid ? (
Username must be at least 3 characters.
) : (
Choose a unique username for your profile.
)}
Bio
{isBioInvalid ? (
Bio must contain at least 20 characters.
) : (
Minimum 20 characters ({bio.length}/20).
)}
);
}
```
### Controlled
Control the value to synchronize counters, previews, or formatting.
```tsx
"use client";
import {Description, Input, Label, TextArea, TextField} from "@heroui/react";
import React from "react";
export function Controlled() {
const [name, setName] = React.useState("");
const [bio, setBio] = React.useState("");
return (
);
}
```
### Error Message
```tsx
import {FieldError, Input, Label, TextField} from "@heroui/react";
export function WithError() {
return (
EmailPlease enter a valid email address
);
}
```
### Disabled State
```tsx
import {Description, Input, Label, TextField} from "@heroui/react";
export function Disabled() {
return (
Account IDThis field cannot be edited
);
}
```
### TextArea
Use [TextArea](/docs/components/textarea) instead of [Input](/docs/components/input) for multiline content.
```tsx
import {Description, Label, TextArea, TextField} from "@heroui/react";
export function TextAreaExample() {
return (
MessageMaximum 500 characters
);
}
```
### Input Types
```tsx
import {Input, Label, TextField} from "@heroui/react";
export function InputTypes() {
return (
PasswordAgeEmailWebsitePhone
);
}
```
### Full Width
```tsx
import {FieldError, Input, Label, TextField} from "@heroui/react";
export function FullWidth() {
return (
Your namePasswordPassword must be longer than 8 characters
);
}
```
### On Surface
When used inside a [Surface](/docs/components/surface) component, TextField and its child Input/TextArea components automatically apply on-surface styling.
```tsx
import {Description, Input, Label, Surface, TextArea, TextField} from "@heroui/react";
export function OnSurface() {
return (
Your nameWe'll never share this with anyone elseEmailBioMinimum 4 rows
);
}
```
## Related Components
* **Input**: Single-line text input built on React Aria
* **TextArea**: Multiline text input with focus management
* **Fieldset**: Group related form controls with legends
## Styling
### Passing Tailwind CSS classes
```tsx
import {TextField, Label, Input, Description} from '@heroui/react';
function CustomTextField() {
return (
Project name
Keep it short and memorable.
);
}
```
### Customizing the component classes
TextField has minimal default styling. Override the `.text-field` class to customize the container styling.
```css
@layer components {
.text-field {
@apply flex flex-col gap-1;
}
/* When invalid, the description is hidden automatically */
.text-field[data-invalid="true"] [data-slot="description"],
.text-field[aria-invalid="true"] [data-slot="description"] {
@apply hidden;
}
/* Description has default padding */
.text-field [data-slot="description"] {
@apply px-1;
}
}
```
### CSS Classes
* `.text-field` – Root container with minimal styling (`flex flex-col gap-1`)
> **Note:** Child components ([Label](/docs/components/label), [Input](/docs/components/input), [TextArea](/docs/components/textarea), [Description](/docs/components/description), [FieldError](/docs/components/field-error)) have their own CSS classes and styling. See their respective documentation for customization options.
### Interactive States
TextField automatically manages these data attributes based on its state:
* **Invalid**: `[data-invalid="true"]` or `[aria-invalid="true"]` - Automatically hides the description slot when invalid
* **Disabled**: `[data-disabled="true"]` - Applied when `isDisabled` is true
* **Focus Within**: `[data-focus-within="true"]` - Applied when any child input is focused
* **Focus Visible**: `[data-focus-visible="true"]` - Applied when focus is visible (keyboard navigation)
Additional attributes are available through render props (see TextFieldRenderProps below).
## API Reference
### TextField Props
TextField inherits all props from React Aria's [TextField](https://react-spectrum.adobe.com/react-aria/TextField.html) component.
#### Base Props
| Prop | Type | Default | Description |
| ----------- | ------------------------------------------------------------------------------ | ------- | -------------------------------------------------------------- |
| `children` | `React.ReactNode \| (values: TextFieldRenderProps) => React.ReactNode` | - | Child components (Label, Input, etc.) or render function. |
| `className` | `string \| (values: TextFieldRenderProps) => string` | - | CSS classes for styling, supports render props. |
| `style` | `React.CSSProperties \| (values: TextFieldRenderProps) => React.CSSProperties` | - | Inline styles, supports render props. |
| `fullWidth` | `boolean` | `false` | Whether the text field should take full width of its container |
| `id` | `string` | - | The element's unique identifier. |
#### 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: string) => ValidationError \| true \| null \| undefined` | - | Custom validation function. |
| `validationBehavior` | `'native' \| 'aria'` | `'native'` | Whether to use native HTML form validation or ARIA attributes. |
| `validationErrors` | `string[]` | - | Server-side validation errors. |
#### Value Props
| Prop | Type | Default | Description |
| -------------- | ------------------------- | ------- | -------------------------------------- |
| `value` | `string` | - | Current value (controlled). |
| `defaultValue` | `string` | - | Default value (uncontrolled). |
| `onChange` | `(value: string) => void` | - | Handler called when the value changes. |
#### State Props
| Prop | Type | Default | Description |
| ------------ | --------- | ------- | -------------------------------------------------- |
| `isDisabled` | `boolean` | - | Whether the input is disabled. |
| `isReadOnly` | `boolean` | - | Whether the input can be selected but not changed. |
#### 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
TextField works with these separate components that should be imported and used directly:
* **Label** - Field label component from `@heroui/react`
* **Input** - Single-line text input from `@heroui/react`
* **TextArea** - Multi-line text input 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 TextField for composition:
```tsx
Email Address
setEmail(e.target.value)} />
We'll never share your email.Please enter a valid email address.
```
### TextFieldRenderProps
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 (DEPRECATED - use `isFocusWithin`). |
| `isFocusWithin` | `boolean` | Whether any child element is focused. |
| `isFocusVisible` | `boolean` | Whether focus is visible (keyboard navigation). |
# TextArea
**Category**: react
**URL**: https://v3.heroui.com/docs/react/components/textarea
**Source**: https://raw.githubusercontent.com/heroui-inc/heroui/refs/heads/v3/apps/docs/content/docs/react/components/(forms)/textarea.mdx
> Primitive multiline text input component that accepts standard HTML attributes
## Import
```tsx
import { TextArea } from '@heroui/react';
```
For validation, labels, and error messages, see **[TextField](/docs/components/text-field)**.
### Usage
```tsx
import {TextArea} from "@heroui/react";
export function Basic() {
return (
);
}
```
### Controlled
```tsx
"use client";
import {Description, TextArea} from "@heroui/react";
import React from "react";
export function Controlled() {
const [value, setValue] = React.useState("");
return (
);
}
```
### Rows and Resizing
```tsx
import {Label, TextArea} from "@heroui/react";
export function Rows() {
return (
Short feedback
Detailed notes
);
}
```
### Full Width
```tsx
import {TextArea} from "@heroui/react";
export function FullWidth() {
return (
);
}
```
### On Surface
When used inside a [Surface](/docs/components/surface) component, TextArea automatically applies on-surface styling.
```tsx
import {Surface, TextArea} from "@heroui/react";
export function OnSurface() {
return (
);
}
```
## Related Components
* **TextField**: Composition-friendly fields with labels and validation
* **Input**: Single-line text input built on React Aria
* **Label**: Accessible label for form controls
## Styling
### Passing Tailwind CSS classes
```tsx
import {Label, TextArea} from '@heroui/react';
function CustomTextArea() {
return (
Message
);
}
```
### Customizing the component classes
Override the shared `.textarea` class once with Tailwind's `@layer components`.
```css
@layer components {
.textarea {
@apply rounded-xl border border-border bgsurface px-4 py-3 text-sm leading-6 shadow-sm;
&:hover,
&[data-hovered="true"] {
@apply bg-surface-secondary border-border/80;
}
&:focus-visible,
&[data-focus-visible="true"] {
@apply border-primary ring-2 ring-primary/20;
}
&[data-invalid="true"] {
@apply border-danger bg-danger-50/10 text-danger;
}
}
}
```
### CSS Classes
* `.textarea` – Underlying `
# TimeField
**Category**: react
**URL**: https://v3.heroui.com/docs/react/components/time-field
**Source**: https://raw.githubusercontent.com/heroui-inc/heroui/refs/heads/v3/apps/docs/content/docs/react/components/(forms)/time-field.mdx
> Time input field with labels, descriptions, and validation built on React Aria TimeField
## Import
```tsx
import { TimeField } from '@heroui/react';
```
### Usage
```tsx
"use client";
import {DateInputGroup, Label, TimeField} from "@heroui/react";
export function Basic() {
return (
Time
{(segment) => }
);
}
```
### Anatomy
```tsx
import {TimeField, Label, DateInputGroup, Description, FieldError} from '@heroui/react';
export default () => (
{(segment) => }
)
```
> **TimeField** combines label, time input, description, and error into a single accessible component.
### With Description
```tsx
"use client";
import {DateInputGroup, Description, Label, TimeField} from "@heroui/react";
export function WithDescription() {
return (
Start time
{(segment) => }
Enter the start timeEnd time
{(segment) => }
Enter the end time
);
}
```
### Required Field
```tsx
"use client";
import {DateInputGroup, Description, Label, TimeField} from "@heroui/react";
export function Required() {
return (
Time
{(segment) => }
Appointment time
{(segment) => }
Required field
);
}
```
### Validation
Use `isInvalid` together with `FieldError` to surface validation messages.
```tsx
"use client";
import {DateInputGroup, FieldError, Label, TimeField} from "@heroui/react";
export function Invalid() {
return (
Time
{(segment) => }
Please enter a valid timeTime
{(segment) => }
Time must be within business hours
);
}
```
### With Validation
TimeField supports validation with `minValue`, `maxValue`, and custom validation logic.
```tsx
"use client";
import type {Time} from "@internationalized/date";
import {DateInputGroup, Description, FieldError, Label, TimeField} from "@heroui/react";
import {parseTime} from "@internationalized/date";
import {useState} from "react";
export function WithValidation() {
const [value, setValue] = useState
# Card
**Category**: react
**URL**: https://v3.heroui.com/docs/react/components/card
**Source**: https://raw.githubusercontent.com/heroui-inc/heroui/refs/heads/v3/apps/docs/content/docs/react/components/(layout)/card.mdx
> Flexible container component for grouping related content and actions
## Import
```tsx
import { Card } from "@heroui/react";
```
### Usage
```tsx
import {CircleDollar} from "@gravity-ui/icons";
import {Card, Link} from "@heroui/react";
export function Default() {
return (
Become an Acme Creator!
Visit the Acme Creator Hub to sign up today and start earning credits from your fans and
followers.
Creator Hub
);
}
```
### Anatomy
Import the Card component and access all parts using dot notation.
```tsx
import { Card } from "@heroui/react";
export default () => (
);
```
### Variants
Cards come in semantic variants that describe their prominence level rather than specific visual styles. This allows themes to interpret them differently:
```tsx
import {Card} from "@heroui/react";
export function Variants() {
return (
TransparentMinimal prominence with transparent background
);
}
```
### Vertical
```tsx
import {Separator} from "@heroui/react";
export function Vertical() {
return (
Blog
Docs
Source
);
}
```
### With Content
```tsx
import {Separator} from "@heroui/react";
const items = [
{
iconUrl: "https://heroui-assets.nyc3.cdn.digitaloceanspaces.com/docs/3dicons/bell-small.png",
subtitle: "Receive account activity updates",
title: "Set Up Notifications",
},
{
iconUrl: "https://heroui-assets.nyc3.cdn.digitaloceanspaces.com/docs/3dicons/compass-small.png",
subtitle: "Connect your browser to your account",
title: "Set up Browser Extension",
},
{
iconUrl:
"https://heroui-assets.nyc3.cdn.digitaloceanspaces.com/docs/3dicons/mint-collective-small.png",
subtitle: "Create your first collectible",
title: "Mint Collectible",
},
];
export function WithContent() {
return (
{items.map((item, index) => (
{item.title}
{item.subtitle}
{index < items.length - 1 && }
))}
);
}
```
## Related Components
* **Card**: Content container with header, body, and footer
* **Chip**: Compact elements for tags and filters
* **Avatar**: Display user profile images
## Styling
### Passing Tailwind CSS classes
```tsx
import {Separator} from '@heroui/react';
function CustomSeparator() {
return (
);
}
```
### Customizing the component classes
To customize the Separator component classes, you can use the `@layer components` directive.
[Learn more](https://tailwindcss.com/docs/adding-custom-styles#adding-component-classes).
```css
@layer components {
.separator {
@apply bg-accent h-[2px];
}
.separator--vertical {
@apply bg-accent w-[2px];
}
}
```
HeroUI follows the [BEM](https://getbem.com/) methodology to ensure component variants and states are reusable and easy to customize.
### CSS Classes
The Separator component uses these CSS classes ([View source styles](https://github.com/heroui-inc/heroui/blob/v3/packages/styles/components/separator.css)):
#### Base & Orientation Classes
* `.separator` - Base separator styles with default horizontal orientation
* `.separator--horizontal` - Horizontal orientation (full width, 1px height)
* `.separator--vertical` - Vertical orientation (full height, 1px width)
* `.separator--on-surface` - Applied when `isOnSurface` is true, uses `bg-separator-on-surface` for better visibility on surface backgrounds
## API Reference
### Separator Props
| Prop | Type | Default | Description |
| ------------- | ---------------------------- | -------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `orientation` | `'horizontal' \| 'vertical'` | `'horizontal'` | The orientation of the separator |
| `isOnSurface` | `boolean \| undefined` | `undefined` | Whether the separator is on a surface background. When `undefined`, automatically detects if it's inside a component with `SurfaceContext` (e.g., Card, Alert, Popover, Modal). When `true`, applies `bg-separator-on-surface` for better visibility. |
| `className` | `string` | - | Additional CSS classes |
### Automatic Surface Detection
The Separator component automatically detects when it's placed inside a surface component (one that uses `bg-surface`) and applies the appropriate divider color. This works with components that provide `SurfaceContext`, such as:
* Card
* Alert
* Popover
* Modal
* Combobox
* Select
* Dropdown
**Example:**
```tsx
```
When `isOnSurface` is not explicitly set, the Separator will automatically detect the `SurfaceContext` and apply the correct styling.
# Surface
**Category**: react
**URL**: https://v3.heroui.com/docs/react/components/surface
**Source**: https://raw.githubusercontent.com/heroui-inc/heroui/refs/heads/v3/apps/docs/content/docs/react/components/(layout)/surface.mdx
> Container component that provides surface-level styling and context for child components
## Import
```tsx
import { Surface } from '@heroui/react';
```
### Usage
```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.
Quaternary
Surface Content
This is a quaternary surface variant. It uses bg-surface-quaternary styling.
);
}
```
## Overview
The Surface component is a semantic container that provides different levels of visual prominence through variants. It also exposes a context that child components (like Input, TextArea, RadioGroup, and InputOTP) can use to automatically apply on-surface styling.
### Variants
Surface comes in semantic variants that describe their prominence level:
* **`default`** - Standard surface appearance (bg-surface)
* **`secondary`** - Medium prominence (bg-surface-secondary)
* **`tertiary`** - Higher prominence (bg-surface-tertiary)
* **`quaternary`** - Highest prominence (bg-surface-quaternary)
## Context
The Surface component provides a `SurfaceContext` that child components can access via `useContext(SurfaceContext)`. Form components like Input, TextArea, RadioGroup, and InputOTP automatically detect when they're inside a Surface and apply the appropriate on-surface styling.
```tsx
import { Surface, Input, TextArea } from '@heroui/react';
import { useContext } from 'react';
import { SurfaceContext } from '@heroui/react';
function MyComponent() {
const surfaceContext = useContext(SurfaceContext);
// Access the variant if needed
const variant = surfaceContext.variant;
return (
<>
>
);
}
function App() {
return (
);
}
```
## Related Components
* **CheckboxGroup**: Group of checkboxes with shared state
* **Fieldset**: Group related form controls with legends
* **InputOTP**: One-time password input
## Styling
### Passing Tailwind CSS classes
```tsx
import { Surface } from '@heroui/react';
function CustomSurface() {
return (
Custom Styled Surface
Content goes here
);
}
```
### Customizing the component classes
To customize the Surface component classes, you can use the `@layer components` directive.
[Learn more](https://tailwindcss.com/docs/adding-custom-styles#adding-component-classes).
```css
@layer components {
.surface {
@apply rounded-2xl border border-border;
}
.surface--secondary {
@apply bg-gradient-to-br from-blue-50 to-purple-50;
}
}
```
HeroUI follows the [BEM](https://getbem.com/) methodology to ensure component variants and states are reusable and easy to customize.
### CSS Classes
The Surface component uses these CSS classes ([View source styles](https://github.com/heroui-inc/heroui/blob/v3/packages/styles/components/surface.css)):
#### Base Classes
* `.surface` - Base surface container
#### Variant Classes
* `.surface--default` - Default surface variant (bg-surface)
* `.surface--secondary` - Secondary surface variant (bg-surface-secondary)
* `.surface--tertiary` - Tertiary surface variant (bg-surface-tertiary)
* `.surface--quaternary` - Quaternary surface variant (bg-surface-quaternary)
## API Reference
### Surface Props
| Prop | Type | Default | Description |
| ----------- | -------------------------------------------------------- | ----------- | --------------------------------- |
| `variant` | `"default" \| "secondary" \| "tertiary" \| "quaternary"` | `"default"` | The visual variant of the surface |
| `className` | `string` | - | Additional CSS classes |
| `children` | `ReactNode` | - | The surface content |
## Context API
### SurfaceContext
Child components can access the Surface context to get the current variant:
```tsx
import { useContext } from 'react';
import { SurfaceContext } from '@heroui/react';
function MyComponent() {
const { variant } = useContext(SurfaceContext);
// variant will be "default" | "secondary" | "tertiary" | "quaternary" | undefined
}
```
# Avatar
**Category**: react
**URL**: https://v3.heroui.com/docs/react/components/avatar
**Source**: https://raw.githubusercontent.com/heroui-inc/heroui/refs/heads/v3/apps/docs/content/docs/react/components/(media)/avatar.mdx
> Display user profile images with customizable fallback content
## Import
```tsx
import { Avatar } from '@heroui/react';
```
### Usage
```tsx
import {Avatar} from "@heroui/react";
export function Basic() {
return (
JDBJR
);
}
```
### Anatomy
Import the Avatar component and access all parts using dot notation.
```tsx
import { Avatar } from '@heroui/react';
export default () => (
)
```
### Sizes
```tsx
import {Avatar} from "@heroui/react";
export function Sizes() {
return (
SMMDLG
);
}
```
### Colors
```tsx
import {Avatar} from "@heroui/react";
export function Colors() {
return (
);
}
```
## Related Components
* **Separator**: Visual divider between content
## Styling
### Passing Tailwind CSS classes
```tsx
import { Avatar } from '@heroui/react';
function CustomAvatar() {
return (
XL
);
}
```
### Customizing the component classes
To customize the Avatar component classes, you can use the `@layer components` directive.
[Learn more](https://tailwindcss.com/docs/adding-custom-styles#adding-component-classes).
```css
@layer components {
.avatar {
@apply size-16 border-2 border-primary;
}
.avatar__fallback {
@apply bg-gradient-to-br from-purple-500 to-pink-500;
}
}
```
HeroUI follows the [BEM](https://getbem.com/) methodology to ensure component variants and states are reusable and easy to customize.
### CSS Classes
The Avatar component uses these CSS classes ([View source styles](https://github.com/heroui-inc/heroui/blob/v3/packages/styles/components/avatar.css)):
#### Base Classes
* `.avatar` - Base container with default size (size-10)
* `.avatar__image` - Image element with aspect-square sizing
* `.avatar__fallback` - Fallback container with centered content
#### Size Modifiers
* `.avatar--sm` - Small avatar (size-8)
* `.avatar--md` - Medium avatar (default, no additional styles)
* `.avatar--lg` - Large avatar (size-12)
#### Variant Modifiers
* `.avatar--soft` - Soft variant with lighter background
#### Color Modifiers
* `.avatar__fallback--default` - Default text color
* `.avatar__fallback--accent` - Accent text color
* `.avatar__fallback--success` - Success text color
* `.avatar__fallback--warning` - Warning text color
* `.avatar__fallback--danger` - Danger text color
## API Reference
### Avatar Props
| Prop | Type | Default | Description |
| ----------- | ------------------------------------------------------------- | ----------- | ---------------------- |
| `size` | `'sm' \| 'md' \| 'lg'` | `'md'` | Avatar size |
| `color` | `'default' \| 'accent' \| 'success' \| 'warning' \| 'danger'` | `'default'` | Fallback color theme |
| `variant` | `'default' \| 'soft'` | `'default'` | Visual style variant |
| `className` | `string` | - | Additional CSS classes |
### Avatar.Image Props
| Prop | Type | Default | Description |
| ------------- | --------------------------------------------------- | ------- | -------------------------------------------------- |
| `src` | `string` | - | Image source URL |
| `srcSet` | `string` | - | The image `srcset` attribute for responsive images |
| `sizes` | `string` | - | The image `sizes` attribute for responsive images |
| `alt` | `string` | - | Alternative text for the image |
| `onLoad` | `(event: SyntheticEvent) => void` | - | Callback when the image loads successfully |
| `onError` | `(event: SyntheticEvent) => void` | - | Callback when there's an error loading the image |
| `crossOrigin` | `'anonymous' \| 'use-credentials'` | - | CORS setting for the image request |
| `loading` | `'eager' \| 'lazy'` | - | Native lazy loading attribute |
| `className` | `string` | - | Additional CSS classes |
### Avatar.Fallback Props
| Prop | Type | Default | Description |
| ----------- | ------------------------------------------------------------- | ------- | ---------------------------------------------- |
| `delayMs` | `number` | - | Delay before showing fallback (prevents flash) |
| `color` | `'default' \| 'accent' \| 'success' \| 'warning' \| 'danger'` | - | Override color from parent |
| `className` | `string` | - | Additional CSS classes |
# Accordion
**Category**: react
**URL**: https://v3.heroui.com/docs/react/components/accordion
**Source**: https://raw.githubusercontent.com/heroui-inc/heroui/refs/heads/v3/apps/docs/content/docs/react/components/(navigation)/accordion.mdx
> A collapsible content panel for organizing information in a compact space
## Import
```tsx
import { Accordion } from '@heroui/react';
```
### Usage
```tsx
import {
ArrowsRotateLeft,
Box,
ChevronDown,
CreditCard,
PlanetEarth,
Receipt,
ShoppingBag,
} from "@gravity-ui/icons";
import {Accordion} from "@heroui/react";
const items = [
{
content:
"Browse our products, add items to your cart, and proceed to checkout. You'll need to provide shipping and payment information to complete your purchase.",
icon: ,
title: "How do I place an order?",
},
{
content:
"Yes, you can modify or cancel your order before it's shipped. Once your order is processed, you can't make changes.",
icon: ,
title: "Can I modify or cancel my order?",
},
{
content: "We accept all major credit cards, including Visa, Mastercard, and American Express.",
icon: ,
title: "What payment methods do you accept?",
},
{
content:
"Shipping costs vary based on your location and the size of your order. We offer free shipping for orders over $50.",
icon: ,
title: "How much does shipping cost?",
},
{
content:
"Yes, we ship to most countries. Please check our shipping rates and policies for more information.",
icon: ,
title: "Do you ship internationally?",
},
{
content:
"If you're not satisfied with your purchase, you can request a refund within 30 days of purchase. Please contact our customer support team for assistance.",
icon: ,
title: "How do I request a refund?",
},
];
export function Basic() {
return (
{items.map((item, index) => (
{item.icon ? (
{item.icon}
) : null}
{item.title}
{item.content}
))}
);
}
```
### Anatomy
Import the Accordion component and access all parts using dot notation.
```tsx
import { Accordion } from '@heroui/react';
export default () => (
)
```
### Surface
```tsx
import {
ArrowsRotateLeft,
Box,
ChevronDown,
CreditCard,
PlanetEarth,
Receipt,
ShoppingBag,
} from "@gravity-ui/icons";
import {Accordion} from "@heroui/react";
const items = [
{
content:
"Browse our products, add items to your cart, and proceed to checkout. You'll need to provide shipping and payment information to complete your purchase.",
icon: ,
title: "How do I place an order?",
},
{
content:
"Yes, you can modify or cancel your order before it's shipped. Once your order is processed, you can't make changes.",
icon: ,
title: "Can I modify or cancel my order?",
},
{
content: "We accept all major credit cards, including Visa, Mastercard, and American Express.",
icon: ,
title: "What payment methods do you accept?",
},
{
content:
"Shipping costs vary based on your location and the size of your order. We offer free shipping for orders over $50.",
icon: ,
title: "How much does shipping cost?",
},
{
content:
"Yes, we ship to most countries. Please check our shipping rates and policies for more information.",
icon: ,
title: "Do you ship internationally?",
},
{
content:
"If you're not satisfied with your purchase, you can request a refund within 30 days of purchase. Please contact our customer support team for assistance.",
icon: ,
title: "How do I request a refund?",
},
];
export function Surface() {
return (
{items.map((item, index) => (
{item.icon ? (
{item.icon}
) : null}
{item.title}
{item.content}
))}
);
}
```
### Multiple Expanded
```tsx
import {Accordion} from "@heroui/react";
export function Multiple() {
return (
Getting Started
Learn the basics of HeroUI and how to integrate it into your React project. This section
covers installation, setup, and your first component.
Core Concepts
Understand the fundamental concepts behind HeroUI, including the compound component
pattern, styling with Tailwind CSS, and accessibility features.
Advanced Usage
Explore advanced features like custom variants, theme customization, and integration
with other libraries in your React ecosystem.
Best Practices
Follow our recommended best practices for building performant, accessible, and
maintainable applications with HeroUI components.
);
}
```
### Custom Indicator
```tsx
"use client";
import type {Key} from "@heroui/react";
import {ChevronsDown, CircleChevronDown, Minus, Plus} from "@gravity-ui/icons";
import {Accordion} from "@heroui/react";
import React from "react";
export function CustomIndicator() {
const [expandedKeys, setExpandedKeys] = React.useState>(new Set([""]));
return (
Using Plus/Minus Icon
{expandedKeys.has("1") ? : }
This accordion uses a plus icon that transforms when expanded. The icon automatically
rotates 45 degrees to form an X.
Using Caret Icon
This item uses a caret icon for the indicator. The rotation animation is applied
automatically.
Using Arrow Icon
This item uses an arrow icon. Any icon you pass will receive the rotation animation when
the item expands.
);
}
```
### Disabled State
```tsx
import {Accordion} from "@heroui/react";
export function Disabled() {
return (
Entire accordion disabled
Disabled Item 1
This content cannot be accessed when the accordion is disabled.
Disabled Item 2
This content cannot be accessed when the accordion is disabled.
Individual items disabled
Active Item
This item is active and can be toggled normally.
Disabled Item
This content cannot be accessed when the item is disabled.
Another Active Item
This item is also active and can be toggled.
);
}
```
### FAQ Layout
```tsx
import {ChevronDown} from "@gravity-ui/icons";
import {Accordion} from "@heroui/react";
export function FAQ() {
const categories = [
{
items: [
{
content:
"Browse our products, add items to your cart, and proceed to checkout. You'll need to provide shipping and payment information to complete your purchase.",
title: "How do I place an order?",
},
{
content:
"Yes, you can modify or cancel your order before it's shipped. Once your order is processed, you can't make changes.",
title: "Can I modify or cancel my order?",
},
],
title: "General",
},
{
items: [
{
content:
"You can purchase a license directly from our website. Select the license type that fits your needs and proceed to checkout.",
title: "How do I purchase a license?",
},
{
content:
"A standard license is for personal use or small projects, while a pro license includes commercial use rights and priority support.",
title: "What is the difference between a standard and a pro license?",
},
],
title: "Licensing",
},
{
items: [
{
content:
"You can reach our support team through the contact form on our website, or email us directly at support@example.com.",
title: "How do I get support?",
},
],
title: "Support",
},
];
return (
Frequently Asked Questions
Everything you need to know about licensing and usage.
);
}
```
### Custom Styles
```tsx
import {ChevronDown} from "@gravity-ui/icons";
import {Accordion, cn} from "@heroui/react";
const items = [
{
content: "Stay informed about your account activity with real-time notifications. ",
iconUrl: "https://heroui-assets.nyc3.cdn.digitaloceanspaces.com/docs/3dicons/bell-small.png",
subtitle: "Receive account activity updates",
title: "Set Up Notifications",
},
{
content: "Enhance your browsing experience by installing our official browser extension",
iconUrl: "https://heroui-assets.nyc3.cdn.digitaloceanspaces.com/docs/3dicons/compass-small.png",
subtitle: "Connect you browser to your account",
title: "Set up Browser Extension",
},
{
content:
"Begin your journey into the world of digital collectibles by creating your first NFT. ",
iconUrl:
"https://heroui-assets.nyc3.cdn.digitaloceanspaces.com/docs/3dicons/mint-collective-small.png",
subtitle: "Create your first collectible",
title: "Mint Collectible",
},
];
export function CustomStyles() {
return (
{items.map((item, index) => (
{item.iconUrl ? (
) : null}
{item.title}{item.subtitle}
{item.content}
))}
);
}
```
### Without Separator
```tsx
import {ChevronDown, CreditCard, Receipt, ShoppingBag} from "@gravity-ui/icons";
import {Accordion} from "@heroui/react";
const items = [
{
content:
"Browse our products, add items to your cart, and proceed to checkout. You'll need to provide shipping and payment information to complete your purchase.",
icon: ,
title: "How do I place an order?",
},
{
content:
"Yes, you can modify or cancel your order before it's shipped. Once your order is processed, you can't make changes.",
icon: ,
title: "Can I modify or cancel my order?",
},
{
content: "We accept all major credit cards, including Visa, Mastercard, and American Express.",
icon: ,
title: "What payment methods do you accept?",
},
];
export function WithoutSeparator() {
return (
{items.map((item, index) => (
{item.icon ? (
{item.icon}
) : null}
{item.title}
{item.content}
))}
);
}
```
## Related Components
* **DisclosureGroup**: Group of collapsible panels
* **Disclosure**: Single collapsible content section
## Styling
### Passing Tailwind CSS classes
```tsx
"use client";
import { Accordion, cn } from "@heroui/react";
import {Icon} from "@iconify/react";
const items = [
{
content:
"Stay informed about your account activity with real-time notifications. You'll receive instant alerts for important events like transactions, new messages, security updates, and system announcements. ",
iconUrl: "https://heroui-assets.nyc3.cdn.digitaloceanspaces.com/docs/3dicons/bell-small.png",
title: "Set Up Notifications",
subtitle: "Receive account activity updates",
},
{
content:
"Enhance your browsing experience by installing our official browser extension. The extension provides seamless integration with your account, allowing you to receive notifications directly in your browser, quickly access your dashboard, and interact with web3 applications securely. Compatible with Chrome, Firefox, Edge, and Brave browsers.",
iconUrl: "https://heroui-assets.nyc3.cdn.digitaloceanspaces.com/docs/3dicons/compass-small.png",
title: "Set up Browser Extension",
subtitle: "Connect you browser to your account",
},
{
content:
"Begin your journey into the world of digital collectibles by creating your first NFT. Our intuitive minting process guides you through uploading your artwork, setting metadata, choosing royalty percentages, and deploying to the blockchain. Whether you're an artist, creator, or collector, you'll find all the tools you need to bring your digital assets to life. Your collectibles are stored on IPFS for permanent decentralized storage.",
iconUrl:
"https://heroui-assets.nyc3.cdn.digitaloceanspaces.com/docs/3dicons/mint-collective-small.png",
title: "Mint Collectible",
subtitle: "Create your first collectible",
},
];
export function CustomStyles() {
return (
{items.map((item, index) => (
{item.iconUrl ? (
) : null}
{item.title}{item.subtitle}
{item.content}
))}
);
}
```
### Customizing the component classes
To customize the Accordion component classes, you can use the `@layer components` directive.
[Learn more](https://tailwindcss.com/docs/adding-custom-styles#adding-component-classes).
```css
@layer components {
.accordion {
@apply rounded-xl bg-gray-50;
}
.accordion__trigger {
@apply font-semibold text-lg;
}
.accordion--outline {
@apply shadow-lg border-2;
}
}
```
HeroUI follows the [BEM](https://getbem.com/) methodology to ensure component variants and states are reusable and easy to customize.
### CSS Classes
The Accordion component uses these CSS classes ([View source styles](https://github.com/heroui-inc/heroui/blob/v3/packages/styles/components/accordion.css)):
#### Base Classes
* `.accordion` - Base accordion container
* `.accordion__body` - Content body container
* `.accordion__heading` - Heading wrapper
* `.accordion__indicator` - Expand/collapse indicator icon
* `.accordion__item` - Individual accordion item
* `.accordion__panel` - Collapsible panel container
* `.accordion__trigger` - Clickable trigger button
#### Variant Classes
* `.accordion--outline` - Outline variant with border and background
#### State Classes
* `.accordion__trigger[aria-expanded="true"]` - Expanded state
* `.accordion__panel[aria-hidden="false"]` - Panel visible state
### Interactive States
The component supports both CSS pseudo-classes and data attributes for flexibility:
* **Hover**: `:hover` or `[data-hovered="true"]` on trigger
* **Focus**: `:focus-visible` or `[data-focus-visible="true"]` on trigger
* **Disabled**: `:disabled` or `[aria-disabled="true"]` on trigger
* **Expanded**: `[aria-expanded="true"]` on trigger
## API Reference
### Accordion Props
| Prop | Type | Default | Description |
| ------------------------ | -------------------------- | ----------- | ---------------------------------------------- |
| `allowsMultipleExpanded` | `boolean` | `false` | Whether multiple items can be expanded at once |
| `defaultExpandedKeys` | `Iterable` | - | The initial expanded keys |
| `expandedKeys` | `Iterable` | - | The controlled expanded keys |
| `onExpandedChange` | `(keys: Set) => void` | - | Handler called when expanded keys change |
| `isDisabled` | `boolean` | `false` | Whether the entire accordion is disabled |
| `variant` | `"default" \| "surface"` | `"default"` | The visual variant of the accordion |
| `hideSeparator` | `boolean` | `false` | Hide separator lines between accordion items |
| `className` | `string` | - | Additional CSS classes |
| `children` | `ReactNode` | - | The accordion items |
### Accordion.Item Props
| Prop | Type | Default | Description |
| ------------------ | ------------------------------- | ------- | ---------------------------------- |
| `id` | `Key` | - | Unique identifier for the item |
| `isDisabled` | `boolean` | `false` | Whether this item is disabled |
| `defaultExpanded` | `boolean` | `false` | Whether item is initially expanded |
| `isExpanded` | `boolean` | - | Controlled expanded state |
| `onExpandedChange` | `(isExpanded: boolean) => void` | - | Handler for expanded state changes |
| `className` | `string` | - | Additional CSS classes |
| `children` | `ReactNode` | - | The item content |
### Accordion.Trigger Props
| Prop | Type | Default | Description |
| ------------ | ----------------------------- | ------- | ---------------------------------- |
| `className` | `string` | - | Additional CSS classes |
| `children` | `ReactNode \| RenderFunction` | - | Trigger content or render function |
| `onPress` | `() => void` | - | Additional press handler |
| `isDisabled` | `boolean` | - | Whether trigger is disabled |
### Accordion.Panel Props
| Prop | Type | Default | Description |
| ----------- | ----------- | ------- | ---------------------- |
| `className` | `string` | - | Additional CSS classes |
| `children` | `ReactNode` | - | Panel content |
### Accordion.Indicator Props
| Prop | Type | Default | Description |
| ----------- | ----------- | ------- | ---------------------- |
| `className` | `string` | - | Additional CSS classes |
| `children` | `ReactNode` | - | Custom indicator icon |
### Accordion.Body Props
| Prop | Type | Default | Description |
| ----------- | ----------- | ------- | ---------------------- |
| `className` | `string` | - | Additional CSS classes |
| `children` | `ReactNode` | - | Body content |
# DisclosureGroup
**Category**: react
**URL**: https://v3.heroui.com/docs/react/components/disclosure-group
**Source**: https://raw.githubusercontent.com/heroui-inc/heroui/refs/heads/v3/apps/docs/content/docs/react/components/(navigation)/disclosure-group.mdx
> Container that manages multiple Disclosure items with coordinated expanded states
## Import
```tsx
import {DisclosureGroup} from '@heroui/react';
```
### Usage
```tsx
"use client";
import {QrCode} from "@gravity-ui/icons";
import {Button, Disclosure, DisclosureGroup, Separator} from "@heroui/react";
import {Icon} from "@iconify/react";
import React from "react";
import {cn} from "tailwind-variants";
export function Basic() {
const [expandedKeys, setExpandedKeys] = React.useState(new Set(["preview"]));
return (
Scan this QR code with your camera app to preview the HeroUI native components.
Expo must be installed on your device.
Download the HeroUI native app to explore our mobile components directly on your
device.
Available on iOS and Android devices.
);
}
```
### Anatomy
Import all parts and piece them together.
```tsx
import {DisclosureGroup, Disclosure} from '@heroui/react';
export default () => (
)
```
### Controlled
You can control which disclosures are expanded with external navigation controls using the `expandedKeys` and `onExpandedChange` props.
```tsx
"use client";
import {ChevronDown, ChevronUp, QrCode} from "@gravity-ui/icons";
import {
Button,
Disclosure,
DisclosureGroup,
Separator,
useDisclosureGroupNavigation,
} from "@heroui/react";
import {Icon} from "@iconify/react";
import React from "react";
import {cn} from "tailwind-variants";
export function Controlled() {
const [expandedKeys, setExpandedKeys] = React.useState(new Set(["preview"]));
const itemIds = ["preview", "download"]; // Track our disclosure items
const {isNextDisabled, isPrevDisabled, onNext, onPrevious} = useDisclosureGroupNavigation({
expandedKeys,
itemIds,
onExpandedChange: setExpandedKeys,
});
return (
HeroUI Native
Scan this QR code with your camera app to preview the HeroUI native components.
Expo must be installed on your device.
Scan this QR code with your camera app to preview the HeroUI native components.
Expo must be installed on your device.
);
}
```
## Related Components
* **Accordion**: Collapsible content sections
* **Disclosure**: Single collapsible content section
* **Button**: Allows a user to perform an action
## Styling
### Passing Tailwind CSS classes
```tsx
import {
DisclosureGroup,
Disclosure,
DisclosureTrigger,
DisclosurePanel
} from '@heroui/react';
function CustomDisclosureGroup() {
return (
Item 1Content 1Item 2Content 2
);
}
```
### Customizing the component classes
To customize the DisclosureGroup component classes, you can use the `@layer components` directive.
[Learn more](https://tailwindcss.com/docs/adding-custom-styles#adding-component-classes).
```css
@layer components {
.disclosure-group {
@apply w-full;
/* Performance optimization */
contain: layout style;
}
}
```
HeroUI follows the [BEM](https://getbem.com/) methodology to ensure component variants and states are reusable and easy to customize.
### CSS Classes
The DisclosureGroup component uses these CSS classes ([View source styles](https://github.com/heroui-inc/heroui/blob/v3/packages/styles/components/disclosure-group.css)):
#### Base Classes
* `.disclosure-group` - Base container styles with layout containment
### Interactive States
The component supports both CSS pseudo-classes and data attributes for flexibility:
* **Disabled**: `:disabled` or `[aria-disabled="true"]` on entire group
* **Expanded Management**: Automatically manages `[data-expanded]` states on child Disclosure items
## API Reference
### DisclosureGroup Props
| Prop | Type | Default | Description |
| ------------------------ | ----------------------------- | ------- | ----------------------------------------------------- |
| `expandedKeys` | `Set` | - | The currently expanded items (controlled) |
| `defaultExpandedKeys` | `Iterable` | - | The initially expanded items (uncontrolled) |
| `onExpandedChange` | `(keys: Set) => void` | - | Handler called when expanded items change |
| `allowsMultipleExpanded` | `boolean` | `false` | Whether multiple items can be expanded simultaneously |
| `isDisabled` | `boolean` | `false` | Whether all disclosures in the group are disabled |
| `children` | `ReactNode \| RenderFunction` | - | Disclosure items to render |
| `className` | `string` | - | Additional CSS classes |
### RenderProps
When using the render prop pattern, these values are provided:
| Prop | Type | Description |
| -------------- | ---------- | ----------------------------- |
| `expandedKeys` | `Set` | Currently expanded item keys |
| `isDisabled` | `boolean` | Whether the group is disabled |
# Disclosure
**Category**: react
**URL**: https://v3.heroui.com/docs/react/components/disclosure
**Source**: https://raw.githubusercontent.com/heroui-inc/heroui/refs/heads/v3/apps/docs/content/docs/react/components/(navigation)/disclosure.mdx
> A disclosure is a collapsible section with a header containing a heading and a trigger button, and a panel that wraps the content.
## Import
```tsx
import { Disclosure } from '@heroui/react';
```
### Usage
```tsx
"use client";
import {QrCode} from "@gravity-ui/icons";
import {Button, Disclosure} from "@heroui/react";
import {Icon} from "@iconify/react";
import React from "react";
export function Basic() {
const [isExpanded, setIsExpanded] = React.useState(true);
return (
Scan this QR code with your camera app to preview the HeroUI native components.
Expo must be installed on your device.
);
}
```
### Anatomy
Import the Disclosure component and access all parts using dot notation.
```tsx
import { Disclosure } from '@heroui/react';
export default () => (
)
```
## Related Components
* **Accordion**: Collapsible content sections
* **DisclosureGroup**: Group of collapsible panels
* **Button**: Allows a user to perform an action
## Styling
### Passing Tailwind CSS classes
```tsx
import { Disclosure } from '@heroui/react';
function CustomDisclosure() {
return (
Click to expand
Hidden content
);
}
```
### Customizing the component classes
To customize the Disclosure component classes, you can use the `@layer components` directive.
[Learn more](https://tailwindcss.com/docs/adding-custom-styles#adding-component-classes).
```css
@layer components {
.disclosure {
@apply relative;
}
.disclosure__trigger {
@apply cursor-pointer;
}
.disclosure__indicator {
@apply transition-transform duration-300;
}
.disclosure__content {
@apply overflow-hidden transition-all;
}
}
```
HeroUI follows the [BEM](https://getbem.com/) methodology to ensure component variants and states are reusable and easy to customize.
### CSS Classes
The Disclosure component uses these CSS classes ([View source styles](https://github.com/heroui-inc/heroui/blob/v3/packages/styles/components/disclosure.css)):
#### Base Classes
* `.disclosure` - Base container styles
* `.disclosure__heading` - Heading wrapper
* `.disclosure__trigger` - Trigger button styles
* `.disclosure__indicator` - Chevron indicator styles
* `.disclosure__content` - Content container with animations
### Interactive States
The component supports both CSS pseudo-classes and data attributes for flexibility:
* **Expanded**: `[data-expanded="true"]` on indicator for rotation
* **Focus**: `:focus-visible` or `[data-focus-visible="true"]` on trigger
* **Disabled**: `:disabled` or `[aria-disabled="true"]` on trigger
* **Hidden**: `[aria-hidden="false"]` on content for visibility
## API Reference
### Disclosure Props
| Prop | Type | Default | Description |
| ------------------ | ------------------------------- | ------- | ------------------------------------ |
| `isExpanded` | `boolean` | `false` | Controls the expanded state |
| `onExpandedChange` | `(isExpanded: boolean) => void` | - | Callback when expanded state changes |
| `isDisabled` | `boolean` | `false` | Whether the disclosure is disabled |
| `children` | `ReactNode \| RenderFunction` | - | Content to render |
| `className` | `string` | - | Additional CSS classes |
### DisclosureTrigger Props
| Prop | Type | Default | Description |
| ----------- | ----------------------------- | ------- | ---------------------- |
| `children` | `ReactNode \| RenderFunction` | - | Trigger content |
| `className` | `string` | - | Additional CSS classes |
### DisclosurePanel Props
| Prop | Type | Default | Description |
| ----------- | ----------- | ------- | ---------------------- |
| `children` | `ReactNode` | - | Content to show/hide |
| `className` | `string` | - | Additional CSS classes |
### RenderProps
When using the render prop pattern, these values are provided:
| Prop | Type | Description |
| ------------ | --------- | ------------------------------ |
| `isExpanded` | `boolean` | Current expanded state |
| `isDisabled` | `boolean` | Whether disclosure is disabled |
# Link
**Category**: react
**URL**: https://v3.heroui.com/docs/react/components/link
**Source**: https://raw.githubusercontent.com/heroui-inc/heroui/refs/heads/v3/apps/docs/content/docs/react/components/(navigation)/link.mdx
> A styled anchor component for navigation with built-in icon support
## Import
```tsx
import { Link } from '@heroui/react';
```
### Usage
```tsx
import {Link} from "@heroui/react";
export function LinkBasic() {
return (
Call to action
);
}
```
### Anatomy
Import the Link component and access all parts using dot notation.
```tsx
import { Link } from '@heroui/react';
export default () => (
Call to action
);
```
### Custom Icon
```tsx
import {ArrowUpRightFromSquare, Link as LinkIcon} from "@gravity-ui/icons";
import {Link} from "@heroui/react";
export function LinkCustomIcon() {
return (
External link
Go to page
);
}
```
### Icon Placement
```tsx
import {Link} from "@heroui/react";
export function LinkIconPlacement() {
return (
Icon at end (default)
Icon at start
);
}
```
### Underline Variants
Control the underline behavior with the `underline` prop:
```tsx
import {Link} from "@heroui/react";
export function LinkUnderlineVariants() {
return (
Underline on hover (default)
Hover to see underline animation
Always visible underline
Underline always visible
No underline
Link without any underline
);
}
```
* `underline="hover"` (default) - Animated underline appears on hover
* `underline="always"` - Underline always visible (50% opacity, 100% on hover)
* `underline="none"` - No underline
### Underline Offset
Adjust the spacing between text and underline with the `underlineOffset` prop:
```tsx
import {Link} from "@heroui/react";
export function LinkUnderlineOffset() {
return (
Offset 1 (default)
Offset 2
Offset 3
);
}
```
* `underlineOffset={1}` (default) - No space
* `underlineOffset={2}` - 2px spacing
* `underlineOffset={3}` - 4px spacing
### Using with Routing Libraries
Use variant functions to style framework-specific links like Next.js:
```tsx
import { Link, linkVariants } from '@heroui/react';
import NextLink from 'next/link';
export default function Demo() {
const slots = linkVariants({underline: "hover"});
return (
About Page
);
}
```
### Direct Class Application
Since HeroUI uses [BEM](https://getbem.com/) classes, you can apply Link styles directly to any link element:
```tsx
import NextLink from 'next/link';
// Apply classes directly
export default function Demo() {
return (
About Page
);
}
// Or with a native anchor
export default function NativeLink() {
return (
About Page
);
}
```
Available BEM classes:
* Base: `link`
* Underline: `link--underline-none`, `link--underline-hover`, `link--underline-always`
* Offset: `link--offset-1`, `link--offset-2`, `link--offset-3`
## Styling
### Passing Tailwind CSS classes
```tsx
import { Link } from '@heroui/react';
function CustomLink() {
return (
Custom styled link
);
}
```
### Customizing the component classes
To customize the Link component classes, you can use the `@layer components` directive.
[Learn more](https://tailwindcss.com/docs/adding-custom-styles#adding-component-classes).
```css
@layer components {
.link {
@apply font-semibold no-underline hover:underline;
}
}
```
HeroUI follows the [BEM](https://getbem.com/) methodology to ensure component variants and states are reusable and easy to customize.
### CSS Classes
The Link component uses these CSS classes ([View source styles](https://github.com/heroui-inc/heroui/blob/v3/packages/styles/components/link.css)):
#### Base Classes
* `.link` - Base link styles
#### Underline Variants
* `.link--underline-none` - No underline
* `.link--underline-hover` - Animated underline on hover (default)
* `.link--underline-always` - Always visible underline
#### Underline Offset
* `.link--offset-1` - No spacing (default)
* `.link--offset-2` - 2px spacing
* `.link--offset-3` - 4px spacing
### 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 `[aria-disabled="true"]`
## API Reference
### Link Props
| Prop | Type | Default | Description |
| ----------------- | ------------------------------- | --------- | ----------------------------------------------------- |
| `href` | `string` | - | Destination URL for the anchor |
| `target` | `string` | `"_self"` | Controls where to open the linked document |
| `rel` | `string` | - | Relationship between the current and linked documents |
| `download` | `boolean \| string` | - | Prompts file download instead of navigation |
| `underline` | `"none" \| "hover" \| "always"` | `"hover"` | Controls underline visibility and behavior |
| `underlineOffset` | `1 \| 2 \| 3` | `1` | Spacing between text and underline |
| `isDisabled` | `boolean` | `false` | Disables pointer and keyboard interaction |
| `className` | `string` | - | Custom classes merged with the default styles |
| `children` | `React.ReactNode` | - | Content rendered inside the link |
| `onPress` | `(e: PressEvent) => void` | - | Fired when the link is activated |
| `autoFocus` | `boolean` | - | Whether the element should receive focus on render |
### Link.Icon Props
| Prop | Type | Default | Description |
| ----------- | ----------------- | ------- | --------------------------------------------------------------------- |
| `children` | `React.ReactNode` | - | Custom icon element; defaults to the built-in arrow icon when omitted |
| `className` | `string` | - | Additional CSS classes |
# Tabs
**Category**: react
**URL**: https://v3.heroui.com/docs/react/components/tabs
**Source**: https://raw.githubusercontent.com/heroui-inc/heroui/refs/heads/v3/apps/docs/content/docs/react/components/(navigation)/tabs.mdx
> Tabs organize content into multiple sections and allow users to navigate between them.
## Import
```tsx
import { Tabs } from '@heroui/react';
```
### Usage
### Anatomy
Import the Tabs component and access all parts using dot notation.
```tsx
import { Tabs } from '@heroui/react';
export default () => (
)
```
### Vertical
### Disabled Tab
### Custom Styles
## Styling
### Passing Tailwind CSS classes
```tsx
import { Tabs } from '@heroui/react';
function CustomTabs() {
return (
DailyWeeklyBi-WeeklyMonthly
This will permanently delete My Awesome Project and all of its
data. This action cannot be undone.
);
}
```
### Anatomy
Import the AlertDialog component and access all parts using dot notation.
```tsx
import {AlertDialog, Button} from "@heroui/react";
export default () => (
{/* Optional: Close button */}
{/* Optional: Status icon */}
);
```
### Statuses
```tsx
"use client";
import {AlertDialog, Button} from "@heroui/react";
export function Statuses() {
const examples = [
{
actions: {
cancel: "Stay Signed In",
confirm: "Sign Out",
},
body: "You'll need to sign in again to access your account. Any unsaved changes will be lost.",
classNames: "bg-accent-soft text-accent-soft-foreground",
header: "Sign out of your account?",
status: "accent",
trigger: "Sign Out",
},
{
actions: {
cancel: "Not Yet",
confirm: "Mark Complete",
},
body: "This will mark the task as complete and notify all team members. The task will be moved to your completed list.",
classNames: "bg-success-soft text-success-soft-foreground",
header: "Complete this task?",
status: "success",
trigger: "Complete Task",
},
{
actions: {
cancel: "Keep Editing",
confirm: "Discard",
},
body: "You have unsaved changes that will be permanently lost. Are you sure you want to discard them?",
classNames: "bg-warning-soft text-warning-soft-foreground",
header: "Discard unsaved changes?",
status: "warning",
trigger: "Discard Changes",
},
{
actions: {
cancel: "Cancel",
confirm: "Delete Account",
},
body: "This will permanently delete your account and remove all your data from our servers. This action is irreversible.",
classNames: "bg-danger-soft text-danger-soft-foreground",
header: "Delete your account?",
status: "danger",
trigger: "Delete Account",
},
] as const;
return (
{placement === "auto"
? "Automatically positions at the bottom on mobile and center on desktop for optimal user experience."
: `This dialog is positioned at the ${placement} of the viewport. Critical confirmations are typically centered for maximum attention.`}
))}
);
}
```
### Backdrop Variants
```tsx
"use client";
import {AlertDialog, Button} from "@heroui/react";
export function BackdropVariants() {
const variants = ["opaque", "blur", "transparent"] as const;
return (
{variant === "opaque"
? "An opaque dark backdrop that completely obscures the background, providing maximum focus on the dialog."
: variant === "blur"
? "A blurred backdrop that softly obscures the background while maintaining visual context."
: "A transparent backdrop that keeps the background fully visible, useful for less critical confirmations."}
))}
);
}
```
### Custom Icon
```tsx
"use client";
import {LockOpen} from "@gravity-ui/icons";
import {AlertDialog, Button} from "@heroui/react";
export function CustomIcon() {
return (
Reset your password?
We'll send a password reset link to your email address. You'll need to create a new
password to regain access to your account.
);
}
```
### Custom Backdrop
```tsx
"use client";
import {TriangleExclamation} from "@gravity-ui/icons";
import {AlertDialog, Button} from "@heroui/react";
export function CustomBackdrop() {
return (
Permanently delete your account?
This action cannot be undone. All your data, settings, and content will be
permanently removed from our servers. The dramatic red backdrop emphasizes the
severity and irreversibility of this decision.
);
}
```
### Dismiss Behavior
```tsx
"use client";
import {CircleInfo} from "@gravity-ui/icons";
import {AlertDialog, Button} from "@heroui/react";
export function DismissBehavior() {
return (
isDismissable
Controls whether the alert dialog can be dismissed by clicking the overlay backdrop. Alert
dialogs typically require explicit action, so this defaults to false. Set to{" "}
true for less critical confirmations.
isDismissable = false
Clicking the backdrop won't close this alert dialog
Try clicking outside this alert dialog on the overlay - it won't close. You must
use the action buttons to dismiss it.
isKeyboardDismissDisabled
Controls whether the ESC key can dismiss the alert dialog. Alert dialogs typically require
explicit action, so this defaults to true. When set to false,
the ESC key will be enabled.
isKeyboardDismissDisabled = true
ESC key is disabled
Press ESC - nothing happens. You must use the action buttons to dismiss this
alert dialog.
);
}
```
### Close Methods
```tsx
"use client";
import {AlertDialog, Button} from "@heroui/react";
export function CloseMethods() {
return (
Using slot="close"
The simplest way to close a dialog. Add slot="close" to any Button component
within the dialog. When clicked, it will automatically close the dialog.
Using slot="close"
Click either button below - both have slot="close" and will close
the dialog automatically.
Using Dialog render props
Access the close method from the Dialog's render props. This gives you full
control over when and how to close the dialog, allowing you to add custom logic before
closing.
{(renderProps) => (
<>
Using Dialog render props
The buttons below use the close method from render props. You
can add validation or other logic before calling{" "}
renderProps.close().
>
)}
);
}
```
### Controlled State
```tsx
"use client";
import {AlertDialog, Button, useOverlayState} from "@heroui/react";
import React from "react";
export function Controlled() {
const [isOpen, setIsOpen] = React.useState(false);
const state = useOverlayState();
return (
With React.useState()
Control the alert dialog using React's useState{" "}
hook for simple state management. Perfect for basic use cases.
Status:{" "}
{isOpen ? "open" : "closed"}
Controlled with useState()
This alert dialog is controlled by React's useState hook. Pass{" "}
isOpen and onOpenChange props to manage the dialog state
externally.
With useOverlayState()
Use the useOverlayState hook for a cleaner API
with convenient methods like open(), close(), and{" "}
toggle().
Status:{" "}
{state.isOpen ? "open" : "closed"}
Controlled with useOverlayState()
The useOverlayState hook provides dedicated methods for common
operations. No need to manually create callbacks—just use{" "}
state.open(), state.close(), or{" "}
state.toggle().
);
}
```
### Custom Trigger
```tsx
"use client";
import {TrashBin} from "@gravity-ui/icons";
import {AlertDialog, Button} from "@heroui/react";
export function CustomTrigger() {
return (
Delete Item
Permanently remove this item
Delete this item?
Use AlertDialog.Trigger to create custom trigger elements beyond
standard buttons. This example shows a card-style trigger with icons and descriptive
text.
);
}
```
### Custom Animations
```tsx
"use client";
import {ArrowUpFromLine, Sparkles} from "@gravity-ui/icons";
import {AlertDialog, Button} from "@heroui/react";
import React from "react";
const iconMap: Record> = {
"gravity-ui:arrow-up-from-line": ArrowUpFromLine,
"gravity-ui:sparkles": Sparkles,
};
export function CustomAnimations() {
const animations = [
{
classNames: {
backdrop: [
"data-[entering]:duration-400",
"data-[entering]:ease-[cubic-bezier(0.16,1,0.3,1)]",
"data-[exiting]:duration-200",
"data-[exiting]:ease-[cubic-bezier(0.7,0,0.84,0)]",
].join(" "),
container: [
"data-[entering]:animate-in",
"data-[entering]:fade-in-0",
"data-[entering]:zoom-in-95",
"data-[entering]:duration-400",
"data-[entering]:ease-[cubic-bezier(0.16,1,0.3,1)]",
"data-[exiting]:animate-out",
"data-[exiting]:fade-out-0",
"data-[exiting]:zoom-out-95",
"data-[exiting]:duration-200",
"data-[exiting]:ease-[cubic-bezier(0.7,0,0.84,0)]",
].join(" "),
},
description:
"Physics-based elastic scaling. Simulates a high-damping spring system with fast transient response and prolonged settling time. Ideal for Alert Dialogs and Modals.",
icon: "gravity-ui:sparkles",
name: "Kinematic Scale",
},
{
classNames: {
backdrop: [
"data-[entering]:duration-500",
"data-[entering]:ease-[cubic-bezier(0.25,1,0.5,1)]",
"data-[exiting]:duration-200",
"data-[exiting]:ease-[cubic-bezier(0.5,0,0.75,0)]",
].join(" "),
container: [
"data-[entering]:animate-in",
"data-[entering]:fade-in-0",
"data-[entering]:slide-in-from-bottom-4",
"data-[entering]:duration-500",
"data-[entering]:ease-[cubic-bezier(0.25,1,0.5,1)]",
"data-[exiting]:animate-out",
"data-[exiting]:fade-out-0",
"data-[exiting]:slide-out-to-bottom-2",
"data-[exiting]:duration-200",
"data-[exiting]:ease-[cubic-bezier(0.5,0,0.75,0)]",
].join(" "),
},
description:
"Simulates movement through a medium with fluid resistance. Eliminates mechanical linearity for a natural, grounded feel. Perfect for Bottom Sheets or Toasts.",
icon: "gravity-ui:arrow-up-from-line",
name: "Fluid Slide",
},
];
return (
Render alert dialogs inside a custom container instead of document.body
Apply transform: translateZ(0) to the
container to create a new stacking context.
{!!portalContainer && (
Custom Portal
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 nisi ut aliquip ex ea commodo consequat.
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 nisi ut aliquip ex ea commodo consequat.
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 nisi ut aliquip ex ea commodo consequat.
)}
);
}
```
## Related Components
* **Button**: Allows a user to perform an action
* **CloseButton**: Button for dismissing overlays
## Styling
### Passing Tailwind CSS classes
```tsx
import {AlertDialog, Button} from "@heroui/react";
function CustomAlertDialog() {
return (
Custom Styled Alert
This alert dialog has custom styling applied via Tailwind classes
);
}
```
### Customizing the component classes
To customize the AlertDialog component classes, you can use the `@layer components` directive.
[Learn more](https://tailwindcss.com/docs/adding-custom-styles#adding-component-classes).
```css
@layer components {
.alert-dialog__backdrop {
@apply bg-gradient-to-br from-black/60 to-black/80;
}
.alert-dialog__dialog {
@apply rounded-2xl border border-red-500/20 shadow-2xl;
}
.alert-dialog__header {
@apply gap-4;
}
.alert-dialog__icon {
@apply size-16;
}
.alert-dialog__close-trigger {
@apply rounded-full bg-white/10 hover:bg-white/20;
}
}
```
HeroUI follows the [BEM](https://getbem.com/) methodology to ensure component variants and states are reusable and easy to customize.
### CSS Classes
The AlertDialog component uses these CSS classes ([View source styles](https://github.com/heroui-inc/heroui/blob/v3/packages/styles/components/alert-dialog.css)):
#### Base Classes
* `.alert-dialog__trigger` - Trigger element that opens the alert dialog
* `.alert-dialog__backdrop` - Overlay backdrop behind the dialog
* `.alert-dialog__container` - Positioning wrapper with placement support
* `.alert-dialog__dialog` - Dialog content container
* `.alert-dialog__header` - Header section for icon and title
* `.alert-dialog__heading` - Heading text styles
* `.alert-dialog__body` - Main content area
* `.alert-dialog__footer` - Footer section for actions
* `.alert-dialog__icon` - Icon container with status colors
* `.alert-dialog__close-trigger` - Close button element
#### Backdrop Variants
* `.alert-dialog__backdrop--opaque` - Opaque colored backdrop (default)
* `.alert-dialog__backdrop--blur` - Blurred backdrop with glass effect
* `.alert-dialog__backdrop--transparent` - Transparent backdrop (no overlay)
#### Status Variants (Icon)
* `.alert-dialog__icon--default` - Default gray status
* `.alert-dialog__icon--accent` - Accent blue status
* `.alert-dialog__icon--success` - Success green status
* `.alert-dialog__icon--warning` - Warning orange status
* `.alert-dialog__icon--danger` - Danger red status
### Interactive States
The component supports these interactive states:
* **Focus**: `:focus-visible` or `[data-focus-visible="true"]` - Applied to trigger, dialog, and close button
* **Hover**: `:hover` or `[data-hovered="true"]` - Applied to close button on hover
* **Active**: `:active` or `[data-pressed="true"]` - Applied to close button when pressed
* **Entering**: `[data-entering]` - Applied during dialog opening animation
* **Exiting**: `[data-exiting]` - Applied during dialog closing animation
* **Placement**: `[data-placement="*"]` - Applied based on dialog position (auto, top, center, bottom)
## API Reference
### AlertDialog
| Prop | Type | Default | Description |
| ---------- | ----------- | ------- | ------------------------------ |
| `children` | `ReactNode` | - | Trigger and container elements |
### AlertDialog.Trigger
| Prop | Type | Default | Description |
| ----------- | ----------- | ------- | ---------------------- |
| `children` | `ReactNode` | - | Custom trigger content |
| `className` | `string` | - | CSS classes |
### AlertDialog.Backdrop
| Prop | Type | Default | Description |
| --------------------------- | ------------------------------------- | ---------- | ------------------------- |
| `variant` | `"opaque" \| "blur" \| "transparent"` | `"opaque"` | Backdrop overlay style |
| `isDismissable` | `boolean` | `false` | Close on backdrop click |
| `isKeyboardDismissDisabled` | `boolean` | `true` | Disable ESC key to close |
| `isOpen` | `boolean` | - | Controlled open state |
| `onOpenChange` | `(isOpen: boolean) => void` | - | Open state change handler |
| `className` | `string \| (values) => string` | - | Backdrop CSS classes |
| `UNSTABLE_portalContainer` | `HTMLElement` | - | Custom portal container |
### AlertDialog.Container
| Prop | Type | Default | Description |
| ----------- | ----------------------------------------- | -------- | ------------------------- |
| `placement` | `"auto" \| "center" \| "top" \| "bottom"` | `"auto"` | Dialog position on screen |
| `className` | `string \| (values) => string` | - | Container CSS classes |
### AlertDialog.Dialog
| Prop | Type | Default | Description |
| ------------------ | ------------------------------------- | --------------- | -------------------------- |
| `children` | `ReactNode \| ({close}) => ReactNode` | - | Content or render function |
| `className` | `string` | - | CSS classes |
| `role` | `string` | `"alertdialog"` | ARIA role |
| `aria-label` | `string` | - | Accessibility label |
| `aria-labelledby` | `string` | - | ID of label element |
| `aria-describedby` | `string` | - | ID of description element |
### AlertDialog.Header
| Prop | Type | Default | Description |
| ----------- | ----------- | ------- | ------------------------------------------- |
| `children` | `ReactNode` | - | Header content (typically Icon and Heading) |
| `className` | `string` | - | CSS classes |
### AlertDialog.Heading
| Prop | Type | Default | Description |
| ----------- | ----------- | ------- | ------------ |
| `children` | `ReactNode` | - | Heading text |
| `className` | `string` | - | CSS classes |
### AlertDialog.Body
| Prop | Type | Default | Description |
| ----------- | ----------- | ------- | ------------ |
| `children` | `ReactNode` | - | Body content |
| `className` | `string` | - | CSS classes |
### AlertDialog.Footer
| Prop | Type | Default | Description |
| ----------- | ----------- | ------- | ----------------------------------------- |
| `children` | `ReactNode` | - | Footer content (typically action buttons) |
| `className` | `string` | - | CSS classes |
### AlertDialog.Icon
| Prop | Type | Default | Description |
| ----------- | ------------------------------------------------------------- | ---------- | -------------------- |
| `children` | `ReactNode` | - | Custom icon element |
| `status` | `"default" \| "accent" \| "success" \| "warning" \| "danger"` | `"danger"` | Status color variant |
| `className` | `string` | - | CSS classes |
### AlertDialog.CloseTrigger
| Prop | Type | Default | Description |
| ----------- | ------------------------------ | ------- | ------------------- |
| `children` | `ReactNode` | - | Custom close button |
| `className` | `string \| (values) => string` | - | CSS classes |
### useOverlayState Hook
```tsx
import {useOverlayState} from "@heroui/react";
const state = useOverlayState({
defaultOpen: false,
onOpenChange: (isOpen) => console.log(isOpen),
});
state.isOpen; // Current state
state.open(); // Open dialog
state.close(); // Close dialog
state.toggle(); // Toggle state
state.setOpen(); // Set state directly
```
## Accessibility
Implements [WAI-ARIA AlertDialog pattern](https://www.w3.org/WAI/ARIA/apg/patterns/alertdialog/):
* **Focus trap**: Focus locked within alert dialog
* **Keyboard**: `ESC` closes (when enabled), `Tab` cycles elements
* **Screen readers**: Proper ARIA attributes with `role="alertdialog"`
* **Scroll lock**: Body scroll disabled when open
* **Required action**: Defaults to requiring explicit user action (no backdrop/ESC dismiss)
# Modal
**Category**: react
**URL**: https://v3.heroui.com/docs/react/components/modal
**Source**: https://raw.githubusercontent.com/heroui-inc/heroui/refs/heads/v3/apps/docs/content/docs/react/components/(overlays)/modal.mdx
> Dialog overlay for focused user interactions and important content
## Import
```tsx
import {Modal} from "@heroui/react";
```
### Usage
```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.
);
}
```
### Anatomy
Import the Modal component and access all parts using dot notation.
```tsx
import {Modal, Button} from "@heroui/react";
export default () => (
{/* Optional: Close button */}
{/* Optional: Icon */}
);
```
### Placement
```tsx
"use client";
import {Rocket} from "@gravity-ui/icons";
import {Button, Modal} from "@heroui/react";
export function Placements() {
const placements = ["auto", "top", "center", "bottom"] as const;
return (
This modal uses the {variant} backdrop variant. Compare the
different visual effects: opaque provides full opacity, blur adds a backdrop
filter, and transparent removes the background.
))}
);
}
```
### Sizes
```tsx
"use client";
import {Rocket} from "@gravity-ui/icons";
import {Button, Modal} from "@heroui/react";
export function Sizes() {
const sizes = ["xs", "sm", "md", "lg", "cover", "full"] as const;
return (
{size === "cover" ? (
<>
This modal 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 cover-style content that needs
maximum width while preserving modal aesthetics.
>
) : size === "full" ? (
<>
This modal uses the full size variant. It occupies the entire
viewport without any margins, rounded corners, or shadows, creating a true
fullscreen experience. Ideal for immersive content or full-page
interactions.
>
) : (
<>
This modal 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.
>
)}
))}
);
}
```
### Custom Backdrop
```tsx
"use client";
import {Sparkles} from "@gravity-ui/icons";
import {Button, Modal} from "@heroui/react";
export function CustomBackdrop() {
return (
Premium Backdrop
This backdrop features a sophisticated gradient that transitions from a dark color
at the bottom to complete transparency at the top, combined with a smooth blur
effect. The gradient automatically adapts its intensity for optimal contrast in both
light and dark modes.
);
}
```
### Dismiss Behavior
```tsx
"use client";
import {CircleInfo} from "@gravity-ui/icons";
import {Button, Modal} from "@heroui/react";
export function DismissBehavior() {
return (
isDismissable
Controls whether the modal can be dismissed by clicking the overlay backdrop. Defaults to{" "}
true. Set to false to require explicit close action.
isDismissable = false
Clicking the backdrop won't close this modal
Try clicking outside this modal on the overlay - it won't close. You must use
the close button or press ESC to dismiss it.
isKeyboardDismissDisabled
Controls whether the ESC key can dismiss the modal. When set to true, the ESC
key will be disabled and users must use explicit close actions.
isKeyboardDismissDisabled = true
ESC key is disabled
Press ESC - nothing happens. You must use the close button or click the overlay
backdrop to dismiss this modal.
);
}
```
### Close Methods
```tsx
"use client";
import {CircleCheck, CircleInfo} from "@gravity-ui/icons";
import {Button, Modal} from "@heroui/react";
export function CloseMethods() {
return (
Using slot="close"
The simplest way to close a modal. Add slot="close" to any Button component
within the modal. When clicked, it will automatically close the modal.
Using slot="close"
Click either button below - both have slot="close" and will close
the modal automatically.
Using Dialog render props
Access the close method from the Dialog's render props. This gives you full
control over when and how to close the modal, allowing you to add custom logic before
closing.
{(renderProps) => (
<>
Using Dialog render props
The buttons below use the close method from render props. You
can add validation or other logic before calling{" "}
renderProps.close().
Compare scroll behaviors - inside keeps content scrollable within the modal,
outside allows page scrolling
{Array.from({length: 30}).map((_, i) => (
Paragraph {i + 1}: Lorem ipsum dolor sit amet, consectetur adipiscing elit.
Nullam pulvinar risus non risus hendrerit venenatis. Pellentesque sit amet
hendrerit risus, sed porttitor quam.
))}
);
}
```
### Controlled State
```tsx
"use client";
import {CircleCheck} from "@gravity-ui/icons";
import {Button, Modal, useOverlayState} from "@heroui/react";
import React from "react";
export function Controlled() {
const [isOpen, setIsOpen] = React.useState(false);
const state = useOverlayState();
return (
With React.useState()
Control the modal using React's useState hook for
simple state management. Perfect for basic use cases.
Status:{" "}
{isOpen ? "open" : "closed"}
Controlled with useState()
This modal is controlled by React's useState hook. Pass{" "}
isOpen and onOpenChange props to manage the modal state
externally.
With useOverlayState()
Use the useOverlayState hook for a cleaner API
with convenient methods like open(), close(), and{" "}
toggle().
Status:{" "}
{state.isOpen ? "open" : "closed"}
Controlled with useOverlayState()
The useOverlayState hook provides dedicated methods for common
operations. No need to manually create callbacks—just use{" "}
state.open(), state.close(), or{" "}
state.toggle().
);
}
```
### With Form
```tsx
"use client";
import {Envelope} from "@gravity-ui/icons";
import {Button, Input, Label, Modal, Surface, TextField} from "@heroui/react";
export function WithForm() {
return (
Contact Us
Fill out the form below and we'll get back to you. The modal adapts automatically
when the keyboard appears on mobile.
);
}
```
### Custom Trigger
```tsx
"use client";
import {Gear} from "@gravity-ui/icons";
import {Button, Modal} from "@heroui/react";
export function CustomTrigger() {
return (
Settings
Manage your preferences
Settings
Use Modal.Trigger to create custom trigger elements beyond standard
buttons. This example shows a card-style trigger with icons and descriptive text.
);
}
```
### Custom Animations
```tsx
"use client";
import {ArrowUpFromLine, Sparkles} from "@gravity-ui/icons";
import {Button, Modal} from "@heroui/react";
import React from "react";
const iconMap: Record> = {
"gravity-ui:arrow-up-from-line": ArrowUpFromLine,
"gravity-ui:sparkles": Sparkles,
};
export function CustomAnimations() {
const animations = [
{
classNames: {
backdrop: [
"data-[entering]:duration-400",
"data-[entering]:ease-[cubic-bezier(0.16,1,0.3,1)]",
"data-[exiting]:duration-200",
"data-[exiting]:ease-[cubic-bezier(0.7,0,0.84,0)]",
].join(" "),
container: [
"data-[entering]:animate-in",
"data-[entering]:fade-in-0",
"data-[entering]:zoom-in-95",
"data-[entering]:duration-400",
"data-[entering]:ease-[cubic-bezier(0.16,1,0.3,1)]",
"data-[exiting]:animate-out",
"data-[exiting]:fade-out-0",
"data-[exiting]:zoom-out-95",
"data-[exiting]:duration-200",
"data-[exiting]:ease-[cubic-bezier(0.7,0,0.84,0)]",
].join(" "),
},
description:
"Physics-based elastic scaling. Simulates a high-damping spring system with fast transient response and prolonged settling time. Ideal for Modals and Popovers.",
icon: "gravity-ui:sparkles",
name: "Kinematic Scale",
},
{
classNames: {
backdrop: [
"data-[entering]:duration-500",
"data-[entering]:ease-[cubic-bezier(0.25,1,0.5,1)]",
"data-[exiting]:duration-200",
"data-[exiting]:ease-[cubic-bezier(0.5,0,0.75,0)]",
].join(" "),
container: [
"data-[entering]:animate-in",
"data-[entering]:fade-in-0",
"data-[entering]:slide-in-from-bottom-4",
"data-[entering]:duration-500",
"data-[entering]:ease-[cubic-bezier(0.25,1,0.5,1)]",
"data-[exiting]:animate-out",
"data-[exiting]:fade-out-0",
"data-[exiting]:slide-out-to-bottom-2",
"data-[exiting]:duration-200",
"data-[exiting]:ease-[cubic-bezier(0.5,0,0.75,0)]",
].join(" "),
},
description:
"Simulates movement through a medium with fluid resistance. Eliminates mechanical linearity for a natural, grounded feel. Perfect for Bottom Sheets or Toasts.",
icon: "gravity-ui:arrow-up-from-line",
name: "Fluid Slide",
},
];
return (
Render modals inside a custom container instead of document.body
Apply transform: translateZ(0) to the
container to create a new stacking context.
{!!portalContainer && (
Custom Portal
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 nisi ut aliquip ex ea commodo consequat.
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 nisi ut aliquip ex ea commodo consequat.
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 nisi ut aliquip ex ea commodo consequat.
This modal has custom styling applied via Tailwind classes
);
}
```
### Customizing the component classes
To customize the Modal component classes, you can use the `@layer components` directive.
[Learn more](https://tailwindcss.com/docs/adding-custom-styles#adding-component-classes).
```css
@layer components {
.modal__backdrop {
@apply bg-gradient-to-br from-black/50 to-black/70;
}
.modal__dialog {
@apply rounded-2xl border border-white/10 shadow-2xl;
}
.modal__header {
@apply text-center;
}
.modal__close-trigger {
@apply rounded-full bg-white/10 hover:bg-white/20;
}
}
```
HeroUI follows the [BEM](https://getbem.com/) methodology to ensure component variants and states are reusable and easy to customize.
### CSS Classes
The Modal component uses these CSS classes ([View source styles](https://github.com/heroui-inc/heroui/blob/v3/packages/styles/components/modal.css)):
#### Base Classes
* `.modal__trigger` - Trigger element that opens the modal
* `.modal__backdrop` - Overlay backdrop behind the modal
* `.modal__container` - Positioning wrapper with placement support
* `.modal__dialog` - Modal content container
* `.modal__header` - Header section for titles and icons
* `.modal__body` - Main content area
* `.modal__footer` - Footer section for actions
* `.modal__close-trigger` - Close button element
#### Backdrop Variants
* `.modal__backdrop--opaque` - Opaque colored backdrop (default)
* `.modal__backdrop--blur` - Blurred backdrop with glass effect
* `.modal__backdrop--transparent` - Transparent backdrop (no overlay)
#### Scroll Variants
* `.modal__container--scroll-outside` - Enables scrolling the entire modal
* `.modal__dialog--scroll-inside` - Constrains modal height for body scrolling
* `.modal__body--scroll-inside` - Makes only the body scrollable
* `.modal__body--scroll-outside` - Allows full-page scrolling
### Interactive States
The component supports these interactive states:
* **Focus**: `:focus-visible` or `[data-focus-visible="true"]` - Applied to trigger, dialog, and close button
* **Hover**: `:hover` or `[data-hovered="true"]` - Applied to close button on hover
* **Active**: `:active` or `[data-pressed="true"]` - Applied to close button when pressed
* **Entering**: `[data-entering]` - Applied during modal opening animation
* **Exiting**: `[data-exiting]` - Applied during modal closing animation
* **Placement**: `[data-placement="*"]` - Applied based on modal position (auto, top, center, bottom)
## API Reference
### Modal
| Prop | Type | Default | Description |
| ---------- | ----------- | ------- | ------------------------------ |
| `children` | `ReactNode` | - | Trigger and container elements |
### Modal.Trigger
| Prop | Type | Default | Description |
| ----------- | ----------- | ------- | ---------------------- |
| `children` | `ReactNode` | - | Custom trigger content |
| `className` | `string` | - | CSS classes |
### Modal.Backdrop
| Prop | Type | Default | Description |
| --------------------------- | ------------------------------------- | ---------- | ------------------------- |
| `variant` | `"opaque" \| "blur" \| "transparent"` | `"opaque"` | Backdrop overlay style |
| `isDismissable` | `boolean` | `true` | Close on backdrop click |
| `isKeyboardDismissDisabled` | `boolean` | `false` | Disable ESC key to close |
| `isOpen` | `boolean` | - | Controlled open state |
| `onOpenChange` | `(isOpen: boolean) => void` | - | Open state change handler |
| `className` | `string \| (values) => string` | - | Backdrop CSS classes |
| `UNSTABLE_portalContainer` | `HTMLElement` | - | Custom portal container |
### Modal.Container
| Prop | Type | Default | Description |
| ----------- | --------------------------------------------------- | ---------- | ------------------------ |
| `placement` | `"auto" \| "center" \| "top" \| "bottom"` | `"auto"` | Modal position on screen |
| `scroll` | `"inside" \| "outside"` | `"inside"` | Scroll behavior |
| `size` | `"xs" \| "sm" \| "md" \| "lg" \| "cover" \| "full"` | `"md"` | Modal size variant |
| `className` | `string \| (values) => string` | - | Container CSS classes |
### Modal.Dialog
| Prop | Type | Default | Description |
| ------------------ | ------------------------------------- | ---------- | -------------------------- |
| `children` | `ReactNode \| ({close}) => ReactNode` | - | Content or render function |
| `className` | `string \| (values) => string` | - | CSS classes |
| `role` | `string` | `"dialog"` | ARIA role |
| `aria-label` | `string` | - | Accessibility label |
| `aria-labelledby` | `string` | - | ID of label element |
| `aria-describedby` | `string` | - | ID of description element |
### Modal.Header
| Prop | Type | Default | Description |
| ----------- | ----------- | ------- | -------------- |
| `children` | `ReactNode` | - | Header content |
| `className` | `string` | - | CSS classes |
### Modal.Body
| Prop | Type | Default | Description |
| ----------- | ----------- | ------- | ------------ |
| `children` | `ReactNode` | - | Body content |
| `className` | `string` | - | CSS classes |
### Modal.Footer
| Prop | Type | Default | Description |
| ----------- | ----------- | ------- | -------------- |
| `children` | `ReactNode` | - | Footer content |
| `className` | `string` | - | CSS classes |
### Modal.CloseTrigger
| Prop | Type | Default | Description |
| ----------- | ------------------------------ | ------- | ------------------- |
| `children` | `ReactNode` | - | Custom close button |
| `className` | `string \| (values) => string` | - | CSS classes |
### useOverlayState Hook
```tsx
import {useOverlayState} from "@heroui/react";
const state = useOverlayState({
defaultOpen: false,
onOpenChange: (isOpen) => console.log(isOpen),
});
state.isOpen; // Current state
state.open(); // Open modal
state.close(); // Close modal
state.toggle(); // Toggle state
state.setOpen(); // Set state directly
```
## Accessibility
Implements [WAI-ARIA Dialog pattern](https://www.w3.org/WAI/ARIA/apg/patterns/dialog-modal/):
* **Focus trap**: Focus locked within modal
* **Keyboard**: `ESC` closes (when enabled), `Tab` cycles elements
* **Screen readers**: Proper ARIA attributes
* **Scroll lock**: Body scroll disabled when open
# Popover
**Category**: react
**URL**: https://v3.heroui.com/docs/react/components/popover
**Source**: https://raw.githubusercontent.com/heroui-inc/heroui/refs/heads/v3/apps/docs/content/docs/react/components/(overlays)/popover.mdx
> Displays rich content in a portal triggered by a button or any custom element
## Import
```tsx
import { Popover } from '@heroui/react';
```
### Usage
```tsx
import {Button, Popover} from "@heroui/react";
export function PopoverBasic() {
return (
Popover Title
This is the popover content. You can put any content here.
);
}
```
### Anatomy
Import the Popover component and access all parts using dot notation.
```tsx
import { Popover } from '@heroui/react';
export default () => (
{/* content goes here */}
)
```
### With Arrow
```tsx
import {Ellipsis} from "@gravity-ui/icons";
import {Button, Popover} from "@heroui/react";
export function PopoverWithArrow() {
return (
Popover with Arrow
The arrow shows which element triggered the popover.
Popover with Arrow
The arrow shows which element triggered the popover.
);
}
```
### Placement
```tsx
import {Button, Popover} from "@heroui/react";
export function PopoverPlacement() {
return (
Top placement
Left placement
Click buttons
Right placement
Bottom placement
);
}
```
### Interactive Content
```tsx
"use client";
import {Avatar, Button, Popover} from "@heroui/react";
import {useState} from "react";
export function PopoverInteractive() {
const [isFollowing, setIsFollowing] = useState(false);
return (
SJ
Sarah Johnson
@sarahj
SJ
Sarah Johnson
@sarahj
Product designer and creative director. Building beautiful experiences that matter.
892Following
12.5KFollowers
);
}
```
## Related Components
* **Button**: Allows a user to perform an action
* **Tooltip**: Contextual information on hover or focus
* **Select**: Dropdown select control
## Styling
### Passing Tailwind CSS classes
```tsx
import { Popover, Button } from '@heroui/react';
function CustomPopover() {
return (
Custom Styled
This popover has custom styling
);
}
```
### Customizing the component classes
To customize the Popover component classes, you can use the `@layer components` directive.
[Learn more](https://tailwindcss.com/docs/adding-custom-styles#adding-component-classes).
```css
@layer components {
.popover {
@apply rounded-xl shadow-2xl;
}
.popover__dialog {
@apply p-4;
}
.popover__heading {
@apply text-lg font-bold;
}
}
```
HeroUI follows the [BEM](https://getbem.com/) methodology to ensure component variants and states are reusable and easy to customize.
### CSS Classes
The Popover component uses these CSS classes ([View source styles](https://github.com/heroui-inc/heroui/blob/v3/packages/styles/components/popover.css)):
#### Base Classes
* `.popover` - Base popover container styles
* `.popover__dialog` - Dialog content wrapper
* `.popover__heading` - Heading text styles
* `.popover__trigger` - Trigger element styles
### Interactive States
The component supports animation states:
* **Entering**: `[data-entering]` - Applied during popover appearance
* **Exiting**: `[data-exiting]` - Applied during popover disappearance
* **Placement**: `[data-placement="*"]` - Applied based on popover position
* **Focus**: `:focus-visible` or `[data-focus-visible="true"]`
## API Reference
### Popover Props
| Prop | Type | Default | Description |
| -------------- | --------------------------- | ------- | ---------------------------------------- |
| `children` | `React.ReactNode` | - | Trigger and content elements |
| `isOpen` | `boolean` | - | Controls popover visibility (controlled) |
| `defaultOpen` | `boolean` | `false` | Initial open state (uncontrolled) |
| `onOpenChange` | `(isOpen: boolean) => void` | - | Called when open state changes |
### Popover.Content Props
| Prop | Type | Default | Description |
| ------------ | ------------------------------------------------------- | ---------- | --------------------------------------------- |
| `children` | `React.ReactNode` | - | Content to display in the popover |
| `placement` | `"top" \| "bottom" \| "left" \| "right"` (and variants) | `"bottom"` | Placement of the popover |
| `offset` | `number` | `8` | Distance from the trigger element |
| `shouldFlip` | `boolean` | `true` | Whether popover can change orientation to fit |
| `className` | `string` | - | Additional CSS classes |
### Popover.Dialog Props
| Prop | Type | Default | Description |
| ----------- | ----------------- | ------- | ---------------------- |
| `children` | `React.ReactNode` | - | Dialog content |
| `className` | `string` | - | Additional CSS classes |
### Popover.Trigger Props
| Prop | Type | Default | Description |
| ----------- | ----------------- | ------- | --------------------------------- |
| `children` | `React.ReactNode` | - | Element that triggers the popover |
| `className` | `string` | - | Additional CSS classes |
### Popover.Arrow Props
| Prop | Type | Default | Description |
| ----------- | ----------------- | ------- | ---------------------- |
| `children` | `React.ReactNode` | - | Custom arrow element |
| `className` | `string` | - | Additional CSS classes |
# Tooltip
**Category**: react
**URL**: https://v3.heroui.com/docs/react/components/tooltip
**Source**: https://raw.githubusercontent.com/heroui-inc/heroui/refs/heads/v3/apps/docs/content/docs/react/components/(overlays)/tooltip.mdx
> Displays informative text when users hover over or focus on an element
## Import
```tsx
import { Tooltip } from '@heroui/react';
```
### Usage
```tsx
import {CircleInfo} from "@gravity-ui/icons";
import {Button, Tooltip} from "@heroui/react";
export function TooltipBasic() {
return (
This is a tooltip
More information
);
}
```
### Anatomy
Import the Tooltip component and access all parts using dot notation.
```tsx
import { Tooltip, Button } from '@heroui/react';
export default () => (
Helpful information about this element
)
```
### With Arrow
```tsx
import {Button, Tooltip} from "@heroui/react";
export function TooltipWithArrow() {
return (
Tooltip with arrow indicator
Custom offset from trigger
);
}
```
### Placement
```tsx
import {Button, Tooltip} from "@heroui/react";
export function TooltipPlacement() {
return (
Top placement
Left placement
Hover buttons
Right placement
Bottom placement
);
}
```
### Custom Triggers
```tsx
import {CircleCheckFill, CircleQuestion} from "@gravity-ui/icons";
import {Avatar, Chip, Tooltip} from "@heroui/react";
export function TooltipCustomTrigger() {
return (
JD
Jane Doe
jane@example.com
Active
Jane is currently online
Help Information
This is a helpful tooltip with more detailed information about this feature.
);
}
```
## Related Components
* **Button**: Allows a user to perform an action
* **Popover**: Displays content in context with a trigger
## Styling
### Passing Tailwind CSS classes
```tsx
import { Tooltip, Button } from '@heroui/react';
function CustomTooltip() {
return (
Custom styled tooltip
);
}
```
### Customizing the component classes
To customize the Tooltip component classes, you can use the `@layer components` directive.
[Learn more](https://tailwindcss.com/docs/adding-custom-styles#adding-component-classes).
```css
@layer components {
.tooltip {
@apply rounded-xl shadow-lg;
}
.tooltip__trigger {
@apply cursor-help;
}
}
```
HeroUI follows the [BEM](https://getbem.com/) methodology to ensure component variants and states are reusable and easy to customize.
### CSS Classes
The Tooltip component uses these CSS classes ([View source styles](https://github.com/heroui-inc/heroui/blob/v3/packages/styles/components/tooltip.css)):
#### Base Classes
* `.tooltip` - Base tooltip styles with animations
* `.tooltip__trigger` - Trigger element styles
### Interactive States
The component supports animation states:
* **Entering**: `[data-entering]` - Applied during tooltip appearance
* **Exiting**: `[data-exiting]` - Applied during tooltip disappearance
* **Placement**: `[data-placement="*"]` - Applied based on tooltip position
## API Reference
### Tooltip Props
| Prop | Type | Default | Description |
| ------------ | -------------------- | --------- | -------------------------------------------- |
| `children` | `React.ReactNode` | - | Trigger element and content |
| `delay` | `number` | `700` | Delay in milliseconds before showing tooltip |
| `closeDelay` | `number` | `0` | Delay in milliseconds before hiding tooltip |
| `trigger` | `"hover" \| "focus"` | `"hover"` | How the tooltip is triggered |
| `isDisabled` | `boolean` | `false` | Whether the tooltip is disabled |
### Tooltip.Content Props
| Prop | Type | Default | Description |
| ----------- | ------------------------------------------------------- | ------------------ | ----------------------------------- |
| `children` | `React.ReactNode` | - | Content to display in the tooltip |
| `showArrow` | `boolean` | `false` | Whether to show the arrow indicator |
| `offset` | `number` | `3` (7 with arrow) | Distance from the trigger element |
| `placement` | `"top" \| "bottom" \| "left" \| "right"` (and variants) | `"top"` | Placement of the tooltip |
| `className` | `string` | - | Additional CSS classes |
### Tooltip.Trigger Props
| Prop | Type | Default | Description |
| ----------- | ----------------- | ------- | --------------------------------- |
| `children` | `React.ReactNode` | - | Element that triggers the tooltip |
| `className` | `string` | - | Additional CSS classes |
### Tooltip.Arrow Props
| Prop | Type | Default | Description |
| ----------- | ----------------- | ------- | ---------------------- |
| `children` | `React.ReactNode` | - | Custom arrow element |
| `className` | `string` | - | Additional CSS classes |
# ComboBox
**Category**: react
**URL**: https://v3.heroui.com/docs/react/components/combobox
**Source**: https://raw.githubusercontent.com/heroui-inc/heroui/refs/heads/v3/apps/docs/content/docs/react/components/(pickers)/combobox.mdx
> A combo box combines a text input with a listbox, allowing users to filter a list of options to items matching a query
## Import
```tsx
import { ComboBox } from '@heroui/react';
```
### Usage
```tsx
"use client";
import {ComboBox, Input, Label, ListBox} from "@heroui/react";
export function Default() {
return (
Favorite Animal
Aardvark
Cat
Dog
Kangaroo
Panda
Snake
);
}
```
### Anatomy
Import the ComboBox component and access all parts using dot notation.
```tsx
import { ComboBox, Input, Label, Description, Header, ListBox, Separator } from '@heroui/react';
export default () => (
)
```
### With Description
```tsx
"use client";
import {ComboBox, Description, Input, Label, ListBox} from "@heroui/react";
export function WithDescription() {
return (
Favorite Animal
Aardvark
Cat
Dog
Kangaroo
Panda
Snake
Search and select your favorite animal
);
}
```
### With Sections
```tsx
"use client";
import {ComboBox, Header, Input, Label, ListBox, Separator} from "@heroui/react";
export function WithSections() {
return (
CountryNorth America
United States
Canada
Mexico
Europe
United Kingdom
France
Germany
Spain
Italy
Asia
Japan
China
India
South Korea
);
}
```
### With Disabled Options
```tsx
"use client";
import {ComboBox, Input, Label, ListBox} from "@heroui/react";
export function WithDisabledOptions() {
return (
Animal
Dog
Cat
Bird
Kangaroo
Elephant
Tiger
);
}
```
### Custom Indicator
```tsx
"use client";
import {ChevronsExpandVertical} from "@gravity-ui/icons";
import {ComboBox, Input, Label, ListBox} from "@heroui/react";
export function CustomIndicator() {
return (
Favorite Animal
Aardvark
Cat
Dog
Kangaroo
Panda
Snake
);
}
```
### Required
```tsx
"use client";
import {Button, ComboBox, FieldError, Form, Input, Label, ListBox} from "@heroui/react";
export function Required() {
const onSubmit = (e: React.FormEvent) => {
e.preventDefault();
const formData = new FormData(e.currentTarget);
const data: Record = {};
formData.forEach((value, key) => {
data[key] = value.toString();
});
alert("Form submitted successfully!");
};
return (
);
}
```
### Custom Value
```tsx
"use client";
import {
Avatar,
AvatarFallback,
AvatarImage,
ComboBox,
Description,
Input,
Label,
ListBox,
} from "@heroui/react";
export function CustomValue() {
const users = [
{
avatarUrl: "https://heroui-assets.nyc3.cdn.digitaloceanspaces.com/avatars/blue.jpg",
email: "bob@heroui.com",
fallback: "B",
id: "1",
name: "Bob",
},
{
avatarUrl: "https://heroui-assets.nyc3.cdn.digitaloceanspaces.com/avatars/green.jpg",
email: "fred@heroui.com",
fallback: "F",
id: "2",
name: "Fred",
},
{
avatarUrl: "https://heroui-assets.nyc3.cdn.digitaloceanspaces.com/avatars/purple.jpg",
email: "martha@heroui.com",
fallback: "M",
id: "3",
name: "Martha",
},
{
avatarUrl: "https://heroui-assets.nyc3.cdn.digitaloceanspaces.com/avatars/red.jpg",
email: "john@heroui.com",
fallback: "J",
id: "4",
name: "John",
},
{
avatarUrl: "https://heroui-assets.nyc3.cdn.digitaloceanspaces.com/avatars/orange.jpg",
email: "jane@heroui.com",
fallback: "J",
id: "5",
name: "Jane",
},
];
return (
User
{users.map((user) => (
{user.fallback}
);
}
```
### Instructional Text
```tsx
import {Kbd} from "@heroui/react";
export function InstructionalText() {
return (
Quick Actions
• Open search:{" "}
K
• Toggle sidebar:{" "}
B
• New file:{" "}
N
• Quick save:{" "}
S
);
}
```
### Special Keys
```tsx
import {Kbd} from "@heroui/react";
export function SpecialKeys() {
return (
Press{" "}
{" "}
to confirm or{" "}
{" "}
to cancel.
Use{" "}
{" "}
to navigate between form fields and{" "}
{" "}
to go back.
Hold{" "}
{" "}
to temporarily enable panning mode.
);
}
```
### Variants
```tsx
import {Kbd} from "@heroui/react";
export function Variants() {
return (
Copy:CC
Paste:VV
Cut:XX
Undo:ZZ
Redo:ZZ
);
}
```
## Styling
### Passing Tailwind CSS classes
```tsx
import { Kbd } from "@heroui/react";
function CustomKbd() {
return (
K
);
}
```
### Customizing the component classes
To customize the Kbd component classes, you can use the `@layer components` directive.
[Learn more](https://tailwindcss.com/docs/adding-custom-styles#adding-component-classes).
```css
@layer components {
.kbd {
@apply bg-gray-100 dark:bg-gray-800 border-gray-300;
}
.kbd__abbr {
@apply font-bold;
}
.kbd__content {
@apply text-sm;
}
}
```
HeroUI follows the [BEM](https://getbem.com/) methodology to ensure component variants and states are reusable and easy to customize.
### CSS Classes
The Kbd component uses these CSS classes ([View source styles](https://github.com/heroui-inc/heroui/blob/v3/packages/styles/components/kbd.css)):
#### Base Classes
* `.kbd` - Base keyboard key styles with background, border, and spacing
* `.kbd__abbr` - Abbreviation element for modifier keys
* `.kbd__content` - Content wrapper for key text
## API Reference
### Kbd Props
| Prop | Type | Default | Description | |
| ----------- | ----------------- | --------- | ------------------ | --------------------------- |
| `children` | `React.ReactNode` | - | Content of the key | |
| `variant` | \`"default" | "light"\` | `default` | Variant of the keyboard key |
| `className` | `string` | - | Custom CSS classes | |
### Kbd.Abbr Props
| Prop | Type | Default | Description |
| ----------- | ----------------- | ------- | --------------------------------------------------------- |
| `title` | `string` | - | Title attribute for accessibility (e.g., "Command" for ⌘) |
| `children` | `React.ReactNode` | - | The symbol or text to display (e.g., ⌘, ⌥, ⇧) |
| `className` | `string` | - | Custom CSS classes |
### Kbd.Key Props
| Prop | Type | Default | Description |
| ----------- | ----------------- | ------- | ----------------------- |
| `children` | `React.ReactNode` | - | Text content of the key |
| `className` | `string` | - | Custom CSS classes |
### Kbd.Content Type
Available key values for the `keyValue` prop:
| Modifier Keys | Special Keys | Navigation Keys | Function Keys |
| ------------- | ------------ | --------------- | ------------- |
| `command` | `enter` | `up` | `fn` |
| `shift` | `delete` | `down` | |
| `ctrl` | `escape` | `left` | |
| `option` | `tab` | `right` | |
| `alt` | `space` | `pageup` | |
| `win` | `capslock` | `pagedown` | |
| | `help` | `home` | |
| | | `end` | |
# Scroll Shadow
**Category**: react
**URL**: https://v3.heroui.com/docs/react/components/scroll-shadow
**Source**: https://raw.githubusercontent.com/heroui-inc/heroui/refs/heads/v3/apps/docs/content/docs/react/components/(utilities)/scroll-shadow.mdx
> Apply visual shadows to indicate scrollable content overflow with automatic detection of scroll position.
## Import
```tsx
import {ScrollShadow} from "@heroui/react";
```
## Usage
```tsx
import {ScrollShadow} from "@heroui/react";
export default function Default() {
return (
{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.
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
))}
);
}
```
## Hide Scroll Bar
```tsx
import {ScrollShadow} from "@heroui/react";
export default function HideScrollBar() {
return (
{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.
))}
);
}
```
## On Surface
```tsx
import {ScrollShadow, Surface} from "@heroui/react";
export default function OnSurface() {
return (
{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.
))}
);
}
```
## Custom Shadow Size
```tsx
import {ScrollShadow} from "@heroui/react";
export default function CustomSize() {
return (
{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.
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 Shadow State: {horizontalState}
setHorizontalState(visibility)}
>
{Array.from({length: 10}).map((_, idx) => (
Bridging the FutureToday, 6:30 PM
))}
);
}
```
## With Card
```tsx
import {Button, Card, ScrollShadow} from "@heroui/react";
export default function WithCard() {
return (
Terms and ConditionsPlease review before proceeding
{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.