# 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

Outline

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 * **Only direct child buttons receive the ButtonGroup props** - Buttons nested inside other components (like Modal, Dropdown, etc.) will not inherit the group's props even if they are descendants of the ButtonGroup * Individual Button components can override the group's `isDisabled` prop by setting `isDisabled={false}` * The component automatically handles border radius 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 (
); } ``` ### Custom Render Function ```tsx "use client"; import {Button} from "@heroui/react"; export function CustomRenderFunction() { return ( ); } ``` ## Related Components * **Popover**: Displays content in context with a trigger * **Tooltip**: Contextual information on hover or focus * **Form**: Form validation and submission handling ## Styling ### Passing Tailwind CSS classes ```tsx import { Button } from '@heroui/react'; function CustomButton() { return ( ); } ``` ### 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 ); } ``` ### CSS Classes The Button component uses these CSS classes ([View source styles](https://github.com/heroui-inc/heroui/blob/v3/packages/styles/components/button.css)): #### Base & Size Classes * `.button` - Base button styles * `.button--sm` - Small size variant * `.button--md` - Medium size variant * `.button--lg` - Large size variant #### Variant Classes * `.button--primary` * `.button--secondary` * `.button--tertiary` * `.button--outline` * `.button--ghost` * `.button--danger` #### Modifier Classes * `.button--icon-only` * `.button--icon-only.button--sm` * `.button--icon-only.button--lg` ### Interactive States The button supports both CSS pseudo-classes and data attributes for flexibility: * **Hover**: `:hover` or `[data-hovered="true"]` * **Active/Pressed**: `:active` or `[data-pressed="true"]` (includes scale transform) * **Focus**: `:focus-visible` or `[data-focus-visible="true"]` (shows focus ring) * **Disabled**: `:disabled` or `[aria-disabled="true"]` (reduced opacity, no pointer events) * **Pending**: `[data-pending]` (no pointer events during loading) ## API Reference ### Button Props | Prop | Type | Default | Description | | ------------ | ---------------------------------------------------------------------------- | ----------- | ---------------------------------------------------------------- | | `variant` | `'primary' \| 'secondary' \| 'tertiary' \| 'outline' \| 'ghost' \| 'danger'` | `'primary'` | Visual style variant | | `size` | `'sm' \| 'md' \| 'lg'` | `'md'` | Size of the button | | `fullWidth` | `boolean` | `false` | Whether the button should take full width of its container | | `isDisabled` | `boolean` | `false` | Whether the button is disabled | | `isPending` | `boolean` | `false` | Whether the button is in a loading state | | `isIconOnly` | `boolean` | `false` | Whether the button contains only an icon | | `onPress` | `(e: PressEvent) => void` | - | Handler called when the button is pressed | | `children` | `React.ReactNode \| (values: ButtonRenderProps) => React.ReactNode` | - | Button content or render prop | | `render` | `DOMRenderFunction` | - | Overrides the default DOM element with a custom render function. | ### ButtonRenderProps When using the render prop pattern, these values are provided: | Prop | Type | Description | | ---------------- | --------- | ---------------------------------------------- | | `isPending` | `boolean` | Whether the button is in a loading state | | `isPressed` | `boolean` | Whether the button is currently pressed | | `isHovered` | `boolean` | Whether the button is hovered | | `isFocused` | `boolean` | Whether the button is focused | | `isFocusVisible` | `boolean` | Whether the button should show focus indicator | | `isDisabled` | `boolean` | Whether the button is disabled |
# CloseButton **Category**: react **URL**: https://v3.heroui.com/docs/react/components/close-button **Source**: https://raw.githubusercontent.com/heroui-inc/heroui/refs/heads/v3/apps/docs/content/docs/react/components/(buttons)/close-button.mdx > Button component for closing dialogs, modals, or dismissing content ## Import ```tsx import {CloseButton} from "@heroui/react"; ``` ### Usage ```tsx import {CloseButton} from "@heroui/react"; export function Default() { return ; } ``` ### With Custom Icon ```tsx import {CircleXmark, Xmark} from "@gravity-ui/icons"; import {CloseButton} from "@heroui/react"; export function WithCustomIcon() { return (
Custom Icon
Alternative Icon
); } ``` ### Interactive ```tsx "use client"; import {CloseButton} from "@heroui/react"; import {useState} from "react"; export function Interactive() { const [count, setCount] = useState(0); return (
setCount(count + 1)} /> Clicked: {count} times
); } ``` ## Related Components * **Alert**: Display important messages and notifications * **AlertDialog**: Critical confirmations requiring user attention * **Chip**: Compact elements for tags and filters ## Styling ### Passing Tailwind CSS classes ```tsx import {CloseButton} from "@heroui/react"; function CustomCloseButton() { return Close; } ``` ### Customizing the component classes To customize the CloseButton component classes, you can use the `@layer components` directive.
[Learn more](https://tailwindcss.com/docs/adding-custom-styles#adding-component-classes). ```css @layer components { .close-button { @apply bg-red-100 text-red-800 hover:bg-red-200; } .close-button--custom { @apply rounded-full border-2 border-red-300; } } ``` HeroUI follows the [BEM](https://getbem.com/) methodology to ensure component variants and states are reusable and easy to customize. ### CSS Classes The CloseButton component uses these CSS classes ([View source styles](https://github.com/heroui-inc/heroui/blob/v3/packages/styles/components/close-button.css)): #### Base Classes * `.close-button` - Base component styles #### Variant Classes * `.close-button--default` - Default variant ### Interactive States The component supports both CSS pseudo-classes and data attributes for flexibility: * **Hover**: `:hover` or `[data-hovered="true"]` * **Active/Pressed**: `:active` or `[data-pressed="true"]` * **Focus**: `:focus-visible` or `[data-focus-visible="true"]` * **Disabled**: `:disabled` or `[aria-disabled="true"]` ## API Reference ### CloseButton Props | Prop | Type | Default | Description | | ------------ | ----------------------- | --------------- | ------------------------------------------- | | `variant` | `"default"` | `"default"` | Visual variant of the button | | `children` | `ReactNode \| function` | `` | Content to display (defaults to close icon) | | `onPress` | `() => void` | - | Handler called when the button is pressed | | `isDisabled` | `boolean` | `false` | Whether the button is disabled | ### React Aria Button Props CloseButton extends all React Aria Button props. Common props include: | Prop | Type | Description | | ------------------ | -------- | --------------------------------------- | | `aria-label` | `string` | Accessible label for screen readers | | `aria-labelledby` | `string` | ID of element that labels the button | | `aria-describedby` | `string` | ID of element that describes the button | ### RenderProps When using the render prop pattern, these values are provided: | Prop | Type | Description | | ------------ | --------- | ------------------------------ | | `isHovered` | `boolean` | Whether the button is hovered | | `isPressed` | `boolean` | Whether the button is pressed | | `isFocused` | `boolean` | Whether the button is focused | | `isDisabled` | `boolean` | Whether the button is disabled |
# 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 () => (
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 (
Actions
X C U
Text Style
B I U
Text Alignment
A H D
); } ``` ### With Keyboard Shortcuts ```tsx "use client"; import {Button, Dropdown, Kbd, Label} from "@heroui/react"; export function WithKeyboardShortcuts() { return ( console.log(`Selected: ${key}`)}> N O S D ); } ``` ### 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}`)}> N O S D ); } ``` ### 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}`)}>
Create a new file
N
Open an existing file
O
Save the current file
S
Move to trash
D
); } ``` ### With Sections ```tsx "use client"; import {EllipsisVertical, Pencil, SquarePlus, TrashBin} from "@gravity-ui/icons"; import {Description, Dropdown, Header, Kbd, Label, Separator} from "@heroui/react"; export function WithSections() { return ( console.log(`Selected: ${key}`)}>
Actions
Create a new file
N
Make changes
E
Danger zone
Move to trash
D
); } ``` ### With Disabled Items ```tsx "use client"; import {Bars, Pencil, SquarePlus, TrashBin} from "@gravity-ui/icons"; import {Button, Description, Dropdown, Header, Kbd, Label, Separator} from "@heroui/react"; export function WithDisabledItems() { return ( console.log(`Selected: ${key}`)} >
Actions
Create a new file
N
Make changes
E
Danger zone
Move to trash
D
); } ``` ### With Submenus ```tsx "use client"; import {Button, Dropdown, Label} from "@heroui/react"; export function WithSubmenus() { return ( console.log(`Selected: ${key}`)}> ); } ``` ### With Custom Submenu Indicator ```tsx "use client"; import {ArrowRight} from "@gravity-ui/icons"; import {Button, Dropdown, Label} from "@heroui/react"; export function WithCustomSubmenuIndicator() { return ( console.log(`Selected: ${key}`)}> ); } ``` ### Controlled ```tsx "use client"; import type {Selection} from "@heroui/react"; import {Button, Dropdown, Label} from "@heroui/react"; import {useState} from "react"; export function Controlled() { const [selected, setSelected] = useState(new Set(["bold"])); const selectedItems = Array.from(selected); return (

Selected: {selectedItems.length > 0 ? selectedItems.join(", ") : "None"}

); } ``` ### Controlled Open State ```tsx "use client"; import {Button, Dropdown, Label} from "@heroui/react"; import {useState} from "react"; export function ControlledOpenState() { const [open, setOpen] = useState(false); return (

Dropdown is: {open ? "open" : "closed"}

); } ``` ### Custom Trigger ```tsx import {ArrowRightFromSquare, Gear, Persons} from "@gravity-ui/icons"; import {Avatar, Dropdown, Label} from "@heroui/react"; export function CustomTrigger() { return ( JD
JD

Jane Doe

jane@example.com

); } ``` ## Related Components * **Button**: Allows a user to perform an action * **Popover**: Displays content in context with a trigger * **Separator**: Visual divider between content ## Styling ### Passing Tailwind CSS classes ```tsx import { Dropdown, Button } from '@heroui/react'; function CustomDropdown() { return ( Item 1 ); } ``` ### Customizing the component classes To customize the Dropdown component classes, you can use the `@layer components` directive.
[Learn more](https://tailwindcss.com/docs/adding-custom-styles#adding-component-classes). ```css @layer components { .dropdown { @apply flex flex-col gap-1; } .dropdown__trigger { @apply outline-none; } .dropdown__popover { @apply rounded-lg border border-border bg-overlay p-2; } .dropdown__menu { @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 Dropdown component uses these CSS classes ([View source styles](https://github.com/heroui-inc/heroui/blob/v3/packages/styles/components/dropdown.css)): #### Base Classes * `.dropdown` - Base dropdown container * `.dropdown__trigger` - The button or element that triggers the dropdown * `.dropdown__popover` - The popover container * `.dropdown__menu` - The menu container inside the popover #### State Classes * `.dropdown__trigger[data-focus-visible="true"]` - Focused trigger state * `.dropdown__trigger[data-disabled="true"]` - Disabled trigger state * `.dropdown__trigger[data-pressed="true"]` - Pressed trigger state * `.dropdown__popover[data-entering]` - Entering animation state * `.dropdown__popover[data-exiting]` - Exiting animation state * `.dropdown__menu[data-selection-mode="single"]` - Single selection mode * `.dropdown__menu[data-selection-mode="multiple"]` - Multiple selection mode ### Menu Component Classes The Dropdown component uses Menu, MenuItem, and MenuSection as base components. These classes are also available for customization: #### Menu Classes * `.menu` - Base menu container ([menu.css](https://github.com/heroui-inc/heroui/blob/v3/packages/styles/components/menu.css)) * `[data-slot="separator"]` - Separator elements within the menu #### MenuItem Classes * `.menu-item` - Base menu item container ([menu-item.css](https://github.com/heroui-inc/heroui/blob/v3/packages/styles/components/menu-item.css)) * `.menu-item__indicator` - Selection indicator (checkmark or dot) * `[data-slot="menu-item-indicator--checkmark"]` - Checkmark indicator SVG * `[data-slot="menu-item-indicator--dot"]` - Dot indicator SVG * `.menu-item__indicator--submenu` - Submenu indicator (chevron) * `.menu-item--default` - Default variant styling * `.menu-item--danger` - Danger variant styling #### MenuItem State Classes * `.menu-item[data-focus-visible="true"]` - Focused item state (keyboard focus) * `.menu-item[data-focus="true"]` - Focused item state * `.menu-item[data-pressed]` - Pressed item state * `.menu-item[data-hovered]` - Hovered item state * `.menu-item[data-selected="true"]` - Selected item state * `.menu-item[data-disabled]` - Disabled item state * `.menu-item[data-has-submenu="true"]` - Item with submenu * `.menu-item[data-selection-mode="single"]` - Single selection mode * `.menu-item[data-selection-mode="multiple"]` - Multiple selection mode * `.menu-item[aria-checked="true"]` - Checked item (ARIA) * `.menu-item[aria-selected="true"]` - Selected item (ARIA) #### MenuSection Classes * `.menu-section` - Base menu section container ([menu-section.css](https://github.com/heroui-inc/heroui/blob/v3/packages/styles/components/menu-section.css)) ### Interactive States The component supports both CSS pseudo-classes and data attributes for flexibility: * **Hover**: `:hover` or `[data-hovered="true"]` on trigger and items * **Focus**: `:focus-visible` or `[data-focus-visible="true"]` on trigger and items * **Disabled**: `:disabled` or `[data-disabled="true"]` on trigger and items * **Pressed**: `:active` or `[data-pressed="true"]` on trigger and items * **Selected**: `[data-selected="true"]` or `[aria-selected="true"]` on items ## API Reference ### Dropdown Props | Prop | Type | Default | Description | | -------------- | --------------------------- | --------- | ------------------------------------------------------ | | `isOpen` | `boolean` | - | Sets the open state of the menu (controlled) | | `defaultOpen` | `boolean` | - | Sets the default open state of the menu (uncontrolled) | | `onOpenChange` | `(isOpen: boolean) => void` | - | Handler called when the open state changes | | `trigger` | `"press" \| "longPress"` | `"press"` | The type of interaction that triggers the menu | | `className` | `string` | - | Additional CSS classes | | `children` | `ReactNode` | - | Dropdown content | ### Dropdown.Trigger Props | Prop | Type | Default | Description | | ----------- | ----------------------------- | ------- | ---------------------------------- | | `className` | `string` | - | Additional CSS classes | | `children` | `ReactNode \| RenderFunction` | - | Trigger content or render function | All [Button](https://react-spectrum.adobe.com/react-aria/Button.html) props are also supported when using a Button as the trigger. ### Dropdown.Popover Props | Prop | Type | Default | Description | | ----------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | ---------- | ------------------------------------------------ | | `placement` | `"bottom" \| "bottom left" \| "bottom right" \| "bottom start" \| "bottom end" \| "top" \| "top left" \| "top right" \| "top start" \| "top end" \| "left" \| "left top" \| "left bottom" \| "start" \| "start top" \| "start bottom" \| "right" \| "right top" \| "right bottom" \| "end" \| "end top" \| "end bottom"` | `"bottom"` | Placement of the popover relative to the trigger | | `className` | `string` | - | Additional CSS classes | | `children` | `ReactNode` | - | Content children | All [Popover](https://react-spectrum.adobe.com/react-aria/Popover.html) props are also supported. ### Dropdown.Menu Props | Prop | Type | Default | Description | | --------------------- | ---------------------------------- | -------- | ----------------------------------------------- | | `selectionMode` | `"single" \| "multiple" \| "none"` | `"none"` | Whether single or multiple selection is enabled | | `selectedKeys` | `Iterable` | - | The currently selected keys (controlled) | | `defaultSelectedKeys` | `Iterable` | - | The initial selected keys (uncontrolled) | | `onSelectionChange` | `(keys: Selection) => void` | - | Handler called when the selection changes | | `disabledKeys` | `Iterable` | - | Keys of disabled items | | `onAction` | `(key: Key) => void` | - | Handler called when an item is activated | | `className` | `string` | - | Additional CSS classes | | `children` | `ReactNode` | - | Menu content | All [Menu](https://react-spectrum.adobe.com/react-aria/Menu.html#menu) props are also supported. ### Dropdown.Section Props | Prop | Type | Default | Description | | --------------------- | --------------------------- | ------- | -------------------------------------------- | | `selectionMode` | `"single" \| "multiple"` | - | Selection mode for items within this section | | `selectedKeys` | `Iterable` | - | The currently selected keys (controlled) | | `defaultSelectedKeys` | `Iterable` | - | The initial selected keys (uncontrolled) | | `onSelectionChange` | `(keys: Selection) => void` | - | Handler called when the selection changes | | `disabledKeys` | `Iterable` | - | Keys of disabled items | | `className` | `string` | - | Additional CSS classes | | `children` | `ReactNode` | - | Section content | All [MenuSection](https://react-spectrum.adobe.com/react-aria/Menu.html#menusection) props are also supported. ### Dropdown.Item Props | Prop | Type | Default | Description | | ----------- | ----------------------------- | ----------- | -------------------------------------- | | `id` | `Key` | - | Unique identifier for the item | | `textValue` | `string` | - | Text content of the item for typeahead | | `variant` | `"default" \| "danger"` | `"default"` | Visual variant of the item | | `className` | `string` | - | Additional CSS classes | | `children` | `ReactNode \| RenderFunction` | - | Item content or render function | All [MenuItem](https://react-spectrum.adobe.com/react-aria/Menu.html#menuitem) props are also supported. ### Dropdown.ItemIndicator Props | Prop | Type | Default | Description | | ----------- | ----------------------------- | ------------- | ------------------------------------------- | | `type` | `"checkmark" \| "dot"` | `"checkmark"` | Type of indicator to display | | `className` | `string` | - | Additional CSS classes | | `children` | `ReactNode \| RenderFunction` | - | Custom indicator content or render function | When using a render function, these values are provided: | Prop | Type | Description | | ----------------- | --------- | --------------------------------------------- | | `isSelected` | `boolean` | Whether the item is selected | | `isIndeterminate` | `boolean` | Whether the item is in an indeterminate state | ### Dropdown.SubmenuIndicator Props | Prop | Type | Default | Description | | ----------- | ----------- | ------- | ------------------------ | | `className` | `string` | - | Additional CSS classes | | `children` | `ReactNode` | - | Custom indicator content | ### Dropdown.SubmenuTrigger Props | Prop | Type | Default | Description | | ----------- | ----------- | ------- | ----------------------- | | `className` | `string` | - | Additional CSS classes | | `children` | `ReactNode` | - | Submenu trigger content | All [SubmenuTrigger](https://react-spectrum.adobe.com/react-aria/Menu.html#submenutrigger) props are also supported. ### RenderProps When using render functions with Dropdown.Item, these values are provided: | Prop | Type | Description | | ------------ | --------- | --------------------------------- | | `isSelected` | `boolean` | Whether the item is selected | | `isFocused` | `boolean` | Whether the item is focused | | `isDisabled` | `boolean` | Whether the item is disabled | | `isPressed` | `boolean` | Whether the item is being pressed | ## Examples ### Basic Usage ```tsx import { Dropdown, Button, Label } from '@heroui/react'; alert(`Selected: ${key}`)}> ``` ### With Sections ```tsx import { Dropdown, Button, Label, Header, Separator } from '@heroui/react'; alert(`Selected: ${key}`)}>
Actions
Danger zone
``` ### Controlled Selection ```tsx import type { Selection } from '@heroui/react'; import { Dropdown, Button, Label } from '@heroui/react'; import { useState } from 'react'; function ControlledDropdown() { const [selected, setSelected] = useState(new Set(['bold'])); return ( ); } ``` ### With Submenus ```tsx import { Dropdown, Button, Label } from '@heroui/react'; alert(`Selected: ${key}`)}> ``` ## Accessibility The Dropdown component implements the ARIA menu pattern and provides: * Full keyboard navigation support (arrow keys, home/end, typeahead) * Screen reader announcements for actions and selection changes * Proper focus management * Support for disabled states * Long press interaction support * Submenu navigation For more information, see the [React Aria Menu documentation](https://react-spectrum.adobe.com/react-aria/Menu.html#menu).
# ListBox **Category**: react **URL**: https://v3.heroui.com/docs/react/components/list-box **Source**: https://raw.githubusercontent.com/heroui-inc/heroui/refs/heads/v3/apps/docs/content/docs/react/components/(collections)/list-box.mdx > A listbox displays a list of options and allows a user to select one or more of them ## Import ```tsx import { ListBox } from '@heroui/react'; ``` ### Usage ```tsx import {Avatar, Description, Label, ListBox} from "@heroui/react"; export function Default() { return ( B
bob@heroui.com
F
fred@heroui.com
M
martha@heroui.com
); } ``` ### 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
E
Danger 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
E
Danger 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 (
B
bob@heroui.com
{({isSelected}) => (isSelected ? : null)}
F
fred@heroui.com
{({isSelected}) => (isSelected ? : null)}
M
martha@heroui.com
{({isSelected}) => (isSelected ? : null)}

Selected: {selectedItems.length > 0 ? selectedItems.join(", ") : "None"}

); } ``` ### Custom Render Function ```tsx "use client"; import {Avatar, Description, Label, ListBox} from "@heroui/react"; export function CustomRenderFunction() { return (
} selectionMode="single" > } textValue="Bob" > B
bob@heroui.com
} textValue="Fred" > F
fred@heroui.com
} textValue="Martha" > M
martha@heroui.com
); } ``` ## Related Components * **Select**: Dropdown select control * **ComboBox**: Text input with searchable dropdown list * **Avatar**: Display user profile images ## Styling ### Passing Tailwind CSS classes ```tsx import { ListBox } from '@heroui/react'; function CustomListBox() { return ( Item 1 ); } ``` ### Customizing the component classes To customize the ListBox component classes, you can use the `@layer components` directive.
[Learn more](https://tailwindcss.com/docs/adding-custom-styles#adding-component-classes). ```css @layer components { .list-box { @apply rounded-lg border border-border bg-surface p-2; } .list-box-item { @apply rounded px-2 py-1 cursor-pointer; } .list-box-item--danger { @apply text-danger; } .list-box-item__indicator { @apply text-accent; } } ``` HeroUI follows the [BEM](https://getbem.com/) methodology to ensure component variants and states are reusable and easy to customize. ### CSS Classes The ListBox component uses these CSS classes ([View source styles](https://github.com/heroui-inc/heroui/blob/v3/packages/styles/components/list-box.css)): #### Base Classes * `.list-box` - Base listbox container * `.list-box-item` - Individual listbox item * `.list-box-item__indicator` - Selection indicator icon * `.list-box-section` - Section container for grouping items #### Variant Classes * `.list-box--default` - Default variant styling * `.list-box--danger` - Danger variant styling * `.list-box-item--default` - Default item variant * `.list-box-item--danger` - Danger item variant #### State Classes * `.list-box-item[data-selected="true"]` - Selected item state * `.list-box-item[data-focus-visible="true"]` - Focused item state * `.list-box-item[data-disabled="true"]` - Disabled item state * `.list-box-item__indicator[data-visible="true"]` - Visible indicator state ### Interactive States The component supports both CSS pseudo-classes and data attributes for flexibility: * **Hover**: `:hover` or `[data-hovered="true"]` on item * **Focus**: `:focus-visible` or `[data-focus-visible="true"]` on item * **Selected**: `[data-selected="true"]` on item * **Disabled**: `:disabled` or `[data-disabled="true"]` on item ## API Reference ### ListBox Props | Prop | Type | Default | Description | | --------------------- | -------------------------------------------------------------------------- | ----------- | ---------------------------------------------------------------- | | `aria-label` | `string` | - | Accessibility label for the listbox | | `aria-labelledby` | `string` | - | ID of element that labels the listbox | | `selectionMode` | `"none" \| "single" \| "multiple"` | `"single"` | Selection behavior | | `selectedKeys` | `Selection` | - | Controlled selected keys | | `defaultSelectedKeys` | `Selection` | - | Initial selected keys | | `onSelectionChange` | `(keys: Selection) => void` | - | Handler called when selection changes | | `disabledKeys` | `Iterable` | - | Keys of disabled items | | `onAction` | `(key: Key) => void` | - | Handler called when an item is activated | | `variant` | `"default" \| "danger"` | `"default"` | Visual variant | | `className` | `string` | - | Additional CSS classes | | `children` | `ReactNode` | - | ListBox items and sections | | `render` | `DOMRenderFunction` | - | Overrides the default DOM element with a custom render function. | ### ListBox.Item Props | Prop | Type | Default | Description | | ------------ | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ----------- | ---------------------------------------------------------------- | | `id` | `Key` | - | Unique identifier for the item | | `textValue` | `string` | - | Text value for accessibility and typeahead | | `isDisabled` | `boolean` | `false` | Whether this item is disabled | | `variant` | `"default" \| "danger"` | `"default"` | Visual variant | | `className` | `string` | - | Additional CSS classes | | `children` | `ReactNode \| RenderFunction` | - | Item content or render function | | `render` | `(props: DetailedHTMLProps \| React.JSX.IntrinsicElements[keyof React.JSX.IntrinsicElements], renderProps: ListBoxItemRenderProps) => ReactElement` | - | Overrides the default DOM element with a custom render function. | ### ListBox.ItemIndicator Props | Prop | Type | Default | Description | | ----------- | ----------------------------- | ------- | ------------------------------------------- | | `className` | `string` | - | Additional CSS classes | | `children` | `ReactNode \| RenderFunction` | - | Custom indicator content or render function | ### ListBox.Section Props | Prop | Type | Default | Description | | ----------- | ----------- | ------- | ------------------------------------------ | | `className` | `string` | - | Additional CSS classes | | `children` | `ReactNode` | - | Section content including Header and Items | ### RenderProps When using render functions with ListBox.Item or ListBox.ItemIndicator, these values are provided: | Prop | Type | Description | | ------------ | --------- | --------------------------------- | | `isSelected` | `boolean` | Whether the item is selected | | `isFocused` | `boolean` | Whether the item is focused | | `isDisabled` | `boolean` | Whether the item is disabled | | `isPressed` | `boolean` | Whether the item is being pressed | ## Examples ### Basic Usage ```tsx import { ListBox, Label, Description } from '@heroui/react'; bob@heroui.com alice@heroui.com ``` ### With Sections ```tsx import { ListBox, Header, Separator } from '@heroui/react'; console.log(key)}>
Actions
New file Edit file
Danger zone
Delete
``` ### Controlled Selection ```tsx import { ListBox, Selection } from '@heroui/react'; import { useState } from 'react'; function ControlledListBox() { const [selected, setSelected] = useState(new Set(["1"])); return ( Option 1 Option 2 Option 3 ); } ``` ### Custom Indicator ```tsx import { ListBox, ListBoxItemIndicator } from '@heroui/react'; import { Icon } from '@iconify/react'; Option 1 {({isSelected}) => isSelected ? : null } ``` ## Accessibility The ListBox component implements the ARIA listbox pattern and provides: * Full keyboard navigation support * Screen reader announcements for selection changes * Proper focus management * Support for disabled states * Typeahead search functionality For more information, see the [React Aria ListBox documentation](https://react-spectrum.adobe.com/react-aria/ListBox.html). # TagGroup **Category**: react **URL**: https://v3.heroui.com/docs/react/components/tag-group **Source**: https://raw.githubusercontent.com/heroui-inc/heroui/refs/heads/v3/apps/docs/content/docs/react/components/(collections)/tag-group.mdx > A focusable list of tags with support for keyboard navigation, selection, and removal ## Import ```tsx import { TagGroup } from '@heroui/react'; ``` ### Usage ```tsx "use client"; import {PlanetEarth, Rocket, ShoppingBag, SquareArticle} from "@gravity-ui/icons"; import {Tag, TagGroup} from "@heroui/react"; export function TagGroupBasic() { return ( News Travel Gaming Shopping ); } ``` ### Anatomy ```tsx import { TagGroup, Tag, Label, Description, ErrorMessage } from '@heroui/react'; export default () => ( ) ``` ### Sizes ```tsx "use client"; import {Label, Tag, TagGroup} from "@heroui/react"; export function TagGroupSizes() { return (
News Travel Gaming News Travel Gaming News Travel Gaming
); } ``` ### Variants ```tsx "use client"; import {Label, Tag, TagGroup} from "@heroui/react"; export function TagGroupVariants() { return (
News Travel Gaming News Travel Gaming
); } ``` ### Disabled ```tsx "use client"; import {Description, Label, Tag, TagGroup} from "@heroui/react"; export function TagGroupDisabled() { return (
News Travel Gaming Some tags are disabled News Travel Gaming Tags disabled via disabledKeys prop
); } ``` ### Selection Modes ```tsx "use client"; import type {Key} from "@heroui/react"; import {Description, Label, Tag, TagGroup} from "@heroui/react"; import {useState} from "react"; export function TagGroupSelectionModes() { const [singleSelected, setSingleSelected] = useState>(new Set(["news"])); const [multipleSelected, setMultipleSelected] = useState>( new Set(["news", "travel"]), ); return (
setSingleSelected(keys)} > News Travel Gaming Shopping Choose one category setMultipleSelected(keys)} > News Travel Gaming Shopping Choose multiple categories
); } ``` ### Controlled ```tsx "use client"; import type {Key} from "@heroui/react"; import {Description, Label, Tag, TagGroup} from "@heroui/react"; import {useState} from "react"; export function TagGroupControlled() { const [selected, setSelected] = useState>(new Set(["news", "travel"])); return (
setSelected(keys)} > News Travel Gaming Shopping Selected: {Array.from(selected).length > 0 ? Array.from(selected).join(", ") : "None"}
); } ``` ### With Error Message ```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 TagGroupWithErrorMessage() { const [selected, setSelected] = useState>(new Set()); const isInvalid = useMemo(() => Array.from(selected).length === 0, [selected]); return ( setSelected(keys)} > Laundry Fitness center Parking Swimming pool Breakfast {isInvalid ? "Select at least one category" : "Selected: " + Array.from(selected).join(", ")} {!!isInvalid && <>Please select at least one category} ); } ``` ### With Prefix ```tsx "use client"; import {PlanetEarth, Rocket, ShoppingBag, SquareArticle} from "@gravity-ui/icons"; import {Avatar, Description, Label, Tag, TagGroup} from "@heroui/react"; export function TagGroupWithPrefix() { return (
News Travel Gaming Shopping Tags with icons F Fred M Michael J Jane Tags with avatars
); } ``` ### With Remove Button ```tsx "use client"; import type {Key} from "@heroui/react"; import {CircleXmarkFill} from "@gravity-ui/icons"; import {Description, EmptyState, Label, Tag, TagGroup} from "@heroui/react"; import {useState} from "react"; export function TagGroupWithRemoveButton() { type TagItem = {id: string; name: string}; const [tags, setTags] = useState([ {id: "news", name: "News"}, {id: "travel", name: "Travel"}, {id: "gaming", name: "Gaming"}, {id: "shopping", name: "Shopping"}, ]); const [frameworks, setFrameworks] = useState([ {id: "react", name: "React"}, {id: "vue", name: "Vue"}, {id: "angular", name: "Angular"}, {id: "svelte", name: "Svelte"}, ]); const onRemoveTags = (keys: Set) => { setTags(tags.filter((tag) => !keys.has(tag.id))); }; const onRemoveFrameworks = (keys: Set) => { setFrameworks(frameworks.filter((framework) => !keys.has(framework.id))); }; return (
No categories found} > {(tag) => ( {tag.name} )} Click the X to remove tags
No frameworks found} > {(tag) => ( {(renderProps) => ( <> {tag.name} {!!renderProps.allowsRemoving && ( )} )} )} Custom remove button with icon
); } ``` ### With List Data ```tsx "use client"; import type {Key} from "@heroui/react"; import {Avatar, Description, EmptyState, Label, Tag, TagGroup, useListData} from "@heroui/react"; export function TagGroupWithListData() { type User = { id: string; name: string; avatar: string; fallback: string; }; const list = useListData({ getKey: (item) => item.id, initialItems: [ { avatar: "https://heroui-assets.nyc3.cdn.digitaloceanspaces.com/avatars/blue.jpg", fallback: "F", id: "fred", name: "Fred", }, { avatar: "https://heroui-assets.nyc3.cdn.digitaloceanspaces.com/avatars/green.jpg", fallback: "M", id: "michael", name: "Michael", }, { avatar: "https://heroui-assets.nyc3.cdn.digitaloceanspaces.com/avatars/purple.jpg", fallback: "J", id: "jane", name: "Jane", }, { avatar: "https://heroui-assets.nyc3.cdn.digitaloceanspaces.com/avatars/red.jpg", fallback: "A", id: "alice", name: "Alice", }, { avatar: "https://heroui-assets.nyc3.cdn.digitaloceanspaces.com/avatars/orange.jpg", fallback: "B", id: "bob", name: "Bob", }, { avatar: "https://heroui-assets.nyc3.cdn.digitaloceanspaces.com/avatars/black.jpg", fallback: "C", id: "charlie", name: "Charlie", }, ], initialSelectedKeys: new Set(["fred", "michael"]), }); const onRemove = (keys: Set) => { list.remove(...keys); }; return (
list.setSelectedKeys(keys)} > No team members} > {(user) => ( {user.fallback} {user.name} )} Select team members for your project {list.selectedKeys !== "all" && Array.from(list.selectedKeys).length > 0 && (

Selected:

{Array.from(list.selectedKeys).map((key) => { const user = list.getItem(key); if (!user) return null; return (
{user.fallback} {user.name}
); })}
)}
); } ``` ### Custom Render Function ```tsx "use client"; import {PlanetEarth, Rocket, ShoppingBag, SquareArticle} from "@gravity-ui/icons"; import {Tag, TagGroup} from "@heroui/react"; export function CustomRenderFunction() { return (
} selectionMode="single" > News Travel Gaming Shopping ); } ``` ## Related Components * **Label**: Accessible label for form controls * **Description**: Helper text for form fields * **ErrorMessage**: Displays validation error messages for components with validation support ## Styling ### Passing Tailwind CSS classes ```tsx import { TagGroup, Tag, Label } from '@heroui/react'; function CustomTagGroup() { return ( Custom Styled ); } ``` ### Customizing the component classes To customize the TagGroup component classes, you can use the `@layer components` directive.
[Learn more](https://tailwindcss.com/docs/adding-custom-styles#adding-component-classes). ```css @layer components { .tag-group { @apply flex flex-col gap-2; } .tag-group__list { @apply flex flex-wrap gap-2; } .tag { @apply rounded-full px-3 py-1; } .tag__remove-button { @apply ml-1; } } ``` HeroUI follows the [BEM](https://getbem.com/) methodology to ensure component variants and states are reusable and easy to customize. ### CSS Classes The TagGroup component uses these CSS classes ([View source styles](https://github.com/heroui-inc/heroui/blob/v3/packages/styles/components/tag-group.css) and [tag.css](https://github.com/heroui-inc/heroui/blob/v3/packages/styles/components/tag.css)): #### Base Classes * `.tag-group` - Base tag group container * `.tag-group__list` - Container for the list of tags * `.tag` - Base tag styles * `.tag__remove-button` - Remove button trigger #### Slot Classes * `.tag-group [slot="description"]` - Description slot styles * `.tag-group [slot="errorMessage"]` - ErrorMessage slot styles #### Size Classes * `.tag--sm` - Small size tag * `.tag--md` - Medium size tag (default) * `.tag--lg` - Large size tag #### Variant Classes * `.tag--default` - Default variant * `.tag--surface` - Surface variant with surface background #### State Classes * `.tag[data-selected="true"]` - Selected tag state * `.tag[data-disabled="true"]` - Disabled tag state * `.tag[data-hovered="true"]` - Hovered tag state * `.tag[data-pressed="true"]` - Pressed tag state * `.tag[data-focus-visible="true"]` - Focused tag state (keyboard focus) ### Interactive States The component supports both CSS pseudo-classes and data attributes for flexibility: * **Hover**: `:hover` or `[data-hovered="true"]` on tag * **Focus**: `:focus-visible` or `[data-focus-visible="true"]` on tag * **Pressed**: `:active` or `[data-pressed="true"]` on tag * **Selected**: `[data-selected="true"]` or `[aria-selected="true"]` on tag * **Disabled**: `:disabled` or `[data-disabled="true"]` on tag ## API Reference ### TagGroup Props | Prop | Type | Default | Description | | --------------------- | ----------------------------------------------------------------- | ----------- | ---------------------------------------------------------------- | | `selectionMode` | `"none" \| "single" \| "multiple"` | `"none"` | The type of selection that is allowed | | `selectedKeys` | `Selection` | - | The currently selected keys (controlled) | | `defaultSelectedKeys` | `Selection` | - | The initial selected keys (uncontrolled) | | `onSelectionChange` | `(keys: Selection) => void` | - | Handler called when the selection changes | | `disabledKeys` | `Iterable` | - | Keys of disabled tags | | `isDisabled` | `boolean` | - | Whether the tag group is disabled | | `onRemove` | `(keys: Set) => void` | - | Handler called when tags are removed | | `size` | `"sm" \| "md" \| "lg"` | `"md"` | Size of the tags in the group | | `variant` | `"default" \| "surface"` | `"default"` | Visual variant of the tags | | `className` | `string` | - | Additional CSS classes | | `children` | `ReactNode \| RenderFunction` | - | TagGroup content or render function | | `render` | `DOMRenderFunction` | - | Overrides the default DOM element with a custom render function. | ### TagGroup.List Props | Prop | Type | Default | Description | | ------------------ | -------------------------------------------------------------------------- | ------- | ---------------------------------------------------------------- | | `items` | `Iterable` | - | The items to display in the tag list | | `renderEmptyState` | `() => ReactNode` | - | Function to render when the list is empty | | `className` | `string` | - | Additional CSS classes | | `children` | `ReactNode \| RenderFunction` | - | TagList content or render function | | `render` | `DOMRenderFunction` | - | Overrides the default DOM element with a custom render function. | ### Tag Props | Prop | Type | Default | Description | | ------------ | ---------------------------------------------------------------------- | ------- | -------------------------------------------------------------------- | | `id` | `Key` | - | The unique identifier for the tag | | `textValue` | `string` | - | A string representation of the tag's content, used for accessibility | | `isDisabled` | `boolean` | - | Whether the tag is disabled | | `className` | `string` | - | Additional CSS classes | | `children` | `ReactNode \| RenderFunction` | - | Tag content or render function | | `render` | `DOMRenderFunction` | - | Overrides the default DOM element with a custom render function. | **Note**: `size`, `variant` are inherited from the parent `TagGroup` component and cannot be set directly on individual `Tag` components. ### Tag.RemoveButton Props | Prop | Type | Default | Description | | ----------- | ----------- | ------- | ----------------------------------------------------- | | `className` | `string` | - | Additional CSS classes | | `children` | `ReactNode` | - | Custom remove button content (defaults to close icon) | **Note**: The `Tag.RemoveButton` component supports customization similar to `SearchField.ClearButton`. When `onRemove` is provided to `TagGroup`: * **Auto-rendering**: If no custom `Tag.RemoveButton` is included in the `Tag` children, a default remove button is automatically rendered. * **Custom button**: If a custom `Tag.RemoveButton` is provided as a child of `Tag`, it will be used instead of the auto-rendered button. * **Custom icon**: You can pass custom content (like icons) to `Tag.RemoveButton` children to customize the appearance. **Example - Auto-rendered (default)**: ```tsx News {/* Remove button is automatically rendered */} ``` **Example - Custom RemoveButton with icon**: ```tsx News ``` **Example - Custom RemoveButton in render props**: ```tsx {(renderProps) => ( <> News {!!renderProps.allowsRemoving && ( )} )} ``` ### RenderProps When using render functions with TagGroup.List, these values are provided: | Prop | Type | Description | | ---------------- | --------- | ---------------------------------- | | `isSelected` | `boolean` | Whether the tag is selected | | `isDisabled` | `boolean` | Whether the tag is disabled | | `isHovered` | `boolean` | Whether the tag is hovered | | `isPressed` | `boolean` | Whether the tag is pressed | | `isFocused` | `boolean` | Whether the tag is focused | | `isFocusVisible` | `boolean` | Whether the tag has keyboard focus | # ColorArea **Category**: react **URL**: https://v3.heroui.com/docs/react/components/color-area **Source**: https://raw.githubusercontent.com/heroui-inc/heroui/refs/heads/v3/apps/docs/content/docs/react/components/(colors)/color-area.mdx > A 2D color picker that allows users to select colors from a gradient area ## Import ```tsx import { ColorArea } from '@heroui/react'; ``` ### Usage ```tsx import {ColorArea} from "@heroui/react"; export function ColorAreaBasic() { return ( ); } ``` ### Anatomy ```tsx import { ColorArea } from '@heroui/react'; export default () => ( ); ``` ### With Dots ```tsx import {ColorArea} from "@heroui/react"; export function ColorAreaWithDots() { return ( ); } ``` ### Controlled ```tsx "use client"; import type {Color} from "@heroui/react"; import {ColorArea, ColorSwatch, parseColor} from "@heroui/react"; import {useState} from "react"; export function ColorAreaControlled() { const [color, setColor] = useState(parseColor("#9B80FF")); return (

Current color:{" "} {color ? color.toString("hex") : "(empty)"}

); } ``` ### Color Space & Channels Use `colorSpace` to set the color space (RGB, HSL, HSB) and `xChannel`/`yChannel` props to customize which color channels are displayed on each axis. ```tsx "use client"; import type {ColorSpace, Key} from "@heroui/react"; import {ColorArea, Label, ListBox, Select, parseColor} from "@heroui/react"; import {useState} from "react"; type ColorChannel = "hue" | "saturation" | "brightness" | "lightness" | "red" | "green" | "blue"; interface ChannelOption { id: ColorChannel; name: string; } const colorSpaces: Array<{id: ColorSpace; name: string}> = [ {id: "rgb", name: "RGB"}, {id: "hsl", name: "HSL"}, {id: "hsb", name: "HSB"}, ]; const channelsBySpace: Record = { hsb: [ {id: "hue", name: "Hue"}, {id: "saturation", name: "Saturation"}, {id: "brightness", name: "Brightness"}, ], hsl: [ {id: "hue", name: "Hue"}, {id: "saturation", name: "Saturation"}, {id: "lightness", name: "Lightness"}, ], rgb: [ {id: "red", name: "Red"}, {id: "green", name: "Green"}, {id: "blue", name: "Blue"}, ], }; export function ColorAreaSpaceAndChannels() { const [colorSpace, setColorSpace] = useState("hsb"); const [color, setColor] = useState(() => parseColor("hsb(219, 58%, 93%)")); const channels = channelsBySpace[colorSpace]; const defaultX = colorSpace === "rgb" ? "blue" : "saturation"; const defaultY = colorSpace === "rgb" ? "green" : colorSpace === "hsl" ? "lightness" : "brightness"; const [xChannel, setXChannel] = useState(defaultX); const [yChannel, setYChannel] = useState(defaultY); const handleColorSpaceChange = (newSpace: Key | null) => { if (!newSpace) return; const space = newSpace as ColorSpace; setColorSpace(space); // Reset channels to appropriate defaults for the new color space if (space === "rgb") { setXChannel("blue"); setYChannel("green"); } else if (space === "hsl") { setXChannel("saturation"); setYChannel("lightness"); } else { setXChannel("saturation"); setYChannel("brightness"); } }; // Filter out the other channel from options (can't have same channel on both axes) const xChannelOptions = channels.filter((c) => c.id !== yChannel); const yChannelOptions = channels.filter((c) => c.id !== xChannel); return (
{/* Controls */}
{/* Color Space Select */} {/* X Channel Select */} {/* Y Channel Select */}
{/* Color Area */} {/* Color Value Display */}
{color.toString(colorSpace)}
); } ``` ### Disabled ```tsx import {ColorArea} from "@heroui/react"; export function ColorAreaDisabled() { return ( ); } ``` ### Custom Render Function ```tsx "use client"; import {ColorArea} from "@heroui/react"; export function CustomRenderFunction() { return (
} >
} /> ); } ``` ## Related Components * **ColorSwatch**: Visual preview of a color value * **ColorSwatchPicker**: Color swatch selection from a list of colors * **ColorField**: Input for entering color values with hex format ## Styling ### Passing Tailwind CSS classes ```tsx import { ColorArea } from '@heroui/react'; function CustomColorArea() { return ( ); } ``` ### Customizing the component classes To customize the ColorArea component classes, you can use the `@layer components` directive.
[Learn more](https://tailwindcss.com/docs/adding-custom-styles#adding-component-classes). ```css @layer components { .color-area { @apply rounded-3xl; } .color-area__thumb { @apply size-5 border-4; } } ``` HeroUI follows the [BEM](https://getbem.com/) methodology to ensure component variants and states are reusable and easy to customize. ### CSS Classes The ColorArea component uses these CSS classes ([View source styles](https://github.com/heroui-inc/heroui/blob/v3/packages/styles/components/color-area.css)): #### Base Classes * `.color-area` - Base styles with gradient background and inner shadow * `.color-area--show-dots` - Adds dot grid overlay for precision picking #### Element Classes * `.color-area__thumb` - Draggable thumb indicator ### Interactive States The component supports both CSS pseudo-classes and data attributes for flexibility: * **Disabled**: `[data-disabled="true"]` * **Focus**: `[data-focus-visible="true"]` * **Dragging**: `[data-dragging="true"]` (thumb only) ## API Reference ### ColorArea Props Inherits from [React Aria ColorArea](https://react-spectrum.adobe.com/react-aria/ColorArea.html). | Prop | Type | Default | Description | | -------------- | ---------------------------------------------------------------------------- | -------------- | ---------------------------------------------------------------- | | `value` | `string \| Color` | - | The current color value (controlled) | | `defaultValue` | `string \| Color` | - | The default color value (uncontrolled) | | `onChange` | `(color: Color) => void` | - | Handler called when the color changes while dragging | | `onChangeEnd` | `(color: Color) => void` | - | Handler called when the user stops dragging | | `xChannel` | `ColorChannel` | `"saturation"` | Color channel for the horizontal axis | | `yChannel` | `ColorChannel` | `"brightness"` | Color channel for the vertical axis | | `colorSpace` | `ColorSpace` | - | The color space for the channels | | `isDisabled` | `boolean` | `false` | Whether the color area is disabled | | `showDots` | `boolean` | `false` | Whether to show the dot grid overlay | | `className` | `string` | - | Additional CSS classes | | `render` | `DOMRenderFunction` | - | Overrides the default DOM element with a custom render function. | ### ColorArea.Thumb Props | Prop | Type | Default | Description | | ----------- | ----------------------------------------------------------------------------- | ------- | ---------------------------------------------------------------- | | `className` | `string` | - | Additional CSS classes | | `style` | `CSSProperties \| ((renderProps) => CSSProperties)` | - | Inline styles or render props function | | `render` | `DOMRenderFunction` | - | Overrides the default DOM element with a custom render function. | # ColorField **Category**: react **URL**: https://v3.heroui.com/docs/react/components/color-field **Source**: https://raw.githubusercontent.com/heroui-inc/heroui/refs/heads/v3/apps/docs/content/docs/react/components/(colors)/color-field.mdx > Color input field with labels, descriptions, and validation built on React Aria ColorField ## Import ```tsx import { ColorField, parseColor } from '@heroui/react'; ``` ### Usage ```tsx "use client"; import type {Color} from "@heroui/react"; import {ColorField, ColorSwatch, Label, parseColor} from "@heroui/react"; import {useState} from "react"; export function Basic() { const [color, setColor] = useState(parseColor("#0485F7")); return ( ); } ``` ### Anatomy ```tsx import {ColorField, Label, ColorSwatch, Description, FieldError, parseColor} from '@heroui/react'; export default () => ( ) ``` > **ColorField** combines label, color input, description, and error into a single accessible component. ### With Description ```tsx import {ColorField, Description, Label} from "@heroui/react"; export function WithDescription() { return (
Enter your brand's primary color Used for highlights and CTAs
); } ``` ### Required Field ```tsx import {ColorField, Description, Label} from "@heroui/react"; export function Required() { return (
Required field
); } ``` ### Validation Use `isInvalid` together with `FieldError` to surface validation messages. ```tsx import {ColorField, FieldError, Label} from "@heroui/react"; export function Invalid() { return (
Please enter a valid hex color Invalid color format. Use hex (e.g., #FF5733)
); } ``` ### Channel Editing ColorField supports editing individual color channels (hue, saturation, lightness, red, green, blue, alpha) by setting the `colorSpace` and `channel` props. ```tsx "use client"; import type {Color} from "@heroui/react"; import {ColorField, ColorSwatch, Label, parseColor} from "@heroui/react"; import {useState} from "react"; export function ChannelEditing() { const [color, setColor] = useState(parseColor("#7F007F")); return (

Edit individual HSL channels:

% %
Current: {color ? color.toString("hex") : "(empty)"}
); } ``` ### Controlled Control the value to synchronize with other components or state management. ```tsx "use client"; import type {Color} from "@heroui/react"; import {Button, ColorField, ColorSwatch, Description, Label, parseColor} from "@heroui/react"; import {useState} from "react"; export function Controlled() { const [value, setValue] = useState(parseColor("#0485F7")); return (
Current value: {value ? value.toString("hex") : "(empty)"}
); } ``` ### Disabled State ```tsx "use client"; import {ColorField, Description, Label} from "@heroui/react"; export function Disabled() { return (
This color field is disabled This color field is disabled
); } ``` ### Full Width ```tsx import {ColorField, Label} from "@heroui/react"; export function FullWidth() { return (
); } ``` ### Variants The ColorField.Group component supports two visual variants: * **`primary`** (default) - Standard styling with shadow, suitable for most use cases * **`secondary`** - Lower emphasis variant without shadow, suitable for use in Surface components ```tsx import {ColorField, Label} from "@heroui/react"; export function Variants() { return (
); } ``` ### On Surface When used inside a [Surface](/docs/components/surface) component, use `variant="secondary"` on ColorField.Group to apply the lower emphasis variant suitable for surface backgrounds. ```tsx import {ColorField, Description, Label, Surface} from "@heroui/react"; export function OnSurface() { return ( Select your theme color ); } ``` ### Form Example Complete form example with validation and submission handling. ```tsx "use client"; import type {Color} from "@heroui/react"; import {Button, ColorField, ColorSwatch, Description, Form, Label} from "@heroui/react"; import {useState} from "react"; export function FormExample() { const [value, setValue] = useState(null); const [isSubmitting, setIsSubmitting] = useState(false); const handleSubmit = (e: React.FormEvent) => { e.preventDefault(); if (!value) { return; } setIsSubmitting(true); // Simulate API call setTimeout(() => { console.log("Color submitted:", {color: value.toString("hex")}); setValue(null); setIsSubmitting(false); }, 1500); }; return (
Choose your brand's primary color
); } ``` ### Custom Render Function ```tsx "use client"; import type {Color} from "@heroui/react"; import {ColorField, ColorSwatch, Label, parseColor} from "@heroui/react"; import {useState} from "react"; export function CustomRenderFunction() { const [color, setColor] = useState(parseColor("#0485F7")); return (
} value={color} onChange={setColor} >
}> ); } ``` ## Related Components * **ColorSwatch**: Visual preview of a color value * **ColorSwatchPicker**: Color swatch selection from a list of colors * **ColorPicker**: Composable color picker with popover ## Styling ### Passing Tailwind CSS classes ```tsx import {ColorField, Label, ColorSwatch, Description} from '@heroui/react'; function CustomColorField() { return ( Select your brand's primary color. ); } ``` ### Customizing the component classes ColorField has minimal default styling. Override the `.color-field` class to customize the container styling. ```css @layer components { .color-field { @apply flex flex-col gap-1; &[data-invalid="true"], &[aria-invalid="true"] { [data-slot="description"] { @apply hidden; } } [data-slot="label"] { @apply w-fit; } [data-slot="description"] { @apply px-1; } } } ``` ### CSS Classes * `.color-field` – Root container with minimal styling (`flex flex-col gap-1`) > **Note:** Child components ([Label](/docs/components/label), [Description](/docs/components/description), [FieldError](/docs/components/field-error)) have their own CSS classes and styling. See their respective documentation for customization options. ColorField.Group styling is documented below in the API Reference section. ### Interactive States ColorField automatically manages these data attributes based on its state: * **Invalid**: `[data-invalid="true"]` or `[aria-invalid="true"]` - Automatically hides the description slot when invalid * **Required**: `[data-required="true"]` - Applied when `isRequired` is true * **Disabled**: `[data-disabled="true"]` - Applied when `isDisabled` is true * **Focus Within**: `[data-focus-within="true"]` - Applied when any child input is focused ## API Reference ### ColorField Props ColorField inherits all props from React Aria's [ColorField](https://react-aria.adobe.com/ColorField.md) component. #### Base Props | Prop | Type | Default | Description | | ----------- | ------------------------------------------------------------------------------- | ------- | -------------------------------------------------------------------- | | `children` | `React.ReactNode \| (values: ColorFieldRenderProps) => React.ReactNode` | - | Child components (Label, ColorField.Group, etc.) or render function. | | `className` | `string \| (values: ColorFieldRenderProps) => string` | - | CSS classes for styling, supports render props. | | `style` | `React.CSSProperties \| (values: ColorFieldRenderProps) => React.CSSProperties` | - | Inline styles, supports render props. | | `fullWidth` | `boolean` | `false` | Whether the color field should take full width of its container | | `id` | `string` | - | The element's unique identifier. | | `render` | `DOMRenderFunction` | - | Overrides the default DOM element with a custom render function. | #### Value Props | Prop | Type | Default | Description | | -------------- | -------------------------------- | ------- | -------------------------------------- | | `value` | `Color \| null` | - | Current value (controlled). | | `defaultValue` | `Color \| null` | - | Default value (uncontrolled). | | `onChange` | `(color: Color \| null) => void` | - | Handler called when the value changes. | #### Channel Props | Prop | Type | Default | Description | | ------------ | -------------- | ------- | ---------------------------------------------------------------------------- | | `colorSpace` | `ColorSpace` | - | The color space that the color field operates in when `channel` is provided. | | `channel` | `ColorChannel` | - | The color channel to edit. If not provided, edits hex value. | #### Validation Props | Prop | Type | Default | Description | | -------------------- | ---------------------------------------------------------------- | ---------- | -------------------------------------------------------------- | | `isRequired` | `boolean` | `false` | Whether user input is required before form submission. | | `isInvalid` | `boolean` | - | Whether the value is invalid. | | `validate` | `(value: Color) => ValidationError \| true \| null \| undefined` | - | Custom validation function. | | `validationBehavior` | `'native' \| 'aria'` | `'native'` | Whether to use native HTML form validation or ARIA attributes. | #### State Props | Prop | Type | Default | Description | | ----------------- | --------- | ------- | -------------------------------------------------- | | `isDisabled` | `boolean` | - | Whether the input is disabled. | | `isReadOnly` | `boolean` | - | Whether the input can be selected but not changed. | | `isWheelDisabled` | `boolean` | - | Whether to disable changing the value with scroll. | #### Form Props | Prop | Type | Default | Description | | ----------- | --------- | ------- | ---------------------------------------------------- | | `name` | `string` | - | Name of the input element, for HTML form submission. | | `autoFocus` | `boolean` | - | Whether the element should receive focus on render. | #### Accessibility Props | Prop | Type | Default | Description | | ------------------ | -------- | ------- | ----------------------------------------------------- | | `aria-label` | `string` | - | Accessibility label when no visible label is present. | | `aria-labelledby` | `string` | - | ID of elements that label this field. | | `aria-describedby` | `string` | - | ID of elements that describe this field. | | `aria-details` | `string` | - | ID of elements with additional details. | ### Composition Components ColorField works with these separate components that should be imported and used directly: * **Label** - Field label component from `@heroui/react` * **ColorField.Group** - Color input group component (documented below) * **ColorField.Input** - Input element within ColorField.Group * **ColorField.Prefix** / **ColorField.Suffix** - Prefix and suffix slots for the input group * **ColorSwatch** - Color preview component from `@heroui/react` * **Description** - Helper text component from `@heroui/react` * **FieldError** - Validation error message from `@heroui/react` Each of these components has its own props API. Use them directly within ColorField for composition: ```tsx import {ColorField, Label, ColorSwatch, Description, FieldError, parseColor} from '@heroui/react'; Select your brand's primary color. Please enter a valid color. ``` ### Color Types ColorField uses `Color` objects from React Aria Components: ```tsx import {parseColor} from '@heroui/react'; // Parse from hex string const color = parseColor('#3B82F6'); // Get hex string from color const hex = color.toString('hex'); // "#3b82f6" // Get RGB values const rgb = color.toString('rgb'); // "rgb(59, 130, 246)" // Use in ColorField {/* ... */} ``` ### ColorFieldRenderProps When using render props with `className`, `style`, or `children`, these values are available: | Prop | Type | Description | | ---------------- | --------- | ----------------------------------------------- | | `isDisabled` | `boolean` | Whether the field is disabled. | | `isInvalid` | `boolean` | Whether the field is currently invalid. | | `isReadOnly` | `boolean` | Whether the field is read-only. | | `isRequired` | `boolean` | Whether the field is required. | | `isFocused` | `boolean` | Whether the field is currently focused. | | `isFocusWithin` | `boolean` | Whether any child element is focused. | | `isFocusVisible` | `boolean` | Whether focus is visible (keyboard navigation). | ### ColorField.Group Props ColorField.Group accepts all props from React Aria's `Group` component plus the following: | Prop | Type | Default | Description | | ----------- | ------------------------------------------------------------------------ | ----------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------ | | `className` | `string` | - | Tailwind classes merged with the component styles. | | `fullWidth` | `boolean` | `false` | Whether the color input group should take full width of its container | | `variant` | `"primary" \| "secondary"` | `"primary"` | Visual variant of the component. `primary` is the default style with shadow. `secondary` is a lower emphasis variant without shadow, suitable for use in surfaces. | | `render` | `DOMRenderFunction` | - | Overrides the default DOM element with a custom render function. | ### ColorField.Input Props ColorField.Input accepts all props from React Aria's `Input` component plus the following: | Prop | Type | Default | Description | | ------------- | -------- | ------- | -------------------------------------------------- | | `className` | `string` | - | Tailwind classes merged with the component styles. | | `placeholder` | `string` | - | Placeholder text shown when empty. | ### ColorField.Prefix Props ColorField.Prefix accepts standard HTML `div` attributes: | Prop | Type | Default | Description | | ----------- | ----------- | ------- | -------------------------------------------------- | | `className` | `string` | - | Tailwind classes merged with the component styles. | | `children` | `ReactNode` | - | Content to display in the prefix slot. | ### ColorField.Suffix Props ColorField.Suffix accepts standard HTML `div` attributes: | Prop | Type | Default | Description | | ----------- | ----------- | ------- | -------------------------------------------------- | | `className` | `string` | - | Tailwind classes merged with the component styles. | | `children` | `ReactNode` | - | Content to display in the suffix slot. | ## ColorField.Group Styling ### Customizing the component classes The base classes power every instance. Override them once with `@layer components`. ```css @layer components { .color-input-group { @apply inline-flex h-9 items-center overflow-hidden rounded-field border bg-field text-sm text-field-foreground shadow-field outline-none; &:hover, &[data-hovered="true"] { @apply bg-field-hover; } &[data-focus-within="true"], &:focus-within { @apply status-focused-field; } &[data-invalid="true"] { @apply status-invalid-field; } &[data-disabled="true"], &[aria-disabled="true"] { @apply status-disabled; } } .color-input-group__input { @apply flex flex-1 items-center rounded-none border-0 bg-transparent px-3 py-2 shadow-none outline-none; } .color-input-group__prefix, .color-input-group__suffix { @apply shrink-0 text-field-placeholder flex items-center; } } ``` ### ColorField.Group CSS Classes * `.color-input-group` – Root container styling * `.color-input-group__input` – Input wrapper styling * `.color-input-group__prefix` – Prefix element styling * `.color-input-group__suffix` – Suffix element styling ### ColorField.Group Interactive States * **Hover**: `:hover` or `[data-hovered="true"]` * **Focus Within**: `[data-focus-within="true"]` or `:focus-within` * **Invalid**: `[data-invalid="true"]` (also syncs with `aria-invalid`) * **Disabled**: `[data-disabled="true"]` or `[aria-disabled="true"]` # ColorPicker **Category**: react **URL**: https://v3.heroui.com/docs/react/components/color-picker **Source**: https://raw.githubusercontent.com/heroui-inc/heroui/refs/heads/v3/apps/docs/content/docs/react/components/(colors)/color-picker.mdx > A composable color picker that synchronizes color value between multiple color components ## Import ```tsx import { ColorPicker, ColorArea, ColorSlider, ColorSwatch, ColorField, ColorSwatchPicker, } from '@heroui/react'; ``` ### Usage ```tsx import {ColorArea, ColorPicker, ColorSlider, ColorSwatch, Label} from "@heroui/react"; export function Basic() { return ( ); } ``` ### Anatomy The ColorPicker is a composable component that combines multiple color components: ```tsx import { ColorPicker, ColorArea, ColorSlider, ColorSwatch, Label } from '@heroui/react'; export default () => ( ); ``` ### Controlled ```tsx "use client"; import { Button, ColorArea, ColorField, ColorPicker, ColorSlider, ColorSwatch, ColorSwatchPicker, Label, parseColor, } from "@heroui/react"; import {Icon} from "@iconify/react"; import {useState} from "react"; export function Controlled() { const [color, setColor] = useState(parseColor("#325578")); const colorPresets = [ "#ef4444", "#f97316", "#eab308", "#22c55e", "#06b6d4", "#3b82f6", "#8b5cf6", "#ec4899", "#f43f5e", ]; const shuffleColor = () => { const randomHue = Math.floor(Math.random() * 360); const randomSaturation = 50 + Math.floor(Math.random() * 50); // 50-100% const randomLightness = 40 + Math.floor(Math.random() * 30); // 40-70% setColor(parseColor(`hsl(${randomHue}, ${randomSaturation}%, ${randomLightness}%)`)); }; return (
{colorPresets.map((preset) => ( ))}

Selected: {color.toString("hex")}

); } ``` ### With Swatches ```tsx import { ColorArea, ColorPicker, ColorSlider, ColorSwatch, ColorSwatchPicker, Label, } from "@heroui/react"; export function WithSwatches() { const presets = [ "#ef4444", "#f97316", "#eab308", "#22c55e", "#06b6d4", "#3b82f6", "#8b5cf6", "#ec4899", "#f43f5e", ]; return ( {presets.map((preset) => ( ))} ); } ``` ### With Fields Use `ColorField` to allow users to edit individual color channel values with a `Select` to switch between color spaces. ```tsx "use client"; import type {ColorChannel, ColorSpace} from "@heroui/react"; import { ColorArea, ColorField, ColorPicker, ColorSlider, ColorSwatch, Label, ListBox, Select, } from "@heroui/react"; import {useState} from "react"; export function WithFields() { const [colorSpace, setColorSpace] = useState("hsl"); const colorChannelsByColorSpace: Record = { hsb: ["hue", "saturation", "brightness"], hsl: ["hue", "saturation", "lightness"], rgb: ["red", "green", "blue"], }; return (
{colorChannelsByColorSpace[colorSpace].map((channel) => ( ))}
); } ``` ### With Sliders Use multiple `ColorSlider` components to adjust each channel of a color value. ```tsx "use client"; import type {ColorChannel, ColorSpace} from "@heroui/react"; import {ColorPicker, ColorSlider, ColorSwatch, Label, ListBox, Select} from "@heroui/react"; import {useState} from "react"; export function WithSliders() { const [colorSpace, setColorSpace] = useState("hsl"); const colorChannelsByColorSpace: Record = { hsb: ["hue", "saturation", "brightness", "alpha"], hsl: ["hue", "saturation", "lightness", "alpha"], rgb: ["red", "green", "blue", "alpha"], }; return (
{colorChannelsByColorSpace[colorSpace].map((channel: ColorChannel) => ( // @ts-expect-error - TypeScript can't correlate dynamic colorSpace with channel type ))}
); } ``` ## Related Components * **ColorArea**: 2D color picker for selecting colors from a gradient area * **ColorSlider**: Slider for adjusting individual color channel values * **ColorSwatch**: Visual preview of a color value ## Styling ### Passing Tailwind CSS classes ```tsx import { ColorPicker, ColorArea, ColorSlider, ColorSwatch, Label } from '@heroui/react'; function CustomColorPicker() { return ( ); } ``` ### Customizing the component classes To customize the ColorPicker component classes, you can use the `@layer components` directive.
[Learn more](https://tailwindcss.com/docs/adding-custom-styles#adding-component-classes). ```css @layer components { .color-picker { @apply inline-flex; } .color-picker__trigger { @apply inline-flex items-center gap-4 rounded-lg; } .color-picker__popover { @apply p-4 rounded-xl; } } ``` HeroUI follows the [BEM](https://getbem.com/) methodology to ensure component variants and states are reusable and easy to customize. ### CSS Classes The ColorPicker component uses these CSS classes ([View source styles](https://github.com/heroui-inc/heroui/blob/v3/packages/styles/components/color-picker.css)): #### Base Classes * `.color-picker` - Base container * `.color-picker__trigger` - Trigger button * `.color-picker__popover` - Popover container ### Interactive States The component supports both CSS pseudo-classes and data attributes for flexibility: * **Focus**: `:focus-visible` or `[data-focus-visible="true"]` * **Disabled**: `:disabled` or `[data-disabled="true"]` ## API Reference ### ColorPicker Props Inherits from [React Aria ColorPicker](https://react-spectrum.adobe.com/react-aria/ColorPicker.html). | Prop | Type | Default | Description | | -------------- | ------------------------ | ------- | ---------------------------------------------------- | | `value` | `string \| Color` | - | The current color value (controlled) | | `defaultValue` | `string \| Color` | - | The default color value (uncontrolled) | | `onChange` | `(color: Color) => void` | - | Handler called when the color changes | | `children` | `React.ReactNode` | - | Content of the color picker (Trigger, Popover, etc.) | | `className` | `string` | - | Additional CSS classes | ### ColorPicker.Trigger Props | Prop | Type | Default | Description | | ----------- | ------------------------------------------------------- | ------- | ------------------------------ | | `children` | `React.ReactNode \| ((renderProps) => React.ReactNode)` | - | Trigger content or render prop | | `className` | `string` | - | Additional CSS classes | ### ColorPicker.Popover Props | Prop | Type | Default | Description | | ----------- | ----------------- | --------------- | ------------------------ | | `placement` | `Placement` | `"bottom left"` | Placement of the popover | | `children` | `React.ReactNode` | - | Popover content | | `className` | `string` | - | Additional CSS classes | ### Related Types #### Color Represents a color value. See [React Aria Color](https://react-spectrum.adobe.com/react-aria/ColorPicker.html#color) for full API. | Method | Description | | ---------------------------------- | ---------------------------------------------------------------------------- | | `toString(format)` | Converts the color to a string in the given format (hex, rgb, hsl, hsb, css) | | `toFormat(format)` | Converts the color to the given format and returns a new Color object | | `getChannelValue(channel)` | Returns the numeric value for a given channel | | `withChannelValue(channel, value)` | Sets the numeric value for a channel and returns a new Color | #### parseColor ```tsx import { parseColor } from 'react-aria-components'; // Parse from string const color = parseColor('#ff0000'); const hslColor = parseColor('hsl(0, 100%, 50%)'); ```
# ColorSlider **Category**: react **URL**: https://v3.heroui.com/docs/react/components/color-slider **Source**: https://raw.githubusercontent.com/heroui-inc/heroui/refs/heads/v3/apps/docs/content/docs/react/components/(colors)/color-slider.mdx > A color slider allows users to adjust an individual channel of a color value ## Import ```tsx import { ColorSlider, Label } from '@heroui/react'; ``` ### Usage ```tsx import {ColorSlider, Label} from "@heroui/react"; export function Basic() { return ( ); } ``` ### Anatomy Import the ColorSlider component and access all parts using dot notation. ```tsx import { ColorSlider, Label } from '@heroui/react'; export default () => ( ) ``` ### Vertical ```tsx import {ColorSlider} from "@heroui/react"; export function Vertical() { return (
); } ``` ### Disabled ```tsx import {ColorSlider, Label} from "@heroui/react"; export function Disabled() { return ( ); } ``` ### Controlled ```tsx "use client"; import {ColorSlider, ColorSwatch, Label} from "@heroui/react"; import {useState} from "react"; import {parseColor} from "react-aria-components"; export function Controlled() { const [color, setColor] = useState(parseColor("hsl(200, 100%, 50%)")); return (

Current color: {color.toString("hsl")}

); } ``` ### HSL Channels Use multiple ColorSliders to control different channels of a color value. The sliders can share the same color value to create a complete color picker. ```tsx "use client"; import {ColorSlider, ColorSwatch, Label} from "@heroui/react"; import {useState} from "react"; import {parseColor} from "react-aria-components"; export function Channels() { const [color, setColor] = useState(parseColor("hsl(0, 100%, 50%)")); return (

Current color: {color.toString("hsl")}

); } ``` ### Alpha Channel The alpha channel slider shows a transparency checkerboard pattern to help visualize the transparency level. ```tsx import {ColorSlider, Label} from "@heroui/react"; export function AlphaChannel() { return ( ); } ``` ### RGB Channels You can also use RGB color space with red, green, and blue channels. ```tsx "use client"; import {ColorSlider, ColorSwatch, Label} from "@heroui/react"; import {useState} from "react"; import {parseColor} from "react-aria-components"; export function RGBChannels() { const [color, setColor] = useState(parseColor("rgb(255, 100, 50)")); return (

Current color: {color.toString("rgb")}

); } ``` ### Custom Render Function ```tsx "use client"; import {ColorSlider, Label} from "@heroui/react"; export function CustomRenderFunction() { return (
} > ); } ``` ## Related Components * **ColorSwatch**: Visual preview of a color value * **ColorSwatchPicker**: Color swatch selection from a list of colors * **ColorPicker**: Composable color picker with popover ## Styling ### Passing Tailwind CSS classes ```tsx import { ColorSlider, Label } from '@heroui/react'; function CustomColorSlider() { return ( ); } ``` ### Customizing the component classes To customize the ColorSlider component classes, you can use the `@layer components` directive.
[Learn more](https://tailwindcss.com/docs/adding-custom-styles#adding-component-classes). ```css @layer components { .color-slider { @apply flex flex-col gap-2; } .color-slider__output { @apply text-muted text-sm; } .color-slider__track { @apply relative h-5 w-full rounded-full; } .color-slider__thumb { @apply size-4 rounded-full border-3 border-white shadow-overlay; } } ``` HeroUI follows the [BEM](https://getbem.com/) methodology to ensure component variants and states are reusable and easy to customize. ### CSS Classes The ColorSlider component uses these CSS classes ([View source styles](https://github.com/heroui-inc/heroui/blob/v3/packages/styles/components/color-slider.css)): #### Base Classes * `.color-slider` - Base slider container * `.color-slider__output` - Output element displaying current value * `.color-slider__track` - Track element with color gradient * `.color-slider__thumb` - Thumb element showing current color #### State Classes * `.color-slider[data-disabled="true"]` - Disabled slider state * `.color-slider[data-orientation="vertical"]` - Vertical orientation * `.color-slider__thumb[data-dragging="true"]` - Thumb being dragged * `.color-slider__thumb[data-focus-visible="true"]` - Thumb keyboard focused * `.color-slider__thumb[data-disabled="true"]` - Disabled thumb state ### Interactive States The component supports both CSS pseudo-classes and data attributes for flexibility: * **Hover**: `:hover` or `[data-hovered="true"]` on thumb * **Focus**: `:focus-visible` or `[data-focus-visible="true"]` on thumb * **Dragging**: `[data-dragging="true"]` on thumb * **Disabled**: `:disabled` or `[data-disabled="true"]` on slider or thumb ## API Reference ### ColorSlider Props Inherits from [React Aria ColorSlider](https://react-spectrum.adobe.com/react-aria/ColorSlider.html). | Prop | Type | Default | Description | | -------------- | ------------------------------------------------------------------------------ | -------------- | --------------------------------------------------------------------------------------------------------------- | | `channel` | `ColorChannel` | - | The color channel that the slider manipulates (hue, saturation, lightness, brightness, alpha, red, green, blue) | | `colorSpace` | `ColorSpace` | - | The color space (hsl, hsb, rgb). Defaults to the color space of the value | | `value` | `string \| Color` | - | The current color value (controlled) | | `defaultValue` | `string \| Color` | - | The default color value (uncontrolled) | | `onChange` | `(value: Color) => void` | - | Handler called when the value changes during dragging | | `onChangeEnd` | `(value: Color) => void` | - | Handler called when dragging ends | | `orientation` | `"horizontal" \| "vertical"` | `"horizontal"` | The orientation of the slider | | `isDisabled` | `boolean` | - | Whether the slider is disabled | | `name` | `string` | - | The name of the input element for form submission | | `aria-label` | `string` | - | Accessibility label for the slider | | `className` | `string` | - | Additional CSS classes | | `children` | `ReactNode \| RenderFunction` | - | Slider content or render function | | `render` | `DOMRenderFunction` | - | Overrides the default DOM element with a custom render function. | ### ColorSlider.Output Props | Prop | Type | Default | Description | | ----------- | ----------------------------- | ------- | --------------------------------- | | `className` | `string` | - | Additional CSS classes | | `children` | `ReactNode \| RenderFunction` | - | Output content or render function | ### ColorSlider.Track Props | Prop | Type | Default | Description | | ----------- | --------------------------------- | ------- | -------------------------------- | | `className` | `string` | - | Additional CSS classes | | `style` | `CSSProperties \| RenderFunction` | - | Inline styles or render function | | `children` | `ReactNode \| RenderFunction` | - | Track content or render function | ### ColorSlider.Thumb Props | Prop | Type | Default | Description | | ----------- | --------------------------------- | ------- | -------------------------------- | | `className` | `string` | - | Additional CSS classes | | `style` | `CSSProperties \| RenderFunction` | - | Inline styles or render function | | `children` | `ReactNode \| RenderFunction` | - | Thumb content or render function | ### RenderProps When using render functions, these values are provided: | Prop | Type | Description | | ------------- | ---------------------------- | ------------------------------ | | `state` | `ColorSliderState` | The state of the color slider | | `color` | `Color` | The current color value | | `orientation` | `"horizontal" \| "vertical"` | The orientation of the slider | | `isDisabled` | `boolean` | Whether the slider is disabled | ## Accessibility The ColorSlider component implements the ARIA slider pattern and provides: * Full keyboard navigation support (Arrow keys, Home, End, Page Up/Down) * Screen reader announcements for value changes * Proper focus management * Support for disabled states * HTML form integration via hidden input elements * Internationalization support with locale-aware value formatting For more information, see the [React Aria ColorSlider documentation](https://react-spectrum.adobe.com/react-aria/ColorSlider.html). # ColorSwatchPicker **Category**: react **URL**: https://v3.heroui.com/docs/react/components/color-swatch-picker **Source**: https://raw.githubusercontent.com/heroui-inc/heroui/refs/heads/v3/apps/docs/content/docs/react/components/(colors)/color-swatch-picker.mdx > A list of color swatches that allows users to select a color from a predefined palette. ## Import ```tsx import { ColorSwatchPicker, parseColor } from '@heroui/react'; ``` ### Usage ```tsx import {ColorSwatchPicker} from "@heroui/react"; const colors = ["#F43F5E", "#D946EF", "#8B5CF6", "#3B82F6", "#06B6D4", "#10B981", "#84CC16"]; export function Basic() { return ( {colors.map((color) => ( ))} ); } ``` ### Anatomy Import the ColorSwatchPicker component and access all parts using dot notation. ```tsx import { ColorSwatchPicker } from '@heroui/react'; export default () => ( ); ``` ### Variants ```tsx import {ColorSwatchPicker} from "@heroui/react"; const colors = ["#F43F5E", "#D946EF", "#8B5CF6", "#3B82F6", "#06B6D4", "#10B981", "#84CC16"]; export function Variants() { return (
Circle (default) {colors.map((color) => ( ))}
Square {colors.map((color) => ( ))}
); } ``` ### Sizes ```tsx import {ColorSwatchPicker} from "@heroui/react"; const colors = ["#F43F5E", "#D946EF", "#8B5CF6", "#3B82F6", "#06B6D4", "#10B981", "#84CC16"]; const sizes = ["xs", "sm", "md", "lg", "xl"] as const; export function Sizes() { return (
{sizes.map((size) => (
{size} {colors.map((color) => ( ))}
))}
); } ``` ### Stack Layout ```tsx import {ColorSwatchPicker} from "@heroui/react"; const colors = ["#F43F5E", "#D946EF", "#8B5CF6", "#3B82F6", "#06B6D4", "#10B981", "#84CC16"]; export function StackLayout() { return ( {colors.map((color) => ( ))} ); } ``` ### Default Value ```tsx import {ColorSwatchPicker} from "@heroui/react"; const colors = ["#F43F5E", "#D946EF", "#8B5CF6", "#3B82F6", "#06B6D4", "#10B981", "#84CC16"]; export function DefaultValue() { return ( {colors.map((color) => ( ))} ); } ``` ### Controlled ```tsx "use client"; import {ColorSwatchPicker, parseColor} from "@heroui/react"; import {useState} from "react"; const colors = ["#F43F5E", "#D946EF", "#8B5CF6", "#3B82F6", "#06B6D4", "#10B981", "#84CC16"]; export function Controlled() { const [value, setValue] = useState(parseColor("#F43F5E")); return (
{colors.map((color) => ( ))}

Selected: {value.toString("hex")}

); } ``` ### Disabled ```tsx import {ColorSwatchPicker} from "@heroui/react"; const colors = ["#F43F5E", "#D946EF", "#8B5CF6", "#3B82F6", "#06B6D4", "#10B981", "#84CC16"]; export function Disabled() { return ( {colors.map((color) => ( ))} ); } ``` ### Custom Indicator ```tsx import {HeartFill} from "@gravity-ui/icons"; import {ColorSwatchPicker} from "@heroui/react"; export function CustomIndicator() { const colors = ["#F43F5E", "#D946EF", "#8B5CF6", "#3B82F6", "#06B6D4", "#10B981", "#84CC16"]; return ( {colors.map((color) => ( ))} ); } ``` ### Custom Render Function ```tsx "use client"; import {ColorSwatchPicker} from "@heroui/react"; const colors = ["#F43F5E", "#D946EF", "#8B5CF6", "#3B82F6", "#06B6D4", "#10B981", "#84CC16"]; export function CustomRenderFunction() { return (
}> {colors.map((color) => ( ))} ); } ``` ## Related Components * **ColorSwatch**: Visual preview of a color value * **ColorField**: Input for entering color values with hex format * **ColorArea**: 2D color picker for selecting colors from a gradient area ## Styling ### Passing Tailwind CSS classes You can customize the ColorSwatchPicker using className props: ```tsx import { ColorSwatchPicker } from '@heroui/react'; function CustomColorSwatchPicker() { return ( ); } ``` ### Customizing the component classes To customize the ColorSwatchPicker component classes, you can use the `@layer components` directive.
[Learn more](https://tailwindcss.com/docs/adding-custom-styles#adding-component-classes). ```css @layer components { .color-swatch-picker { @apply gap-4; } .color-swatch-picker__item { @apply shadow-md; } .color-swatch-picker__swatch { @apply border-2 border-white; } } ``` HeroUI follows the [BEM](https://getbem.com/) methodology to ensure component variants and states are reusable and easy to customize. ### CSS Classes The ColorSwatchPicker component uses these CSS classes ([View source styles](https://github.com/heroui-inc/heroui/blob/v3/packages/styles/components/color-swatch-picker.css)): #### Base & Structure * `.color-swatch-picker` - Base container (flex layout) * `.color-swatch-picker__item` - Individual swatch item wrapper * `.color-swatch-picker__swatch` - The color swatch visual element #### Size Classes * `.color-swatch-picker--xs` - Extra small (16px) * `.color-swatch-picker--sm` - Small (24px) * `.color-swatch-picker--md` - Medium (32px, default) * `.color-swatch-picker--lg` - Large (36px) * `.color-swatch-picker--xl` - Extra large (40px) #### Shape Variants * `.color-swatch-picker--circle` - Circle shape (default) * `.color-swatch-picker--square` - Square shape with rounded corners #### Layout Classes * `.color-swatch-picker--grid` - Horizontal wrapping layout (default) * `.color-swatch-picker--stack` - Vertical stacked layout ### Interactive States The component supports both CSS pseudo-classes and data attributes for flexibility: * **Hover**: `:hover` or `[data-hovered="true"]` - Scale up to 1.1 (only when not selected) * **Focus**: `:focus-visible` or `[data-focus-visible="true"]` - Focus ring * **Selected**: `[data-selected="true"]` - Inner border with same color as swatch * **Disabled**: `[data-disabled="true"]` - Reduced opacity ## API Reference ### ColorSwatchPicker Props Inherits from [React Aria ColorSwatchPicker](https://react-spectrum.adobe.com/react-aria/ColorSwatchPicker.html). | Prop | Type | Default | Description | | -------------- | ------------------------------------------------------------------------------------ | ---------- | ---------------------------------------------------------------- | | `value` | `string \| Color` | - | The current selected color (controlled) | | `defaultValue` | `string \| Color` | - | The default selected color (uncontrolled) | | `onChange` | `(value: Color) => void` | - | Handler called when selection changes | | `size` | `"xs" \| "sm" \| "md" \| "lg" \| "xl"` | `"md"` | Size of the swatches | | `variant` | `"circle" \| "square"` | `"circle"` | Shape of the swatches | | `layout` | `"grid" \| "stack"` | `"grid"` | Layout direction | | `className` | `string` | - | Additional CSS classes | | `children` | `React.ReactNode` | - | ColorSwatchPicker.Item elements | | `render` | `DOMRenderFunction` | - | Overrides the default DOM element with a custom render function. | ### ColorSwatchPicker.Item Props | Prop | Type | Default | Description | | ------------ | ---------------------------------------------------------------------------------------- | ------------ | ---------------------------------------------------------------- | | `color` | `string \| Color` | **Required** | The color of the swatch | | `isDisabled` | `boolean` | `false` | Whether the item is disabled | | `className` | `string` | - | Additional CSS classes | | `children` | `React.ReactNode` | - | ColorSwatchPicker.Swatch element | | `render` | `DOMRenderFunction` | - | Overrides the default DOM element with a custom render function. | ### ColorSwatchPicker.Swatch Props | Prop | Type | Default | Description | | ----------- | -------- | ------- | ---------------------- | | `className` | `string` | - | Additional CSS classes | ### parseColor The `parseColor` function is re-exported from React Aria Components for convenience: ```tsx import { parseColor } from '@heroui/react'; // Parse hex color const red = parseColor('#ff0000'); // Parse RGB const green = parseColor('rgb(0, 255, 0)'); // Parse HSL const blue = parseColor('hsl(240, 100%, 50%)'); ``` # ColorSwatch **Category**: react **URL**: https://v3.heroui.com/docs/react/components/color-swatch **Source**: https://raw.githubusercontent.com/heroui-inc/heroui/refs/heads/v3/apps/docs/content/docs/react/components/(colors)/color-swatch.mdx > A visual preview of a color value with accessibility support ## Import ```tsx import { ColorSwatch } from '@heroui/react'; ``` ### Usage ```tsx import {ColorSwatch} from "@heroui/react"; export function ColorSwatchBasic() { return (
); } ``` ### Sizes ```tsx import {ColorSwatch} from "@heroui/react"; export function ColorSwatchSizes() { return (
); } ``` ### Shapes ```tsx import {ColorSwatch} from "@heroui/react"; export function ColorSwatchShapes() { return (
); } ``` ### Transparency ```tsx import {ColorSwatch} from "@heroui/react"; export function ColorSwatchTransparency() { return (
); } ``` ### Custom Styles with Render Props You can use the `style` render props to access the color value and create custom visual effects. ```tsx "use client"; import {ColorSwatch} from "@heroui/react"; export function ColorSwatchCustomStyles() { const colors = ["#0485F7", "#EF4444", "#F59E0B", "#10B981", "#D946EF"]; return (
{/* Glow effect */}
Glow Effect
{colors.map((color) => ( ({ boxShadow: `0 0 20px 2px ${color}`, })} /> ))}
{/* Gradient swatch */}
Gradient
{colors.map((color) => ( ({ background: `linear-gradient(135deg, ${c.toString("css")}, white)`, })} /> ))}
); } ``` ### Accessibility Use `colorName` to provide a custom accessible name for the color, and `aria-label` to add context about how the color is used. ```tsx import {ColorSwatch} from "@heroui/react"; export function ColorSwatchAccessibility() { return (
); } ``` ### Custom Render Function ```tsx "use client"; import {ColorSwatch} from "@heroui/react"; export function CustomRenderFunction() { return (
} />
} />
} />
} />
} />
); } ``` ## Related Components * **ColorSwatchPicker**: Color swatch selection from a list of colors * **ColorField**: Input for entering color values with hex format * **ColorArea**: 2D color picker for selecting colors from a gradient area ## Styling ### Passing Tailwind CSS classes ```tsx import {ColorSwatch} from '@heroui/react'; function CustomColorSwatch() { return ( ); } ``` ### Customizing the component classes To customize the ColorSwatch component classes, you can use the `@layer components` directive.
[Learn more](https://tailwindcss.com/docs/adding-custom-styles#adding-component-classes). ```css @layer components { .color-swatch { @apply border-2 border-white; } } ``` HeroUI follows the [BEM](https://getbem.com/) methodology to ensure component variants and states are reusable and easy to customize. ### CSS Classes The ColorSwatch component uses these CSS classes ([View source styles](https://github.com/heroui-inc/heroui/blob/v3/packages/styles/components/color-swatch.css)): #### Base Classes * `.color-swatch` - Base swatch styles with checkered background for transparency #### Shape Classes * `.color-swatch--circle` - Circular shape (default) * `.color-swatch--square` - Square shape with rounded corners #### Size Classes * `.color-swatch--xs` - Extra small (16px) * `.color-swatch--sm` - Small (24px) * `.color-swatch--md` - Medium (32px, default) * `.color-swatch--lg` - Large (36px) * `.color-swatch--xl` - Extra large (40px) ## API Reference ### ColorSwatch Props | Prop | Type | Default | Description | | ------------ | ------------------------------------------------------------------------------ | ---------- | -------------------------------------------------------------------- | | `color` | `string \| Color` | - | The color value to display (hex, rgb, hsl, etc.) | | `colorName` | `string` | - | Accessible name for the color (overrides auto-generated description) | | `className` | `string` | - | Additional CSS classes | | `shape` | `"circle" \| "square"` | `"circle"` | Shape of the swatch | | `size` | `"xs" \| "sm" \| "md" \| "lg" \| "xl"` | `"md"` | Size of the swatch | | `style` | `CSSProperties \| ((renderProps) => CSSProperties)` | - | Inline styles or render props function with access to color | | `aria-label` | `string` | - | Accessible label for the swatch | | `render` | `DOMRenderFunction` | - | Overrides the default DOM element with a custom render function. | ### Style Render Props When using the `style` prop as a function, you receive render props with access to the color: ```tsx ({ boxShadow: `0 4px 14px ${color.toString("css")}80`, })} /> ``` The `color` object provides methods like: * `color.toString("css")` - Returns CSS color string * `color.toString("hex")` - Returns hex color string * `color.getChannelValue("alpha")` - Returns alpha channel value # Slider **Category**: react **URL**: https://v3.heroui.com/docs/react/components/slider **Source**: https://raw.githubusercontent.com/heroui-inc/heroui/refs/heads/v3/apps/docs/content/docs/react/components/(controls)/slider.mdx > A slider allows a user to select one or more values within a range ## Import ```tsx import { Slider } from '@heroui/react'; ``` ### Usage ```tsx import {Label, Slider} from "@heroui/react"; export function Default() { return ( ); } ``` ### Anatomy Import the Slider component and access all parts using dot notation. ```tsx import { Slider, Label } from '@heroui/react'; export default () => ( ) ``` ### Range Slider Anatomy ```tsx import { Slider, Label } from '@heroui/react'; export default () => ( ) ``` ### Vertical ```tsx import {Label, Slider} from "@heroui/react"; export function Vertical() { return (
); } ``` ### Range ```tsx "use client"; import {Label, Slider} from "@heroui/react"; export function Range() { return ( {({state}) => ( <> {state.values.map((_, i) => ( ))} )} ); } ``` ### Disabled ```tsx import {Label, Slider} from "@heroui/react"; export function Disabled() { return ( ); } ``` ### Custom Render Function ```tsx "use client"; import {Label, Slider} from "@heroui/react"; export function CustomRenderFunction() { return (
} > ); } ``` ## Related Components * **Label**: Accessible label for form controls * **Form**: Form validation and submission handling * **Description**: Helper text for form fields ## Styling ### Passing Tailwind CSS classes ```tsx import { Slider, Label } from '@heroui/react'; function CustomSlider() { return ( ); } ``` ### Customizing the component classes To customize the Slider component classes, you can use the `@layer components` directive.
[Learn more](https://tailwindcss.com/docs/adding-custom-styles#adding-component-classes). ```css @layer components { .slider { @apply flex flex-col gap-2; } .slider__output { @apply text-muted-fg text-sm; } .slider-track { @apply relative h-2 w-full rounded-full bg-surface-secondary; } .slider-fill { @apply absolute h-full rounded-full bg-accent; } .slider-thumb { @apply size-4 rounded-full bg-accent border-2 border-background; } } ``` HeroUI follows the [BEM](https://getbem.com/) methodology to ensure component variants and states are reusable and easy to customize. ### CSS Classes The Slider component uses these CSS classes ([View source styles](https://github.com/heroui-inc/heroui/blob/v3/packages/styles/components/slider.css)): #### Base Classes * `.slider` - Base slider container * `.slider__output` - Output element displaying current value(s) * `.slider-track` - Track element containing fill and thumbs * `.slider-fill` - Fill element showing selected range * `.slider-thumb` - Individual thumb element #### State Classes * `.slider[data-disabled="true"]` - Disabled slider state * `.slider[data-orientation="vertical"]` - Vertical orientation * `.slider-thumb[data-dragging="true"]` - Thumb being dragged * `.slider-thumb[data-focus-visible="true"]` - Thumb keyboard focused * `.slider-thumb[data-disabled="true"]` - Disabled thumb state * `.slider-track[data-fill-start="true"]` - Fill starts at beginning * `.slider-track[data-fill-end="true"]` - Fill ends at end ### Interactive States The component supports both CSS pseudo-classes and data attributes for flexibility: * **Hover**: `:hover` or `[data-hovered="true"]` on thumb * **Focus**: `:focus-visible` or `[data-focus-visible="true"]` on thumb * **Dragging**: `[data-dragging="true"]` on thumb * **Disabled**: `:disabled` or `[data-disabled="true"]` on slider or thumb ## API Reference ### Slider Props | Prop | Type | Default | Description | | ----------------- | ------------------------------------------------------------------------- | -------------- | ---------------------------------------------------------------- | | `value` | `number \| number[]` | - | The current value (controlled) | | `defaultValue` | `number \| number[]` | - | The default value (uncontrolled) | | `onChange` | `(value: number \| number[]) => void` | - | Handler called when the value changes | | `onChangeEnd` | `(value: number \| number[]) => void` | - | Handler called when dragging ends | | `minValue` | `number` | `0` | The slider's minimum value | | `maxValue` | `number` | `100` | The slider's maximum value | | `step` | `number` | `1` | The slider's step value | | `formatOptions` | `Intl.NumberFormatOptions` | - | The display format of the value label | | `orientation` | `"horizontal" \| "vertical"` | `"horizontal"` | The orientation of the slider | | `isDisabled` | `boolean` | - | Whether the slider is disabled | | `aria-label` | `string` | - | Accessibility label for the slider | | `aria-labelledby` | `string` | - | ID of element that labels the slider | | `className` | `string` | - | Additional CSS classes | | `children` | `ReactNode \| RenderFunction` | - | Slider content or render function | | `render` | `DOMRenderFunction` | - | Overrides the default DOM element with a custom render function. | ### Slider.Output Props | Prop | Type | Default | Description | | ----------- | ------------------------------------------------------------------------------- | ------- | ---------------------------------------------------------------- | | `className` | `string` | - | Additional CSS classes | | `children` | `ReactNode \| RenderFunction` | - | Output content or render function | | `render` | `DOMRenderFunction` | - | Overrides the default DOM element with a custom render function. | ### Slider.Track Props | Prop | Type | Default | Description | | ----------- | ------------------------------------------------------------------------------ | ------- | ---------------------------------------------------------------- | | `className` | `string` | - | Additional CSS classes | | `children` | `ReactNode \| RenderFunction` | - | Track content or render function | | `render` | `DOMRenderFunction` | - | Overrides the default DOM element with a custom render function. | ### Slider.Fill Props | Prop | Type | Default | Description | | ----------- | --------------- | ------- | ---------------------- | | `className` | `string` | - | Additional CSS classes | | `style` | `CSSProperties` | - | Inline styles | ### Slider.Thumb Props | Prop | Type | Default | Description | | ------------ | ------------------------------------------------------------------------------ | ------- | ---------------------------------------------------------------- | | `index` | `number` | `0` | Index of the thumb within the slider | | `isDisabled` | `boolean` | - | Whether this thumb is disabled | | `name` | `string` | - | The name of the input element, used when submitting an HTML form | | `className` | `string` | - | Additional CSS classes | | `children` | `ReactNode \| RenderFunction` | - | Thumb content or render function | | `render` | `DOMRenderFunction` | - | Overrides the default DOM element with a custom render function. | ### RenderProps When using render functions with Slider.Output or Slider.Track, these values are provided: | Prop | Type | Description | | -------------------- | ---------------------------- | -------------------------------------------------------- | | `state` | `SliderState` | The state of the slider | | `values` | `number[]` | Values managed by the slider by thumb index | | `getThumbValueLabel` | `(index: number) => string` | Returns the string label for the specified thumb's value | | `orientation` | `"horizontal" \| "vertical"` | The orientation of the slider | | `isDisabled` | `boolean` | Whether the slider is disabled | ## Examples ### Basic Usage ```tsx import { Slider, Label } from '@heroui/react'; ``` ### Range Slider ```tsx import { Slider, Label } from '@heroui/react'; {({state}) => ( <> {state.values.map((_, i) => ( ))} )} ``` ### Controlled Value ```tsx import { Slider, Label } from '@heroui/react'; import { useState } from 'react'; function ControlledSlider() { const [value, setValue] = useState(25); return ( <>

Current value: {value}

); } ``` ### Custom Value Formatting ```tsx import { Slider, Label } from '@heroui/react'; ``` ### Vertical Orientation ```tsx import { Slider, Label } from '@heroui/react'; ``` ### Custom Output Display ```tsx import { Slider, Label } from '@heroui/react'; {({state}) => state.values.map((_, i) => state.getThumbValueLabel(i)).join(' – ') } {({state}) => ( <> {state.values.map((_, i) => ( ))} )} ``` ## Accessibility The Slider component implements the ARIA slider pattern and provides: * Full keyboard navigation support (Arrow keys, Home, End, Page Up/Down) * Screen reader announcements for value changes * Proper focus management * Support for disabled states * HTML form integration via hidden input elements * Internationalization support with locale-aware value formatting * Right-to-left (RTL) language support For more information, see the [React Aria Slider documentation](https://react-spectrum.adobe.com/react-aria/Slider.html). # Switch **Category**: react **URL**: https://v3.heroui.com/docs/react/components/switch **Source**: https://raw.githubusercontent.com/heroui-inc/heroui/refs/heads/v3/apps/docs/content/docs/react/components/(controls)/switch.mdx > A toggle switch component for boolean states ## Import ```tsx import { Switch, SwitchGroup, Label } from '@heroui/react'; ``` ### Usage ```tsx import {Label, Switch} from "@heroui/react"; export function Basic() { return ( ); } ``` ### Anatomy Import the Switch component and access all parts using dot notation. ```tsx import { Switch, Label } from '@heroui/react'; export default () => ( {/* 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 (
{Object.entries(icons).map(([key, value]) => ( {({isSelected}) => ( <> {isSelected ? ( ) : ( )} )} ))}
); } ``` ### 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 ? ( ) : ( )} )} ); } ``` ### Custom Render Function ```tsx "use client"; import {Label, Switch} from "@heroui/react"; export function CustomRenderFunction() { return ( ); } ``` ## 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 | | `render` | `DOMRenderFunction` | - | Overrides the default DOM element with a custom render function. | ### 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'; ``` ## Anatomy Import the Chip component and access all parts using dot notation. > Plain-text children are automatically wrapped in ``. ```tsx Label text ``` ### Usage ```tsx import {Chip} from "@heroui/react"; export function ChipBasic() { return (
Default Accent Success Warning Danger
); } ``` ### 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 You can style the root container and individual slots: ```tsx import {Chip} from '@heroui/react'; function CustomChip() { return ( Custom Styled ); } ``` ### Customizing the component classes To customize the Chip component classes, you can use the `@layer components` directive.
[Learn more](https://tailwindcss.com/docs/adding-custom-styles#adding-component-classes). ```css @layer components { .chip { @apply rounded-full text-xs; } .chip__label { @apply font-medium; } .chip--accent { @apply border-accent/20; } .chip--accent .chip__label { @apply text-accent; } } ``` HeroUI follows the [BEM](https://getbem.com/) methodology to ensure component variants and states are reusable and easy to customize. ### CSS Classes The Chip component uses these CSS classes ([View source styles](https://github.com/heroui-inc/heroui/blob/v3/packages/styles/components/chip.css)): #### Base Classes * `.chip` - Base chip container styles * `.chip__label` - Label text slot styles #### Color Classes * `.chip--accent` - Accent color variant * `.chip--danger` - Danger color variant * `.chip--default` - Default color variant * `.chip--success` - Success color variant * `.chip--warning` - Warning color variant #### Variant Classes * `.chip--primary` - Primary variant with filled background * `.chip--secondary` - Secondary variant with border * `.chip--tertiary` - Tertiary variant with transparent background * `.chip--soft` - Soft variant with lighter background #### Size Classes * `.chip--sm` - Small size * `.chip--md` - Medium size (default) * `.chip--lg` - Large size #### Compound Variant Classes Chips support combining variant and color classes (e.g., `.chip--secondary.chip--accent`). The following combinations have default styles defined: **Primary Variants:** * `.chip--primary.chip--accent` - Primary accent combination with filled background * `.chip--primary.chip--success` - Primary success combination with filled background * `.chip--primary.chip--warning` - Primary warning combination with filled background * `.chip--primary.chip--danger` - Primary danger combination with filled background **Soft Variants:** * `.chip--accent.chip--soft` - Soft accent combination with lighter background * `.chip--success.chip--soft` - Soft success combination with lighter background * `.chip--warning.chip--soft` - Soft warning combination with lighter background * `.chip--danger.chip--soft` - Soft danger combination with lighter background **Note:** You can apply custom styles to any variant-color combination (e.g., `.chip--secondary.chip--accent`, `.chip--tertiary.chip--success`) using the `@layer components` directive in your CSS. ## API Reference ### Chip Props | Prop | Type | Default | Description | | ----------- | ------------------------------------------------------------- | ------------- | ------------------------------------------- | | `children` | `React.ReactNode` | - | Content to display inside the chip | | `className` | `string` | - | Additional CSS classes for the root element | | `color` | `"default" \| "accent" \| "success" \| "warning" \| "danger"` | `"default"` | Color variant of the chip | | `variant` | `"primary" \| "secondary" \| "tertiary" \| "soft"` | `"secondary"` | Visual style variant | | `size` | `"sm" \| "md" \| "lg"` | `"md"` | Size of the chip | ### Chip.Label Props | Prop | Type | Default | Description | | ----------- | ----------------- | ------- | ----------------------------------------- | | `children` | `React.ReactNode` | - | Label text content | | `className` | `string` | - | Additional CSS classes for the label slot | # Calendar **Category**: react **URL**: https://v3.heroui.com/docs/react/components/calendar **Source**: https://raw.githubusercontent.com/heroui-inc/heroui/refs/heads/v3/apps/docs/content/docs/react/components/(date-and-time)/calendar.mdx > Composable date picker with month grid, navigation, and year picker support built on React Aria Calendar ## Import ```tsx import { Calendar } from '@heroui/react'; ``` ### Usage ```tsx "use client"; import {Calendar} from "@heroui/react"; export function Basic() { return ( {(day) => {day}} {(date) => } ); } ``` ### Anatomy ```tsx import {Calendar} from '@heroui/react'; export default () => ( {(day) => {day}} {(date) => } ) ``` ### Year Picker `Calendar.YearPickerTrigger`, `Calendar.YearPickerGrid`, and their body/cell subcomponents provide an integrated year navigation pattern. ```tsx "use client"; import {Calendar} from "@heroui/react"; export function YearPicker() { return ( {(day) => {day}} {(date) => } {({year}) => } ); } ``` ### Default Value ```tsx "use client"; import {Calendar} from "@heroui/react"; import {parseDate} from "@internationalized/date"; export function DefaultValue() { return ( {(day) => {day}} {(date) => } ); } ``` ### Controlled Use controlled `value` and `focusedValue` for external state coordination and custom shortcuts. ```tsx "use client"; import type {DateValue} from "@internationalized/date"; import {Button, ButtonGroup, Calendar, Description} from "@heroui/react"; import { getLocalTimeZone, parseDate, startOfMonth, startOfWeek, today, } from "@internationalized/date"; import {useState} from "react"; import {useLocale} from "react-aria-components"; export function Controlled() { const [value, setValue] = useState(null); const [focusedDate, setFocusedDate] = useState(parseDate("2025-12-25")); const {locale} = useLocale(); return (
{(day) => {day}} {(date) => } Selected date: {value ? value.toString() : "(none)"}
); } ``` ### Min and Max Dates ```tsx "use client"; import {Calendar, Description} from "@heroui/react"; import {getLocalTimeZone, today} from "@internationalized/date"; export function MinMaxDates() { const now = today(getLocalTimeZone()); const minDate = now; const maxDate = now.add({months: 3}); return (
{(day) => {day}} {(date) => } Select a date between today and {maxDate.toString()}
); } ``` ### Unavailable Dates Use `isDateUnavailable` to block dates such as weekends, holidays, or booked slots. ```tsx "use client"; import type {DateValue} from "@internationalized/date"; import {Calendar, Description} from "@heroui/react"; import {isWeekend} from "@internationalized/date"; import {useLocale} from "react-aria-components"; export function UnavailableDates() { const {locale} = useLocale(); const isDateUnavailable = (date: DateValue) => isWeekend(date, locale); return (
{(day) => {day}} {(date) => } Weekends are unavailable
); } ``` ### Disabled ```tsx "use client"; import {Calendar, Description} from "@heroui/react"; import {getLocalTimeZone, today} from "@internationalized/date"; export function Disabled() { return (
{(day) => {day}} {(date) => } Calendar is disabled
); } ``` ### Read Only ```tsx "use client"; import {Calendar, Description} from "@heroui/react"; import {getLocalTimeZone, today} from "@internationalized/date"; export function ReadOnly() { return (
{(day) => {day}} {(date) => } Calendar is read-only
); } ``` ### Focused Value Programmatically control which date is focused using `focusedValue` and `onFocusChange`. ```tsx "use client"; import type {DateValue} from "@internationalized/date"; import {Button, Calendar, Description} from "@heroui/react"; import {parseDate} from "@internationalized/date"; import {useState} from "react"; export function FocusedValue() { const [focusedDate, setFocusedDate] = useState(parseDate("2025-06-15")); return (
{(day) => {day}} {(date) => } Focused: {focusedDate.toString()}
); } ``` ### Cell Indicators You can customize `Calendar.Cell` children and use `Calendar.CellIndicator` to display metadata like events. ```tsx "use client"; import {Calendar} from "@heroui/react"; import {getLocalTimeZone, isToday} from "@internationalized/date"; const datesWithEvents = [3, 7, 12, 15, 21, 28]; export function WithIndicators() { return ( {(day) => {day}} {(date) => ( {({formattedDate}) => ( <> {formattedDate} {(isToday(date, getLocalTimeZone()) || datesWithEvents.includes(date.day)) && ( )} )} )} ); } ``` ### Multiple Months Render multiple grids with `visibleDuration` and `offset` for booking and planning experiences. ```tsx "use client"; import {Calendar} from "@heroui/react"; import {getLocalTimeZone} from "@internationalized/date"; import React from "react"; import {CalendarStateContext, useLocale} from "react-aria-components"; function CalendarMonthHeading({offset = 0}: {offset?: number}) { const state = React.useContext(CalendarStateContext)!; const {locale} = useLocale(); const startDate = state.visibleRange.start; const monthDate = startDate.add({months: offset}); const dateObj = monthDate.toDate(getLocalTimeZone()); const monthYear = new Intl.DateTimeFormat(locale, {month: "long", year: "numeric"}).format( dateObj, ); return {monthYear}; } export function MultipleMonths() { return (
{(day) => {day}} {(date) => }
{(day) => {day}} {(date) => }
); } ``` ### International Calendars By default, Calendar displays dates using the calendar system for the user's locale. You can override this by wrapping your Calendar with `I18nProvider` and setting the [Unicode calendar locale extension](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Intl/Locale/calendar#adding_a_calendar_in_the_locale_string). The example below shows the Indian calendar system: ```tsx "use client"; import {Calendar} from "@heroui/react"; import {getLocalTimeZone, today} from "@internationalized/date"; import {I18nProvider} from "react-aria-components"; export function InternationalCalendar() { return ( {(day) => {day}} {(date) => } {({year}) => } ); } ``` **Note:** The `onChange` event always returns a date in the same calendar system as the `value` or `defaultValue` (Gregorian if no value is provided), regardless of the displayed locale. This ensures your application logic works consistently with a single calendar system while still displaying dates in the user's preferred format. For a complete list of supported calendar systems and their identifiers, see: * [React Aria Calendar Implementations](https://react-aria.adobe.com/internationalized/date/Calendar#implementations) * [React Aria International Calendars](https://react-aria.adobe.com/Calendar#international-calendars) ### Custom Navigation Icons Pass children to `Calendar.NavButton` to replace the default chevron icons. ```tsx "use client"; import {Calendar} from "@heroui/react"; export function CustomIcons() { return ( {(day) => {day}} {(date) => } ); } ``` ### Real-World Example ```tsx "use client"; import type {DateValue} from "@internationalized/date"; import {Button, Calendar} from "@heroui/react"; import {getLocalTimeZone, isWeekend, today} from "@internationalized/date"; import {useState} from "react"; import {useLocale} from "react-aria-components"; export function BookingCalendar() { const [selectedDate, setSelectedDate] = useState(null); const {locale} = useLocale(); const bookedDates = [5, 6, 12, 13, 14, 20]; const isDateUnavailable = (date: DateValue) => { return isWeekend(date, locale) || bookedDates.includes(date.day); }; return (
{(day) => {day}} {(date) => ( {({formattedDate, isUnavailable}) => ( <> {formattedDate} {!isUnavailable && !isWeekend(date, locale) && bookedDates.includes(date.day) && } )} )}
Has bookings Weekend/Unavailable
{selectedDate ? ( ) : null}
); } ``` ### Custom Styles ```tsx "use client"; import {Calendar} from "@heroui/react"; export function CustomStyles() { return ( {(day) => {day}} {(date) => } {({year}) => } ); } ``` ## Related Components * **DateField**: Date input field with labels, descriptions, and validation * **DatePicker**: Composable date picker with date field trigger and calendar popover * **TimeField**: Time input field with labels, descriptions, and validation ## Styling ### Passing Tailwind CSS classes ```tsx import {Calendar} from '@heroui/react'; function CustomCalendar() { return ( {(day) => {day}} {(date) => } ); } ``` ### Customizing the component classes ```css @layer components { .calendar { @apply w-72 rounded-2xl border border-border bg-surface p-3 shadow-sm; } .calendar__heading { @apply text-sm font-semibold text-default-700; } .calendar__cell[data-selected="true"] { @apply bg-accent text-accent-foreground; } } ``` ### CSS Classes Calendar uses these classes in `packages/styles/components/calendar.css` and `packages/styles/components/calendar-year-picker.css`: * `.calendar` - Root container. * `.calendar__header` - Header row containing nav buttons and heading. * `.calendar__heading` - Current month label. * `.calendar__nav-button` - Previous/next navigation controls. * `.calendar__grid` - Main day grid. * `.calendar__grid-header` - Weekday header row wrapper. * `.calendar__grid-body` - Date rows wrapper. * `.calendar__header-cell` - Weekday header cell. * `.calendar__cell` - Interactive day cell. * `.calendar__cell-indicator` - Dot indicator inside a day cell. * `.calendar-year-picker__trigger` - Year picker toggle button. * `.calendar-year-picker__trigger-heading` - Heading text inside year picker trigger. * `.calendar-year-picker__trigger-indicator` - Indicator icon inside year picker trigger. * `.calendar-year-picker__year-grid` - Overlay grid of selectable years. * `.calendar-year-picker__year-cell` - Individual year option. ### Interactive States Calendar supports both pseudo-classes and React Aria data attributes: * **Selected**: `[data-selected="true"]` * **Today**: `[data-today="true"]` * **Unavailable**: `[data-unavailable="true"]` * **Outside month**: `[data-outside-month="true"]` * **Hovered**: `:hover` or `[data-hovered="true"]` * **Pressed**: `:active` or `[data-pressed="true"]` * **Focus visible**: `:focus-visible` or `[data-focus-visible="true"]` * **Disabled**: `:disabled` or `[data-disabled="true"]` ## API Reference ### Calendar Props Calendar inherits all props from React Aria [Calendar](https://react-spectrum.adobe.com/react-aria/Calendar.html). | Prop | Type | Default | Description | | ------------------------ | ------------------------------ | --------------------------- | ------------------------------------------------------ | | `value` | `DateValue \| null` | - | Controlled selected date. | | `defaultValue` | `DateValue \| null` | - | Initial selected date (uncontrolled). | | `onChange` | `(value: DateValue) => void` | - | Called when selection changes. | | `focusedValue` | `DateValue` | - | Controlled focused date. | | `onFocusChange` | `(value: DateValue) => void` | - | Called when focus moves to another date. | | `minValue` | `DateValue` | Calendar-aware `1900-01-01` | Earliest selectable date. | | `maxValue` | `DateValue` | Calendar-aware `2099-12-31` | Latest selectable date. | | `isDateUnavailable` | `(date: DateValue) => boolean` | - | Marks dates as unavailable. | | `isDisabled` | `boolean` | `false` | Disables interaction and selection. | | `isReadOnly` | `boolean` | `false` | Keeps content readable but prevents selection changes. | | `isInvalid` | `boolean` | `false` | Marks the calendar as invalid for validation UI. | | `visibleDuration` | `{months?: number}` | `{months: 1}` | Number of visible months. | | `defaultYearPickerOpen` | `boolean` | `false` | Initial open state of internal year picker. | | `isYearPickerOpen` | `boolean` | - | Controlled year picker open state. | | `onYearPickerOpenChange` | `(isOpen: boolean) => void` | - | Called when year picker open state changes. | ### Composition Parts | Component | Description | | ------------------------------------- | -------------------------------------------------------------------------- | | `Calendar.Header` | Header container for navigation and heading. | | `Calendar.Heading` | Current month/year heading. | | `Calendar.NavButton` | Previous/next navigation control (`slot=\"previous\"` or `slot=\"next\"`). | | `Calendar.Grid` | Day grid for one month (`offset` supported for multi-month layouts). | | `Calendar.GridHeader` | Weekday header container. | | `Calendar.GridBody` | Date cell body container. | | `Calendar.HeaderCell` | Weekday label cell. | | `Calendar.Cell` | Individual date cell. | | `Calendar.CellIndicator` | Optional indicator element for custom metadata. | | `Calendar.YearPickerTrigger` | Trigger to toggle year-picker mode. | | `Calendar.YearPickerTriggerHeading` | Localized heading content inside the year-picker trigger. | | `Calendar.YearPickerTriggerIndicator` | Toggle icon inside the year-picker trigger. | | `Calendar.YearPickerGrid` | Overlay year selection grid container. | | `Calendar.YearPickerGridBody` | Body renderer for year grid cells. | | `Calendar.YearPickerCell` | Individual year option cell. | ### Calendar.Cell Render Props When `Calendar.Cell` children is a function, React Aria render props are available: | Prop | Type | Description | | ---------------- | --------- | ------------------------------------------- | | `formattedDate` | `string` | Localized day label for the cell. | | `isSelected` | `boolean` | Whether the date is selected. | | `isUnavailable` | `boolean` | Whether the date is unavailable. | | `isDisabled` | `boolean` | Whether the cell is disabled. | | `isOutsideMonth` | `boolean` | Whether the date belongs to adjacent month. | # 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/(date-and-time)/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, Label} from "@heroui/react"; export function Basic() { return ( {(segment) => } ); } ``` ### Anatomy ```tsx import {DateField, Label, Description, FieldError} from '@heroui/react'; export default () => ( ) ``` > **DateField** combines label, date input, description, and error into a single accessible component. ### With Description ```tsx "use client"; import {DateField, 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, 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, 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, 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 )}
); } ``` ### Granularity ```tsx "use client"; import type {DateValue} from "@internationalized/date"; import {CircleQuestion} from "@gravity-ui/icons"; import {DateField, Label, ListBox, Select, Tooltip} from "@heroui/react"; import {parseDate, parseZonedDateTime} from "@internationalized/date"; import {useState} from "react"; export function Granularity() { const granularityOptions = [ {id: "day", label: "Day"}, {id: "hour", label: "Hour"}, {id: "minute", label: "Minute"}, {id: "second", label: "Second"}, ] as const; const [granularity, setGranularity] = useState<"day" | "hour" | "minute" | "second">("day"); // Determine appropriate default value based on granularity let defaultValue: DateValue; if (granularity === "day") { defaultValue = parseDate("2025-02-03"); } else { // hour, minute, second defaultValue = parseZonedDateTime("2025-02-03T08:45:00[America/Los_Angeles]"); } return (
{(segment) => }

Determines the smallest unit displayed in the date picker. By default, this is "day" for dates, and "minute" for times.

); } ``` ### Controlled Control the value to synchronize with other components or state management. ```tsx "use client"; import type {DateValue} from "@internationalized/date"; import {Button, DateField, 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, 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, Label} from "@heroui/react"; export function WithPrefixIcon() { return ( {(segment) => } ); } ``` ```tsx "use client"; import {Calendar} from "@gravity-ui/icons"; import {DateField, Label} from "@heroui/react"; export function WithSuffixIcon() { return ( {(segment) => } ); } ``` ```tsx "use client"; import {Calendar, ChevronDown} from "@gravity-ui/icons"; import {DateField, 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, Label} from "@heroui/react"; export function FullWidth() { return (
{(segment) => } {(segment) => }
); } ``` ### Variants The DateField.Group component supports two visual variants: * **`primary`** (default) - Standard styling with shadow, suitable for most use cases * **`secondary`** - Lower emphasis variant without shadow, suitable for use in Surface components ```tsx "use client"; import {DateField, Label} from "@heroui/react"; export function Variants() { return (
{(segment) => } {(segment) => }
); } ``` ### In Surface When used inside a [Surface](/docs/components/surface) component, use `variant="secondary"` on DateField.Group to apply the lower emphasis variant suitable for surface backgrounds. ```tsx "use client"; import {Calendar} from "@gravity-ui/icons"; import {DateField, 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, 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 (
{(segment) => } {isInvalid ? ( Date must be today or in the future ) : ( Enter a date from today onwards )}
); } ``` ## Related Components * **DatePicker**: Composable date picker with date field trigger and calendar popover * **Calendar**: Interactive month grid for selecting dates * **Label**: Accessible label for form controls ### Custom Render Function ```tsx "use client"; import {DateField, Label} from "@heroui/react"; export function CustomRenderFunction() { return (
} >
}>
}> {(segment) => } ); } ``` ## Styling ### Passing Tailwind CSS classes ```tsx import {DateField, Label, 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. DateField.Group 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, DateField.Group, 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. | | `render` | `DOMRenderFunction` | - | Overrides the default DOM element with a custom render function. | #### 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` * **DateField.Group** - Date input group component (documented below) * **DateField.Input** - Input component with segmented editing from `@heroui/react` * **DateField.Segment** - Individual date segment (year, month, day, etc.) * **DateField.Prefix** / **DateField.Suffix** - Prefix and suffix slots for the input group * **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, 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). | ### DateField.Group Props DateField.Group accepts all props from React Aria's `Group` component plus the following: | Prop | Type | Default | Description | | ----------- | -------------------------- | ----------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------ | | `className` | `string` | - | Tailwind classes merged with the component styles. | | `fullWidth` | `boolean` | `false` | Whether the date input group should take full width of its container | | `variant` | `"primary" \| "secondary"` | `"primary"` | Visual variant of the component. `primary` is the default style with shadow. `secondary` is a lower emphasis variant without shadow, suitable for use in surfaces. | ### DateField.Input Props DateField.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. | | `variant` | `"primary" \| "secondary"` | `"primary"` | Visual variant of the input. `primary` is the default style with shadow. `secondary` is a lower emphasis variant without shadow, suitable for use in surfaces. | The `DateField.Input` component accepts a render prop function that receives date segments. Each segment represents a part of the date (year, month, day, etc.). ### DateField.Segment Props DateField.Segment accepts all props from React Aria's `DateSegment` component: | Prop | Type | Default | Description | | ----------- | ------------- | ------- | ------------------------------------------------------------- | | `segment` | `DateSegment` | - | The date segment object from the DateField.Input render prop. | | `className` | `string` | - | Tailwind classes merged with the component styles. | ### DateField.Prefix Props DateField.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. | ### DateField.Suffix Props DateField.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. | ## DateField.Group 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; } } ``` ### DateField.Group 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 ### DateField.Group Interactive States * **Hover**: `:hover` or `[data-hovered="true"]` * **Focus Within**: `[data-focus-within="true"]` or `:focus-within` * **Invalid**: `[data-invalid="true"]` (also syncs with `aria-invalid`) * **Disabled**: `[data-disabled="true"]` or `[aria-disabled="true"]` * **Segment Focus**: `:focus` or `[data-focused="true"]` on segment elements * **Segment Placeholder**: `[data-placeholder="true"]` on segment elements # DatePicker **Category**: react **URL**: https://v3.heroui.com/docs/react/components/date-picker **Source**: https://raw.githubusercontent.com/heroui-inc/heroui/refs/heads/v3/apps/docs/content/docs/react/components/(date-and-time)/date-picker.mdx > Composable date picker built on React Aria DatePicker with DateField and Calendar composition ## Import ```tsx import { DatePicker, DateField, Calendar, Label } from '@heroui/react'; ``` ### Usage ```tsx "use client"; import {Calendar, DateField, DatePicker, Label} from "@heroui/react"; export function Basic() { return ( {(segment) => } {(day) => {day}} {(date) => } {({year}) => } ); } ``` ### Anatomy `DatePicker` follows a composition-first API. Compose `DateField` and `Calendar` explicitly to control structure and styling. ```tsx import {Calendar, DateField, DatePicker, Label} from '@heroui/react'; export default () => ( ) ``` ### Controlled ```tsx "use client"; import type {DateValue} from "@internationalized/date"; import {Button, Calendar, DateField, DatePicker, Description, Label} from "@heroui/react"; import {getLocalTimeZone, today} from "@internationalized/date"; import {useState} from "react"; export function Controlled() { const [value, setValue] = useState(today(getLocalTimeZone())); return (
{(segment) => } {(day) => {day}} {(date) => } {({year}) => } Current value: {value ? value.toString() : "(empty)"}
); } ``` ### Validation ```tsx "use client"; import type {DateValue} from "@internationalized/date"; import {Calendar, DateField, DatePicker, FieldError, Label} from "@heroui/react"; import {getLocalTimeZone, today} from "@internationalized/date"; import {useState} from "react"; export function WithValidation() { const [value, setValue] = useState(null); const currentDate = today(getLocalTimeZone()); const isInvalid = value != null && value.compare(currentDate) < 0; return ( {(segment) => } Date must be today or in the future. {(day) => {day}} {(date) => } {({year}) => } ); } ``` ### Format Options Control how DatePicker values are displayed with props such as `granularity`, `hourCycle`, `hideTimeZone`, and `shouldForceLeadingZeros`. ```tsx "use client"; import type {DateValue} from "@internationalized/date"; import {Calendar, DateField, DatePicker, Label, ListBox, Select, Switch} from "@heroui/react"; import {parseDate, parseZonedDateTime} from "@internationalized/date"; import {useMemo, useState} from "react"; type Granularity = "day" | "hour" | "minute" | "second"; type HourCycle = 12 | 24; const granularityOptions: {label: string; value: Granularity}[] = [ {label: "Day", value: "day"}, {label: "Hour", value: "hour"}, {label: "Minute", value: "minute"}, {label: "Second", value: "second"}, ]; const hourCycleOptions: {label: string; value: HourCycle}[] = [ {label: "12-hour", value: 12}, {label: "24-hour", value: 24}, ]; export function FormatOptions() { const [granularity, setGranularity] = useState("day"); const [hourCycle, setHourCycle] = useState(12); const [hideTimeZone, setHideTimeZone] = useState(false); const [shouldForceLeadingZeros, setShouldForceLeadingZeros] = useState(false); const defaultValue = useMemo(() => { if (granularity === "day") { return parseDate("2025-02-03"); } return parseZonedDateTime("2025-02-03T08:45:00[America/Los_Angeles]"); }, [granularity]); return (
{(segment) => } {(day) => {day}} {(date) => } {({year}) => }
); } ``` ### Disabled ```tsx "use client"; import {Calendar, DateField, DatePicker, Description, Label} from "@heroui/react"; import {getLocalTimeZone, today} from "@internationalized/date"; export function Disabled() { return ( {(segment) => } This date picker is disabled. {(day) => {day}} {(date) => } {({year}) => } ); } ``` ### Custom Indicator `DatePicker.TriggerIndicator` renders the default `IconCalendar` when no children are provided. Pass children to replace it. ```tsx "use client"; import {Calendar, DateField, DatePicker, Description, Label} from "@heroui/react"; import {Icon} from "@iconify/react"; export function WithCustomIndicator() { return ( {(segment) => } Replace the default calendar icon by passing custom children. {(day) => {day}} {(date) => } {({year}) => } ); } ``` ### Form Example ```tsx "use client"; import type {DateValue} from "@internationalized/date"; import { Button, Calendar, DateField, DatePicker, 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 currentDate = today(getLocalTimeZone()); const isInvalid = value != null && value.compare(currentDate) < 0; const handleSubmit = (event: React.FormEvent) => { event.preventDefault(); if (!value || isInvalid) { return; } setIsSubmitting(true); setTimeout(() => { setValue(null); setIsSubmitting(false); }, 1200); }; return (
{(segment) => } {isInvalid ? ( Date must be today or in the future. ) : ( Choose a valid appointment date. )} {(day) => {day}} {(date) => } {({year}) => }
); } ``` ### International Calendar By default, DatePicker displays dates using the calendar system for the user's locale. You can override this by wrapping your DatePicker with `I18nProvider` and setting the [Unicode calendar locale extension](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Intl/Locale/calendar#adding_a_calendar_in_the_locale_string). The example below shows the Indian calendar system: ```tsx "use client"; import {Calendar, DateField, DatePicker, Label} from "@heroui/react"; import {getLocalTimeZone, today} from "@internationalized/date"; import {I18nProvider} from "react-aria-components"; export function InternationalCalendar() { return ( {(segment) => } {(day) => {day}} {(date) => } {({year}) => } ); } ``` **Note:** The `onChange` event always returns a date in the same calendar system as the `value` or `defaultValue` (Gregorian if no value is provided), regardless of the displayed locale. This ensures your application logic works consistently with a single calendar system while still displaying dates in the user's preferred format. For a complete list of supported calendar systems and their identifiers, see: * [React Aria Calendar Implementations](https://react-aria.adobe.com/internationalized/date/Calendar#implementations) * [React Aria International Calendars](https://react-aria.adobe.com/Calendar#international-calendars) ### Custom Render Function ```tsx "use client"; import {Calendar, DateField, DatePicker, Label} from "@heroui/react"; export function CustomRenderFunction() { return (
} >
} >
}> {(segment) => ( } segment={segment} /> )}
); } ``` ### Disabled State ```tsx "use client"; import {Description, Label, TimeField} from "@heroui/react"; import {Time, getLocalTimeZone, now} from "@internationalized/date"; export function Disabled() { const currentTime = now(getLocalTimeZone()); const timeValue = new Time(currentTime.hour, currentTime.minute, currentTime.second); return (
{(segment) => } This time field is disabled {(segment) => } This time field is disabled
); } ``` ### With Icons Add prefix or suffix icons to enhance the time field. ```tsx "use client"; import {Clock} from "@gravity-ui/icons"; import {Label, TimeField} from "@heroui/react"; export function WithPrefixIcon() { return ( {(segment) => } ); } ``` ```tsx "use client"; import {Clock} from "@gravity-ui/icons"; import {Label, TimeField} from "@heroui/react"; export function WithSuffixIcon() { return ( {(segment) => } ); } ``` ```tsx "use client"; import {ChevronDown, Clock} from "@gravity-ui/icons"; import {Description, Label, TimeField} from "@heroui/react"; export function WithPrefixAndSuffix() { return ( {(segment) => } Enter a time ); } ``` ### Full Width ```tsx "use client"; import {ChevronDown, Clock} from "@gravity-ui/icons"; import {Label, TimeField} from "@heroui/react"; export function FullWidth() { return (
{(segment) => } {(segment) => }
); } ``` ### On Surface When used inside a [Surface](/docs/components/surface) component, use `variant="secondary"` on TimeField.Group to apply the lower emphasis variant suitable for surface backgrounds. ```tsx "use client"; import {Clock} from "@gravity-ui/icons"; import {Description, Label, Surface, TimeField} from "@heroui/react"; export function OnSurface() { return ( {(segment) => } Enter a time {(segment) => } Enter a time for your appointment ); } ``` ### Form Example Complete form example with validation and submission handling. ```tsx "use client"; import type {Time} from "@internationalized/date"; import {Clock} from "@gravity-ui/icons"; import {Button, Description, FieldError, Form, Label, TimeField} from "@heroui/react"; import {parseTime} from "@internationalized/date"; import {useState} from "react"; export function FormExample() { const [value, setValue] = useState