# HeroUI v3 > design-principles > Design Principles URL: /docs/design-principles Source: https://raw.githubusercontent.com/heroui-inc/heroui/refs/heads/v3/apps/docs/content/docs/design-principles.mdx Core principles that guide HeroUI v3's design and development *** title: Design Principles description: Core principles that guide HeroUI v3's design and development icon: book ---------- ## Overview HeroUI v3 follows 10 core principles that prioritize clarity, accessibility, customization, and developer experience. ## Core Principles ### 1. Semantic Intent Over Visual Style Components use semantic naming (primary, secondary, tertiary) instead of visual descriptions (solid, flat, bordered). Inspired by [Uber's Base design system](https://base.uber.com/6d2425e9f/p/756216-button), our variants follow a clear hierarchy: ![Semantic Intent Hierarchy](https://heroui-assets.nyc3.cdn.digitaloceanspaces.com/docs/semantic-intent.jpg) ```tsx // ✅ Semantic variants communicate hierarchy ``` | Variant | Purpose | Usage | | ------------- | --------------------------------- | ---------------- | | **Primary** | Main action to move forward | 1 per context | | **Secondary** | Alternative actions | Multiple allowed | | **Tertiary** | Dismissive actions (cancel, skip) | Sparingly | | **Danger** | Destructive actions | When needed | ### 2. Accessibility as Foundation Built on [React Aria Components](https://react-spectrum.adobe.com/react-aria/) for WCAG 2.1 AA compliance, keyboard navigation, and screen reader support. ```tsx // Automatic ARIA attributes, keyboard navigation, and focus management Profile Security Content Content ``` ### 3. Composition Over Configuration Compound components let you rearrange, customize, or omit parts as needed. ```tsx // Compose parts to build exactly what you need Question Text Answer content ``` ### 4. Progressive Disclosure Start simple, add complexity only when needed. ```tsx // Level 1: Minimal // Level 2: Enhanced // Level 3: Advanced ``` ### 5. Predictable Behavior Consistent patterns across all components: sizes (`sm`, `md`, `lg`), variants, className support, and data attributes. ```tsx // All components follow the same patterns ``` or with React: ```tsx // Apply styles to any component import { buttonVariants } from '@heroui/react'; Home ``` ### 8. Developer Experience Excellence Clear APIs, descriptive errors, IntelliSense, AI-friendly markdown docs, and Storybook for visual testing. ### 9. Complete Customization Beautiful defaults out-of-the-box. Transform the entire look with CSS variables or BEM classes. ```css /* Theme-wide changes with variables */ :root { --accent: oklch(0.7 0.25 260); --radius: 0.375rem; --spacing: 0.5rem; } /* Component-specific customization */ @layer components { .button { @apply uppercase tracking-wider; } .button--primary { @apply bg-gradient-to-r from-purple-500 to-pink-500; } } ``` ### 10. Open and Extensible Wrap, extend, and customize components to match your needs. ```tsx // Custom wrapper component const CTAButton = ({ intent = 'primary-cta', children, ref, ...props }: CTAButtonProps) => { const variantMap = { 'primary-cta': 'primary', 'secondary-cta': 'secondary', 'minimal': 'ghost' }; return ( ); }; ``` Or extend with Tailwind Variants: ```tsx import { Button, buttonVariants } from '@heroui/react'; import { tv } from 'tailwind-variants'; // Extend button styles with custom variants const myButtonVariants = tv({ extend: buttonVariants, variants: { variant: { 'primary-cta': 'bg-gradient-to-r from-blue-500 to-purple-600 text-white shadow-lg', 'secondary-cta': 'border-2 border-blue-500 text-blue-500 hover:bg-blue-50', } } }); // Use the custom variants function CustomButton({ variant, className, ...props }) { return ); } ``` ## What's Next? * [Browse Components](/docs/components) - See all available components * [Learn Styling](/docs/handbook/styling) - Customize with Tailwind CSS * [Explore Patterns](/docs/handbook/composition) - Master compound components # HeroUI v3 > components > Accordion URL: /docs/components/accordion Source: https://raw.githubusercontent.com/heroui-inc/heroui/refs/heads/v3/apps/docs/content/docs/components/accordion.mdx A collapsible content panel for organizing information in a compact space *** title: Accordion description: A collapsible content panel for organizing information in a compact space links: rac: Disclosure source: accordion/accordion.tsx styles: accordion.css storybook: accordion figma: true ----------- ## Import ```tsx import { Accordion } from '@heroui/react'; ``` ### Example ### Anatomy Import all parts and piece them together. ```tsx import { Accordion } from '@heroui/react'; export default () => ( ) ``` ### Outline ### Multiple Expanded ### Custom Indicator ### Disabled State ### FAQ Layout ### Custom Styles ## Styling ### Passing Tailwind CSS classes {items.map((item, index) => ( {item.iconUrl ? ( {item.title} ) : null}
{item.title} {item.subtitle}
{item.content}
))} ); }`} /> ### Customizing the component classes To customize the Accordion component classes, you can use the `@layer components` directive.
[Learn more](https://tailwindcss.com/docs/adding-custom-styles#adding-component-classes). ```css @layer components { .accordion { @apply rounded-xl bg-gray-50; } .accordion__trigger { @apply font-semibold text-lg; } .accordion--outline { @apply shadow-lg border-2; } } ``` HeroUI follows the [BEM](https://getbem.com/) methodology to ensure component variants and states are reusable and easy to customize. ### CSS Classes The Accordion component uses these CSS classes ([View source styles](https://github.com/heroui-inc/heroui/blob/v3/packages/styles/components/accordion.css)): #### Base Classes * `.accordion` - Base accordion container * `.accordion__body` - Content body container * `.accordion__heading` - Heading wrapper * `.accordion__indicator` - Expand/collapse indicator icon * `.accordion__item` - Individual accordion item * `.accordion__panel` - Collapsible panel container * `.accordion__trigger` - Clickable trigger button #### Variant Classes * `.accordion--outline` - Outline variant with border and background #### State Classes * `.accordion__trigger[aria-expanded="true"]` - Expanded state * `.accordion__panel[aria-hidden="false"]` - Panel visible state ### Interactive States The component supports both CSS pseudo-classes and data attributes for flexibility: * **Hover**: `:hover` or `[data-hover="true"]` on trigger * **Focus**: `:focus-visible` or `[data-focus-visible="true"]` on trigger * **Disabled**: `:disabled` or `[aria-disabled="true"]` on trigger * **Expanded**: `[aria-expanded="true"]` on trigger ## API Reference ### Accordion Props | Prop | Type | Default | Description | | ------------------------ | -------------------------- | ----------- | ---------------------------------------------- | | `allowsMultipleExpanded` | `boolean` | `false` | Whether multiple items can be expanded at once | | `defaultExpandedKeys` | `Iterable` | - | The initial expanded keys | | `expandedKeys` | `Iterable` | - | The controlled expanded keys | | `onExpandedChange` | `(keys: Set) => void` | - | Handler called when expanded keys change | | `isDisabled` | `boolean` | `false` | Whether the entire accordion is disabled | | `variant` | `"default" \| "outline"` | `"default"` | The visual variant of the accordion | | `className` | `string` | - | Additional CSS classes | | `children` | `ReactNode` | - | The accordion items | ### Accordion.Item Props | Prop | Type | Default | Description | | ------------------ | ------------------------------- | ------- | ---------------------------------- | | `id` | `Key` | - | Unique identifier for the item | | `isDisabled` | `boolean` | `false` | Whether this item is disabled | | `defaultExpanded` | `boolean` | `false` | Whether item is initially expanded | | `isExpanded` | `boolean` | - | Controlled expanded state | | `onExpandedChange` | `(isExpanded: boolean) => void` | - | Handler for expanded state changes | | `className` | `string` | - | Additional CSS classes | | `children` | `ReactNode` | - | The item content | ### Accordion.Trigger Props | Prop | Type | Default | Description | | ------------ | ----------------------------- | ------- | ---------------------------------- | | `className` | `string` | - | Additional CSS classes | | `children` | `ReactNode \| RenderFunction` | - | Trigger content or render function | | `onPress` | `() => void` | - | Additional press handler | | `isDisabled` | `boolean` | - | Whether trigger is disabled | ### Accordion.Panel Props | Prop | Type | Default | Description | | ----------- | ----------- | ------- | ---------------------- | | `className` | `string` | - | Additional CSS classes | | `children` | `ReactNode` | - | Panel content | ### Accordion.Indicator Props | Prop | Type | Default | Description | | ----------- | ----------- | ------- | ---------------------- | | `className` | `string` | - | Additional CSS classes | | `children` | `ReactNode` | - | Custom indicator icon | ### Accordion.Body Props | Prop | Type | Default | Description | | ----------- | ----------- | ------- | ---------------------- | | `className` | `string` | - | Additional CSS classes | | `children` | `ReactNode` | - | Body content | # HeroUI v3 > components > Avatar URL: /docs/components/avatar Source: https://raw.githubusercontent.com/heroui-inc/heroui/refs/heads/v3/apps/docs/content/docs/components/avatar.mdx Display user profile images with customizable fallback content *** title: Avatar description: Display user profile images with customizable fallback content links: radix: avatar source: avatar/avatar.tsx styles: avatar.css storybook: avatar figma: true ----------- ## Import ```tsx import { Avatar } from '@heroui/react'; ``` ### Usage ### Anatomy Import all parts and piece them together. ```tsx import { Avatar } from '@heroui/react'; export default () => ( ) ``` ### Sizes ### Colors ### Fallback Content ### Avatar Group ### Custom Styles ## Styling ### Passing Tailwind CSS classes ```tsx import { Avatar } from '@heroui/react'; function CustomAvatar() { return ( XL ); } ``` ### Customizing the component classes To customize the Avatar component classes, you can use the `@layer components` directive.
[Learn more](https://tailwindcss.com/docs/adding-custom-styles#adding-component-classes). ```css @layer components { .avatar { @apply size-16 border-2 border-primary; } .avatar__fallback { @apply bg-gradient-to-br from-purple-500 to-pink-500; } } ``` HeroUI follows the [BEM](https://getbem.com/) methodology to ensure component variants and states are reusable and easy to customize. ### CSS Classes The Avatar component uses these CSS classes ([View source styles](https://github.com/heroui-inc/heroui/blob/v3/packages/styles/components/avatar.css)): #### Base Classes * `.avatar` - Base container with default size (size-10) * `.avatar__image` - Image element with aspect-square sizing * `.avatar__fallback` - Fallback container with centered content #### Size Modifiers * `.avatar--sm` - Small avatar (size-8) * `.avatar--md` - Medium avatar (default, no additional styles) * `.avatar--lg` - Large avatar (size-12) #### Color Modifiers * `.avatar__fallback--default` - Default text color * `.avatar__fallback--accent` - Accent text color * `.avatar__fallback--success` - Success text color * `.avatar__fallback--warning` - Warning text color * `.avatar__fallback--danger` - Danger text color ## API Reference ### Avatar Props | Prop | Type | Default | Description | | ----------- | ------------------------------------------------------------- | ----------- | ----------------------- | | `size` | `'sm' \| 'md' \| 'lg'` | `'md'` | Avatar size | | `color` | `'default' \| 'accent' \| 'success' \| 'warning' \| 'danger'` | `'default'` | Fallback color theme | | `className` | `string` | - | Additional CSS classes | | `asChild` | `boolean` | `false` | Render as child element | ### Avatar.Image Props | Prop | Type | Default | Description | | ----------------------- | ------------------------------------------------------------------ | ------- | ------------------------------------------------------------------------- | | `src` | `string` | - | Image source URL | | `srcSet` | `string` | - | The image `srcset` attribute for responsive images | | `sizes` | `string` | - | The image `sizes` attribute for responsive images | | `alt` | `string` | - | Alternative text for the image | | `onLoad` | `(event: SyntheticEvent) => void` | - | Callback when the image loads successfully | | `onError` | `(event: SyntheticEvent) => void` | - | Callback when there's an error loading the image | | `onLoadingStatusChange` | `(status: 'loading' \| 'loaded' \| 'pending' \| 'failed') => void` | - | Callback for loading status changes | | `ignoreFallback` | `boolean` | `false` | If `true`, opt out of the fallback logic and use as regular `img` | | `shouldBypassImageLoad` | `boolean` | `false` | If `true`, image load will be bypassed and handled by `asChild` component | | `crossOrigin` | `'anonymous' \| 'use-credentials'` | - | CORS setting for the image request | | `loading` | `'eager' \| 'lazy'` | - | Native lazy loading attribute | | `className` | `string` | - | Additional CSS classes | | `asChild` | `boolean` | `false` | Render as child element | ### Avatar.Fallback Props | Prop | Type | Default | Description | | ----------- | ------------------------------------------------------------- | ------- | ---------------------------------------------- | | `delayMs` | `number` | - | Delay before showing fallback (prevents flash) | | `color` | `'default' \| 'accent' \| 'success' \| 'warning' \| 'danger'` | - | Override color from parent | | `className` | `string` | - | Additional CSS classes | | `asChild` | `boolean` | `false` | Render as child element | # HeroUI v3 > components > Button URL: /docs/components/button Source: https://raw.githubusercontent.com/heroui-inc/heroui/refs/heads/v3/apps/docs/content/docs/components/button.mdx A clickable button component with multiple variants and states *** title: Button description: A clickable button component with multiple variants and states links: rac: Button source: button/button.tsx styles: button.css storybook: button figma: true ----------- ## Import ```tsx import { Button } from '@heroui/react'; ``` ### Usage ### Variants ### With Icons ### Icon Only ### Loading ### Loading State ### Sizes ### Disabled State ### Social Buttons ## 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. ### CSS Classes The Button component uses these CSS classes ([View source styles](https://github.com/heroui-inc/heroui/blob/v3/packages/styles/components/button.css)): #### Base & Size Classes * `.button` - Base button styles * `.button--sm` - Small size variant * `.button--md` - Medium size variant * `.button--lg` - Large size variant #### Variant Classes * `.button--primary` * `.button--secondary` * `.button--tertiary` * `.button--ghost` * `.button--danger` #### Modifier Classes * `.button--icon-only` * `.button--icon-only.button--sm` * `.button--icon-only.button--lg` ### Interactive States The button supports both CSS pseudo-classes and data attributes for flexibility: * **Hover**: `:hover` or `[data-hover="true"]` * **Active/Pressed**: `:active` or `[data-pressed="true"]` (includes scale transform) * **Focus**: `:focus-visible` or `[data-focus-visible="true"]` (shows focus ring) * **Disabled**: `:disabled` or `[aria-disabled="true"]` (reduced opacity, no pointer events) * **Pending**: `[data-pending]` (no pointer events during loading) ## API Reference ### Button Props | Prop | Type | Default | Description | | ------------ | ------------------------------------------------------------------- | ----------- | ----------------------------------------- | | `variant` | `'primary' \| 'secondary' \| 'tertiary' \| 'ghost' \| 'danger'` | `'primary'` | Visual style variant | | `size` | `'sm' \| 'md' \| 'lg'` | `'md'` | Size of the button | | `isDisabled` | `boolean` | `false` | Whether the button is disabled | | `isPending` | `boolean` | `false` | Whether the button is in a loading state | | `isIconOnly` | `boolean` | `false` | Whether the button contains only an icon | | `onPress` | `(e: PressEvent) => void` | - | Handler called when the button is pressed | | `children` | `React.ReactNode \| (values: ButtonRenderProps) => React.ReactNode` | - | Button content or render prop | ### ButtonRenderProps When using the render prop pattern, these values are provided: | Prop | Type | Description | | ---------------- | --------- | ---------------------------------------------- | | `isPending` | `boolean` | Whether the button is in a loading state | | `isPressed` | `boolean` | Whether the button is currently pressed | | `isHovered` | `boolean` | Whether the button is hovered | | `isFocused` | `boolean` | Whether the button is focused | | `isFocusVisible` | `boolean` | Whether the button should show focus indicator | | `isDisabled` | `boolean` | Whether the button is disabled | # HeroUI v3 > components > Chip URL: /docs/components/chip Source: https://raw.githubusercontent.com/heroui-inc/heroui/refs/heads/v3/apps/docs/content/docs/components/chip.mdx Small informational badges for displaying labels, statuses, and categories *** title: Chip description: Small informational badges for displaying labels, statuses, and categories links: source: chip/chip.tsx styles: chip.css storybook: chip figma: true ----------- ## Import ```tsx import { Chip } from '@heroui/react'; ``` ### Usage ### Variants ### With Icons ### Statuses ## Styling ### Passing Tailwind CSS classes ```tsx import {Chip} from '@heroui/react'; function CustomChip() { return ( Custom Styled ); } ``` ### Customizing the component classes To customize the Chip component classes, you can use the `@layer components` directive.
[Learn more](https://tailwindcss.com/docs/adding-custom-styles#adding-component-classes). ```css @layer components { .chip { @apply rounded-full text-xs; } .chip--accent { @apply border-accent/20; } } ``` HeroUI follows the [BEM](https://getbem.com/) methodology to ensure component variants and states are reusable and easy to customize. ### CSS Classes The Chip component uses these CSS classes ([View source styles](https://github.com/heroui-inc/heroui/blob/v3/packages/styles/components/chip.css)): #### Base Classes * `.chip` - Base chip styles #### Color Classes * `.chip--accent` - Accent color variant * `.chip--danger` - Danger color variant * `.chip--default` - Default color variant * `.chip--success` - Success color variant * `.chip--warning` - Warning color variant #### Variant Classes * `.chip--primary` - Primary variant with filled background * `.chip--secondary` - Secondary variant with border * `.chip--tertiary` - Tertiary variant with transparent background #### Compound Variant Classes * `.chip--primary.chip--accent` - Primary accent combination * `.chip--primary.chip--success` - Primary success combination * `.chip--primary.chip--warning` - Primary warning combination * `.chip--primary.chip--danger` - Primary danger combination ### Interactive States The component supports focus visibility: * **Focus**: `:focus-visible` or `[data-focus-visible="true"]` ## API Reference ### Chip Props | Prop | Type | Default | Description | | ----------- | ------------------------------------------------------------- | ------------- | ---------------------------------- | | `children` | `React.ReactNode` | - | Content to display inside the chip | | `className` | `string` | - | Additional CSS classes | | `color` | `"default" \| "accent" \| "success" \| "warning" \| "danger"` | `"default"` | Color variant of the chip | | `variant` | `"primary" \| "secondary" \| "tertiary"` | `"secondary"` | Visual style variant | # HeroUI v3 > components > Disclosure URL: /docs/components/disclosure Source: https://raw.githubusercontent.com/heroui-inc/heroui/refs/heads/v3/apps/docs/content/docs/components/disclosure.mdx A disclosure is a collapsible section with a header containing a heading and a trigger button, and a panel that wraps the content. *** title: Disclosure description: A disclosure is a collapsible section with a header containing a heading and a trigger button, and a panel that wraps the content. links: rac: Disclosure source: disclosure/disclosure.tsx styles: disclosure.css storybook: disclosure figma: true ----------- ## Import ```tsx import {Disclosure} from '@heroui/react'; ``` ### Usage ### Anatomy Import all parts and piece them together. ```tsx import { Disclosure } from '@heroui/react'; export default () => ( ) ``` ## Styling ### Passing Tailwind CSS classes ```tsx import { Disclosure } from '@heroui/react'; function CustomDisclosure() { return ( Click to expand Hidden content ); } ``` ### Customizing the component classes To customize the Disclosure component classes, you can use the `@layer components` directive.
[Learn more](https://tailwindcss.com/docs/adding-custom-styles#adding-component-classes). ```css @layer components { .disclosure { @apply relative; } .disclosure__trigger { @apply cursor-pointer; } .disclosure__indicator { @apply transition-transform duration-300; } .disclosure__content { @apply overflow-hidden transition-all; } } ``` HeroUI follows the [BEM](https://getbem.com/) methodology to ensure component variants and states are reusable and easy to customize. ### CSS Classes The Disclosure component uses these CSS classes ([View source styles](https://github.com/heroui-inc/heroui/blob/v3/packages/styles/components/disclosure.css)): #### Base Classes * `.disclosure` - Base container styles * `.disclosure__heading` - Heading wrapper * `.disclosure__trigger` - Trigger button styles * `.disclosure__indicator` - Chevron indicator styles * `.disclosure__content` - Content container with animations ### Interactive States The component supports both CSS pseudo-classes and data attributes for flexibility: * **Expanded**: `[data-expanded="true"]` on indicator for rotation * **Focus**: `:focus-visible` or `[data-focus-visible="true"]` on trigger * **Disabled**: `:disabled` or `[aria-disabled="true"]` on trigger * **Hidden**: `[aria-hidden="false"]` on content for visibility ## API Reference ### Disclosure Props | Prop | Type | Default | Description | | ------------------ | ------------------------------- | ------- | ------------------------------------ | | `isExpanded` | `boolean` | `false` | Controls the expanded state | | `onExpandedChange` | `(isExpanded: boolean) => void` | - | Callback when expanded state changes | | `isDisabled` | `boolean` | `false` | Whether the disclosure is disabled | | `children` | `ReactNode \| RenderFunction` | - | Content to render | | `className` | `string` | - | Additional CSS classes | ### Disclosure.Trigger Props | Prop | Type | Default | Description | | ----------- | ----------------------------- | ----------- | ------------------------ | | `children` | `ReactNode \| RenderFunction` | - | Trigger content | | `className` | `string` | - | Additional CSS classes | | `slot` | `string` | `"trigger"` | Slot name for React Aria | ### Disclosure.Content Props | Prop | Type | Default | Description | | ----------- | ----------- | ------- | ---------------------- | | `children` | `ReactNode` | - | Content to show/hide | | `className` | `string` | - | Additional CSS classes | ### Disclosure.Indicator Props | Prop | Type | Default | Description | | ----------- | -------------- | --------------------- | ------------------------ | | `children` | `ReactElement` | `` | Custom indicator element | | `className` | `string` | - | Additional CSS classes | ### RenderProps When using the render prop pattern, these values are provided: | Prop | Type | Description | | ------------ | --------- | ------------------------------ | | `isExpanded` | `boolean` | Current expanded state | | `isDisabled` | `boolean` | Whether disclosure is disabled | # HeroUI v3 > components > Kbd URL: /docs/components/kbd Source: https://raw.githubusercontent.com/heroui-inc/heroui/refs/heads/v3/apps/docs/content/docs/components/kbd.mdx Display keyboard shortcuts and key combinations *** title: Kbd description: Display keyboard shortcuts and key combinations links: source: kbd/kbd.tsx styles: kbd.css storybook: kbd figma: true ----------- ## Import ```tsx import {Kbd} from "@heroui/react"; ``` ### Usage ### Anatomy Import all parts and piece them together. ```tsx import {Kbd} from "@heroui/react"; export default () => ( K ); ``` ### Navigation Keys ### Inline Usage ### Instructional Text ### Special Keys ## Styling ### Passing Tailwind CSS classes ```tsx import {Kbd} from "@heroui/react"; function CustomKbd() { return ( K ); } ``` ### Customizing the component classes To customize the Kbd component classes, you can use the `@layer components` directive.
[Learn more](https://tailwindcss.com/docs/adding-custom-styles#adding-component-classes). ```css @layer components { .kbd { @apply bg-gray-100 dark:bg-gray-800 border-gray-300; } .kbd__abbr { @apply font-bold; } .kbd__content { @apply text-sm; } } ``` HeroUI follows the [BEM](https://getbem.com/) methodology to ensure component variants and states are reusable and easy to customize. ### CSS Classes The Kbd component uses these CSS classes ([View source styles](https://github.com/heroui-inc/heroui/blob/v3/packages/styles/components/kbd.css)): #### Base Classes * `.kbd` - Base keyboard key styles with background, border, and spacing * `.kbd__abbr` - Abbreviation element for modifier keys * `.kbd__content` - Content wrapper for key text ## API Reference ### Kbd Props | Prop | Type | Default | Description | | ----------- | ----------------- | ------- | ------------------ | | `children` | `React.ReactNode` | - | Content of the key | | `className` | `string` | - | Custom CSS classes | ### Kbd.Abbr Props | Prop | Type | Default | Description | | ----------- | -------- | ------- | ------------------------------------------------------------------------------------ | | `keyValue` | `KbdKey` | - | The keyboard key to display. Available values include modifier keys and special keys | | `className` | `string` | - | Custom CSS classes | ### Kbd.Content Props | Prop | Type | Default | Description | | ----------- | ----------------- | ------- | ----------------------- | | `children` | `React.ReactNode` | - | Text content of the key | | `className` | `string` | - | Custom CSS classes | ### KbdKey Type Available key values for the `keyValue` prop: | Modifier Keys | Special Keys | Navigation Keys | Function Keys | | ------------- | ------------ | --------------- | ------------- | | `command` | `enter` | `up` | `fn` | | `shift` | `delete` | `down` | | | `ctrl` | `escape` | `left` | | | `option` | `tab` | `right` | | | `alt` | `space` | `pageup` | | | `win` | `capslock` | `pagedown` | | | | `help` | `home` | | | | | `end` | | # HeroUI v3 > components > Link URL: /docs/components/link Source: https://raw.githubusercontent.com/heroui-inc/heroui/refs/heads/v3/apps/docs/content/docs/components/link.mdx A styled anchor component for navigation with built-in icon support *** title: Link description: A styled anchor component for navigation with built-in icon support links: rac: Link source: link/link.tsx styles: link.css storybook: link figma: true ----------- ## Import ```tsx import { Link } from '@heroui/react'; ``` ### Usage ### With Icons ## Styling ### Passing Tailwind CSS classes ```tsx import {Link} from '@heroui/react'; function CustomLink() { return ( Custom styled link ); } ``` ### Customizing the component classes To customize the Link component classes, you can use the `@layer components` directive.
[Learn more](https://tailwindcss.com/docs/adding-custom-styles#adding-component-classes). ```css @layer components { .link { @apply font-semibold no-underline hover:underline; } } ``` HeroUI follows the [BEM](https://getbem.com/) methodology to ensure component variants and states are reusable and easy to customize. ### CSS Classes The Link component uses these CSS classes ([View source styles](https://github.com/heroui-inc/heroui/blob/v3/packages/styles/components/link.css)): #### Base Classes * `.link` - Base link styles with underline on hover ### Interactive States The component supports both CSS pseudo-classes and data attributes for flexibility: * **Focus**: `:focus-visible` or `[data-focus-visible="true"]` * **Disabled**: `:disabled` or `[aria-disabled="true"]` ## API Reference ### Link Props | Prop | Type | Default | Description | | --------------- | ------------------------- | ------- | -------------------------------------------------- | | `href` | `string` | - | URL for navigation | | `target` | `string` | - | Specifies where to open the linked document | | `rel` | `string` | - | Specifies the relationship between documents | | `isDisabled` | `boolean` | `false` | Disables link interaction | | `showIcon` | `boolean` | `false` | Shows the link icon | | `iconPlacement` | `"start" \| "end"` | `"end"` | Position of the icon | | `className` | `string` | - | Additional CSS classes | | `children` | `React.ReactNode` | - | Link content | | `onPress` | `(e: PressEvent) => void` | - | Handler called when the link is pressed | | `autoFocus` | `boolean` | - | Whether the element should receive focus on render | ### Link.Icon Props | Prop | Type | Default | Description | | ----------- | ----------------- | ------- | ------------------------------ | | `asChild` | `boolean` | `false` | Merge props with child element | | `children` | `React.ReactNode` | - | Custom icon element | | `className` | `string` | - | Additional CSS classes | # HeroUI v3 > components > Popover URL: /docs/components/popover Source: https://raw.githubusercontent.com/heroui-inc/heroui/refs/heads/v3/apps/docs/content/docs/components/popover.mdx Displays rich content in a portal triggered by a button or any custom element *** title: Popover description: Displays rich content in a portal triggered by a button or any custom element links: rac: Popover source: popover/popover.tsx styles: popover.css storybook: popover ------------------ ## Import ```tsx import { Popover } from '@heroui/react'; ``` ### Usage ### Anatomy Import all parts and piece them together. ```tsx import { Popover } from '@heroui/react'; export default () => ( {/* content goes here */} ) ``` ### With Arrow ### Placement ### Interactive Content ## Styling ### Passing Tailwind CSS classes ```tsx import {Popover, Button} from '@heroui/react'; function CustomPopover() { return ( Custom Styled

This popover has custom styling

); } ``` ### Customizing the component classes To customize the Popover component classes, you can use the `@layer components` directive.
[Learn more](https://tailwindcss.com/docs/adding-custom-styles#adding-component-classes). ```css @layer components { .popover { @apply rounded-xl shadow-2xl; } .popover__dialog { @apply p-4; } .popover__heading { @apply text-lg font-bold; } } ``` HeroUI follows the [BEM](https://getbem.com/) methodology to ensure component variants and states are reusable and easy to customize. ### CSS Classes The Popover component uses these CSS classes ([View source styles](https://github.com/heroui-inc/heroui/blob/v3/packages/styles/components/popover.css)): #### Base Classes * `.popover` - Base popover container styles * `.popover__dialog` - Dialog content wrapper * `.popover__heading` - Heading text styles * `.popover__trigger` - Trigger element styles ### Interactive States The component supports animation states: * **Entering**: `[data-entering]` - Applied during popover appearance * **Exiting**: `[data-exiting]` - Applied during popover disappearance * **Placement**: `[data-placement="*"]` - Applied based on popover position * **Focus**: `:focus-visible` or `[data-focus-visible="true"]` ## API Reference ### Popover Props | Prop | Type | Default | Description | | -------------- | --------------------------- | ------- | ---------------------------------------- | | `children` | `React.ReactNode` | - | Trigger and content elements | | `isOpen` | `boolean` | - | Controls popover visibility (controlled) | | `defaultOpen` | `boolean` | `false` | Initial open state (uncontrolled) | | `onOpenChange` | `(isOpen: boolean) => void` | - | Called when open state changes | ### Popover.Content Props | Prop | Type | Default | Description | | ------------ | ------------------------------------------------------- | ---------- | --------------------------------------------- | | `children` | `React.ReactNode` | - | Content to display in the popover | | `placement` | `"top" \| "bottom" \| "left" \| "right"` (and variants) | `"bottom"` | Placement of the popover | | `offset` | `number` | `8` | Distance from the trigger element | | `shouldFlip` | `boolean` | `true` | Whether popover can change orientation to fit | | `className` | `string` | - | Additional CSS classes | ### Popover.Dialog Props | Prop | Type | Default | Description | | ----------- | ----------------- | ------- | ---------------------- | | `children` | `React.ReactNode` | - | Dialog content | | `className` | `string` | - | Additional CSS classes | ### Popover.Trigger Props | Prop | Type | Default | Description | | ----------- | ----------------- | ------- | --------------------------------- | | `children` | `React.ReactNode` | - | Element that triggers the popover | | `className` | `string` | - | Additional CSS classes | ### Popover.Heading Props | Prop | Type | Default | Description | | ----------- | ----------------- | ------- | ---------------------- | | `children` | `React.ReactNode` | - | Heading text content | | `className` | `string` | - | Additional CSS classes | ### Popover.Arrow Props | Prop | Type | Default | Description | | ----------- | ----------------- | ------- | ---------------------- | | `children` | `React.ReactNode` | - | Custom arrow element | | `className` | `string` | - | Additional CSS classes | # HeroUI v3 > components > Separator URL: /docs/components/separator Source: https://raw.githubusercontent.com/heroui-inc/heroui/refs/heads/v3/apps/docs/content/docs/components/separator.mdx Visually divide content sections *** title: Separator description: Visually divide content sections links: rac: Separator source: separator/separator.tsx styles: separator.css storybook: separator figma: true ----------- ## Import ```tsx import { Separator } from '@heroui/react'; ``` ### Usage ### Vertical ### With Content ## Styling ### Passing Tailwind CSS classes ```tsx import {Separator} from '@heroui/react'; function CustomSeparator() { return ( ); } ``` ### Customizing the component classes To customize the Separator component classes, you can use the `@layer components` directive.
[Learn more](https://tailwindcss.com/docs/adding-custom-styles#adding-component-classes). ```css @layer components { .separator { @apply bg-accent h-[2px]; } .separator--vertical { @apply bg-accent w-[2px]; } } ``` HeroUI follows the [BEM](https://getbem.com/) methodology to ensure component variants and states are reusable and easy to customize. ### CSS Classes The Separator component uses these CSS classes ([View source styles](https://github.com/heroui-inc/heroui/blob/v3/packages/styles/components/separator.css)): #### Base & Orientation Classes * `.separator` - Base separator styles with default horizontal orientation * `.separator--horizontal` - Horizontal orientation (full width, 1px height) * `.separator--vertical` - Vertical orientation (full height, 1px width) ## API Reference ### Separator Props | Prop | Type | Default | Description | | ------------- | ---------------------------- | -------------- | -------------------------------- | | `orientation` | `'horizontal' \| 'vertical'` | `'horizontal'` | The orientation of the separator | | `className` | `string` | - | Additional CSS classes | # HeroUI v3 > components > Skeleton URL: /docs/components/skeleton Source: https://raw.githubusercontent.com/heroui-inc/heroui/refs/heads/v3/apps/docs/content/docs/components/skeleton.mdx Skeleton is a placeholder to show a loading state and the expected shape of a component. *** title: Skeleton description: Skeleton is a placeholder to show a loading state and the expected shape of a component. links: source: skeleton/skeleton.tsx styles: skeleton.css storybook: skeleton figma: true ----------- ## Import ```tsx import { Skeleton } from '@heroui/react'; ``` ### Usage ### Text Content ### User Profile ### List Items ## Styling ### Passing Tailwind CSS classes ```tsx import { Skeleton } from '@heroui/react'; function CustomSkeleton() { return ( ); } ``` ### Customizing the component classes To customize the Skeleton component classes, you can use the `@layer components` directive.
[Learn more](https://tailwindcss.com/docs/adding-custom-styles#adding-component-classes). ```css @layer components { .skeleton { @apply bg-gray-200; } .skeleton:before { @apply via-gray-100; } } ``` HeroUI follows the [BEM](https://getbem.com/) methodology to ensure component variants and states are reusable and easy to customize. ### CSS Classes The Skeleton component uses these CSS classes ([View source styles](https://github.com/heroui-inc/heroui/blob/v3/packages/styles/components/skeleton.css)): #### Base Class `.skeleton` - Base skeleton styles with shimmer animation ### Animation The shimmer effect is created using a CSS gradient animation that moves across the skeleton element: ```css .skeleton { @apply bg-surface-3 pointer-events-none relative overflow-hidden rounded-md; &:before { @apply animate-skeleton via-surface-2 absolute inset-0 -translate-x-full bg-gradient-to-r from-transparent to-transparent content-['']; } } @theme inline { --animate-skeleton: skeleton 2s linear infinite; @keyframes skeleton { 100% { transform: translateX(200%); } } } ``` ## API Reference ### Skeleton Props | Prop | Type | Default | Description | | ----------- | ----------- | ------- | ---------------------- | | `className` | `string` | - | Additional CSS classes | | `children` | `ReactNode` | - | Optional child content | # HeroUI v3 > components > Spinner URL: /docs/components/spinner Source: https://raw.githubusercontent.com/heroui-inc/heroui/refs/heads/v3/apps/docs/content/docs/components/spinner.mdx A loading indicator component to show pending states *** title: Spinner description: A loading indicator component to show pending states links: source: spinner/spinner.tsx styles: spinner.css storybook: spinner figma: true ----------- ## Import ```tsx import { Spinner } from '@heroui/react'; ``` ### Usage ### Colors ### Sizes ## Styling ### Passing Tailwind CSS classes ```tsx import {Spinner} from '@heroui/react'; function CustomSpinner() { return ( ); } ``` ### Customizing the component classes To customize the Spinner component classes, you can use the `@layer components` directive.
[Learn more](https://tailwindcss.com/docs/adding-custom-styles#adding-component-classes). ```css @layer components { .spinner { @apply animate-spin; } .spinner--accent { color: var(--accent); } } ``` HeroUI follows the [BEM](https://getbem.com/) methodology to ensure component variants and states are reusable and easy to customize. ### CSS Classes The Spinner component uses these CSS classes ([View source styles](https://github.com/heroui-inc/heroui/blob/v3/packages/styles/components/spinner.css)): #### Base & Size Classes * `.spinner` - Base spinner styles with default size * `.spinner--sm` - Small size variant * `.spinner--md` - Medium size variant (default) * `.spinner--lg` - Large size variant * `.spinner--xl` - Extra large size variant #### Color Classes * `.spinner--current` - Inherits current text color * `.spinner--accent` - Accent color variant * `.spinner--danger` - Danger color variant * `.spinner--success` - Success color variant * `.spinner--warning` - Warning color variant ## API Reference ### Spinner Props | Prop | Type | Default | Description | | ----------- | ------------------------------------------------------------- | ----------- | ---------------------------- | | `size` | `"sm" \| "md" \| "lg" \| "xl"` | `"md"` | Size of the spinner | | `color` | `"current" \| "accent" \| "success" \| "warning" \| "danger"` | `"current"` | Color variant of the spinner | | `className` | `string` | - | Additional CSS classes | # HeroUI v3 > components > Tabs URL: /docs/components/tabs Source: https://raw.githubusercontent.com/heroui-inc/heroui/refs/heads/v3/apps/docs/content/docs/components/tabs.mdx Tabs organize content into multiple sections and allow users to navigate between them. *** title: Tabs description: Tabs organize content into multiple sections and allow users to navigate between them. links: rac: Tabs source: tabs/tabs.tsx styles: tabs.css storybook: tabs figma: true ----------- ## Import ```tsx import { Tabs } from '@heroui/react'; ``` ### Usage ### Anatomy Import all parts and piece them together. ```tsx import { Tabs } from '@heroui/react'; export default () => ( ) ``` ### Vertical ### Disabled Tab ### Custom Styles ## Styling ### Passing Tailwind CSS classes Daily Weekly Bi-Weekly Monthly

Daily

Manage your daily tasks and goals.

Weekly

Manage your weekly tasks and goals.

Bi-Weekly

Manage your bi-weekly tasks and goals.

Monthly

Manage your monthly tasks and goals.

); } `} /> ### CSS Classes The Tabs component uses these CSS classes: #### Base Classes * `.tabs` - Base tabs container * `.tabs__list-wrapper` - Tab list wrapper * `.tabs__list` - Tab list container * `.tabs__tab` - Individual tab button * `.tabs__panel` - Tab panel content * `.tabs__indicator` - Tab indicator #### Orientation Attributes * `.tabs[data-orientation="horizontal"]` - Horizontal tab layout (default) * `.tabs[data-orientation="vertical"]` - Vertical tab layout ### Interactive States The component supports both CSS pseudo-classes and data attributes: * **Selected**: `[aria-selected="true"]` * **Hover**: `:hover` or `[data-hover="true"]` * **Focus**: `:focus-visible` or `[data-focus-visible="true"]` * **Disabled**: `[aria-disabled="true"]` ## API Reference ### Tabs Props | Prop | Type | Default | Description | | -------------------- | ---------------------------- | -------------- | --------------------------- | | `orientation` | `"horizontal" \| "vertical"` | `"horizontal"` | Tab layout orientation | | `selectedKey` | `string` | - | Controlled selected tab key | | `defaultSelectedKey` | `string` | - | Default selected tab key | | `onSelectionChange` | `(key: Key) => void` | - | Selection change handler | | `className` | `string` | - | Additional CSS classes | ### Tabs.List Props | Prop | Type | Default | Description | | ------------ | -------- | ------- | -------------------------------- | | `aria-label` | `string` | - | Accessibility label for tab list | | `className` | `string` | - | Additional CSS classes | ### Tabs.Tab Props | Prop | Type | Default | Description | | ------------ | --------- | ------- | ----------------------- | | `id` | `string` | - | Unique tab identifier | | `isDisabled` | `boolean` | `false` | Whether tab is disabled | | `className` | `string` | - | Additional CSS classes | ### Tabs.Panel Props | Prop | Type | Default | Description | | ----------- | -------- | ------- | -------------------------------- | | `id` | `string` | - | Panel identifier matching tab id | | `className` | `string` | - | Additional CSS classes | # HeroUI v3 > components > TextField URL: /docs/components/text-field Source: https://raw.githubusercontent.com/heroui-inc/heroui/refs/heads/v3/apps/docs/content/docs/components/text-field.mdx Text input fields for forms with labels, descriptions, and error messages *** title: TextField description: Text input fields for forms with labels, descriptions, and error messages links: rac: TextField source: text-field/text-field.tsx styles: text-field.css storybook: text-field figma: true ----------- ## Import ```tsx import { TextField } from '@heroui/react'; ``` ### Usage ### Anatomy Import all parts and piece them together. ```tsx import { TextField } from '@heroui/react'; export default () => ( Field label Helper text for the field Error message when invalid ) ``` ### With Description ### Required Field ### With Error ### Disabled State ### TextArea ### Input Types ## Styling ### Passing Tailwind CSS classes ```tsx import { TextField } from '@heroui/react'; function CustomTextField() { return ( Custom styled field With custom styles ); } ``` ### CSS Classes The TextField component uses these CSS classes: #### Base Classes * `.text-field` - Base container styles * `.text-field__label` - Label element styles * `.text-field__input` - Input element styles * `.text-field__textarea` - TextArea element styles * `.text-field__description` - Description text styles * `.text-field__error` - Error message styles #### State Classes * `.text-field--disabled` - Disabled state styles * `.text-field--invalid` - Invalid/error state styles * `.text-field--required` - Required field styles ### Interactive States The component supports both CSS pseudo-classes and data attributes: * **Focus**: `:focus` or `[data-focus="true"]` * **Focus Within**: `:focus-within` or `[data-focus-within="true"]` * **Invalid**: `:invalid` or `[aria-invalid="true"]` * **Disabled**: `:disabled` or `[aria-disabled="true"]` * **Required**: `:required` or `[aria-required="true"]` ## Accessibility #### Keyboard Navigation * **Tab** - Move focus to the input field * **Shift + Tab** - Move focus to the previous element * **Arrow keys** - Navigate within textarea content #### Screen Reader Support * Labels are properly associated with input fields * Required fields are announced * Error messages are announced when present * Descriptions provide additional context * Invalid state is communicated via ARIA attributes #### Focus Management * Clear focus indicators on interactive elements * Focus moves naturally through form fields * Error messages receive focus when validation fails ## API Reference ### TextField Props | Prop | Type | Default | Description | | ------------ | --------- | ------- | ----------------------------- | | `isRequired` | `boolean` | `false` | Whether the field is required | | `isInvalid` | `boolean` | `false` | Whether the field is invalid | | `isDisabled` | `boolean` | `false` | Whether the field is disabled | | `className` | `string` | - | Additional CSS classes | ### TextField.Label Props | Prop | Type | Default | Description | | ----------- | -------- | ------- | ---------------------- | | `className` | `string` | - | Additional CSS classes | ### TextField.Input Props | Prop | Type | Default | Description | | ------------- | ------------------------- | -------- | ---------------------------------------- | | `type` | `string` | `"text"` | Input type (text, email, password, etc.) | | `placeholder` | `string` | - | Placeholder text | | `value` | `string` | - | Input value | | `onChange` | `(value: string) => void` | - | Change handler | | `className` | `string` | - | Additional CSS classes | ### TextField.TextArea Props | Prop | Type | Default | Description | | ------------- | ------------------------- | ------- | ---------------------------- | | `rows` | `number` | `3` | Number of visible text lines | | `placeholder` | `string` | - | Placeholder text | | `value` | `string` | - | TextArea value | | `onChange` | `(value: string) => void` | - | Change handler | | `className` | `string` | - | Additional CSS classes | ### TextField.Description Props | Prop | Type | Default | Description | | ----------- | -------- | ------- | ---------------------- | | `className` | `string` | - | Additional CSS classes | ### TextField.Error Props | Prop | Type | Default | Description | | ----------- | -------- | ------- | ---------------------- | | `className` | `string` | - | Additional CSS classes | # HeroUI v3 > components > Tooltip URL: /docs/components/tooltip Source: https://raw.githubusercontent.com/heroui-inc/heroui/refs/heads/v3/apps/docs/content/docs/components/tooltip.mdx Displays informative text when users hover over or focus on an element *** title: Tooltip description: Displays informative text when users hover over or focus on an element links: rac: Tooltip source: tooltip/tooltip.tsx styles: tooltip.css storybook: tooltip figma: true ----------- ## Import ```tsx import { Tooltip } from '@heroui/react'; ``` ### Usage ### Anatomy Import all parts and piece them together. ```tsx import { Tooltip } from '@heroui/react'; export default () => ( Helpful information about this element ) ``` ### With Arrow ### Placement ### Custom Triggers ## Styling ### Passing Tailwind CSS classes ```tsx import {Tooltip, Button} from '@heroui/react'; function CustomTooltip() { return (

Custom styled tooltip

); } ``` ### Customizing the component classes To customize the Tooltip component classes, you can use the `@layer components` directive.
[Learn more](https://tailwindcss.com/docs/adding-custom-styles#adding-component-classes). ```css @layer components { .tooltip { @apply rounded-xl shadow-lg; } .tooltip__trigger { @apply cursor-help; } } ``` HeroUI follows the [BEM](https://getbem.com/) methodology to ensure component variants and states are reusable and easy to customize. ### CSS Classes The Tooltip component uses these CSS classes ([View source styles](https://github.com/heroui-inc/heroui/blob/v3/packages/styles/components/tooltip.css)): #### Base Classes * `.tooltip` - Base tooltip styles with animations * `.tooltip__trigger` - Trigger element styles ### Interactive States The component supports animation states: * **Entering**: `[data-entering]` - Applied during tooltip appearance * **Exiting**: `[data-exiting]` - Applied during tooltip disappearance * **Placement**: `[data-placement="*"]` - Applied based on tooltip position ## API Reference ### Tooltip Props | Prop | Type | Default | Description | | ------------ | -------------------- | --------- | -------------------------------------------- | | `children` | `React.ReactNode` | - | Trigger element and content | | `delay` | `number` | `700` | Delay in milliseconds before showing tooltip | | `closeDelay` | `number` | `0` | Delay in milliseconds before hiding tooltip | | `trigger` | `"hover" \| "focus"` | `"hover"` | How the tooltip is triggered | | `isDisabled` | `boolean` | `false` | Whether the tooltip is disabled | ### Tooltip.Content Props | Prop | Type | Default | Description | | ----------- | ------------------------------------------------------- | ------------------ | ----------------------------------- | | `children` | `React.ReactNode` | - | Content to display in the tooltip | | `showArrow` | `boolean` | `false` | Whether to show the arrow indicator | | `offset` | `number` | `3` (7 with arrow) | Distance from the trigger element | | `placement` | `"top" \| "bottom" \| "left" \| "right"` (and variants) | `"top"` | Placement of the tooltip | | `className` | `string` | - | Additional CSS classes | ### Tooltip.Trigger Props | Prop | Type | Default | Description | | ----------- | ----------------- | ------- | --------------------------------- | | `children` | `React.ReactNode` | - | Element that triggers the tooltip | | `className` | `string` | - | Additional CSS classes | ### Tooltip.Arrow Props | Prop | Type | Default | Description | | ----------- | ----------------- | ------- | ---------------------- | | `children` | `React.ReactNode` | - | Custom arrow element | | `className` | `string` | - | Additional CSS classes | # HeroUI v3 > handbook > Animation URL: /docs/handbook/animation Source: https://raw.githubusercontent.com/heroui-inc/heroui/refs/heads/v3/apps/docs/content/docs/handbook/animation.mdx Add smooth animations and transitions to HeroUI v3 components *** title: Animation description: Add smooth animations and transitions to HeroUI v3 components icon: copy-transparent ---------------------- ## Overview HeroUI components are built on React Aria and support multiple animation approaches: * **Built-in animations** - Components come with default CSS transitions * **CSS animations** - Customize with Tailwind utilities or custom CSS * **JavaScript libraries** - Integrate with Framer Motion, React Spring, etc. ## Built-in Animations HeroUI components use data attributes to expose their state for animation: ```css /* Popover entrance/exit */ .popover[data-entering] { @apply animate-in zoom-in-90 fade-in-0 duration-200; } .popover[data-exiting] { @apply animate-out zoom-out-95 fade-out duration-150; } /* Button press effect */ .button:active, .button[data-pressed="true"] { transform: scale(0.97); } /* Accordion expansion */ .accordion__panel[aria-hidden="false"] { @apply h-[var(--panel-height)] opacity-100; } ``` ### State Attributes Components expose these states for styling: * `[data-hover="true"]` - Hover state * `[data-pressed="true"]` - Active/pressed state * `[data-focus-visible="true"]` - Keyboard focus * `[data-disabled="true"]` - Disabled state * `[data-entering]` / `[data-exiting]` - Transition states * `[aria-expanded="true"]` - Expanded state ## CSS Animations ### Using Tailwind Utilities ```tsx // Pulse on hover // Fade in entrance Welcome message // Staggered list
Item 1 Item 2
``` ### Custom Transitions Override default component animations: ```css /* Slower accordion */ .accordion__panel { @apply transition-all duration-500; } /* Bouncy button */ .button:active { animation: bounce 0.3s; } @keyframes bounce { 50% { transform: scale(0.95); } } ``` ## Framer Motion HeroUI components work seamlessly with Framer Motion for advanced animations. ### Basic Usage ```tsx import { motion } from 'framer-motion'; import { Button } from '@heroui/react'; const MotionButton = motion(Button); Animated Button ``` ### Entrance Animations ```tsx Welcome! ``` ### Layout Animations ```tsx import { AnimatePresence, motion } from 'framer-motion'; function Tabs({ items, selected }) { return (
{items.map((item, i) => ( ))}
); } ``` ## Render Props Use render props to apply dynamic animations based on component state: ```tsx ``` ## Accessibility ### Respecting Motion Preferences Always respect user motion preferences: ```css @media (prefers-reduced-motion: reduce) { .button { transition: none; } .animate-* { animation: none !important; } } ``` With Framer Motion: ```tsx import { useReducedMotion } from 'framer-motion'; function AnimatedCard() { const shouldReduceMotion = useReducedMotion(); return ( Content ); } ``` ## Performance Tips ### Use GPU-Accelerated Properties Prefer `transform` and `opacity` for smooth animations: ```css /* Good - GPU accelerated */ .slide-in { transform: translateX(-100%); transition: transform 0.3s; } /* Avoid - Triggers layout */ .slide-in { left: -100%; transition: left 0.3s; } ``` ### Will-Change Optimization ```css .button { will-change: transform; } .button:not(:hover) { will-change: auto; } ``` ## Next Steps * Learn about [Styling](/docs/handbook/styling) approaches * Explore [Component](/docs/components) examples * View [Theming](/docs/handbook/theming) documentation # HeroUI v3 > handbook > Colors URL: /docs/handbook/colors Source: https://raw.githubusercontent.com/heroui-inc/heroui/refs/heads/v3/apps/docs/content/docs/handbook/colors.mdx Color palette and theming system for HeroUI v3 *** title: Colors description: Color palette and theming system for HeroUI v3 icon: bucket-paint links: themes: true tailwind: theme --------------- import {ColorSwatch, ColorPalette} from "@/components/color-swatch"; HeroUI uses CSS variables for colors that automatically switch between light and dark themes. All colors use the `oklch` color space for better color transitions. ## How It Works HeroUI's color system is built on top of Tailwind CSS v4's theme. When you import `@heroui/styles`, it uses Tailwind's built-in color palettes (like `--color-neutral-*`) and maps them to semantic variables. Add a theme class to your HTML and apply colors to the body: ```html ``` We follow a simple naming pattern: * Colors without a suffix are backgrounds (e.g., `--accent`) * Colors with `-foreground` are for text on that background (e.g., `--accent-foreground`) ```tsx // This gives you the right background and text colors
Hello
``` ## Available Colors ### Base Colors These four colors stay the same in all themes:
### Background & Surface ### Primary Colors * **Accent**: Your main brand color (used for primary actions) * **Accent Soft**: A lighter version for secondary actions ### Status Colors For alerts, validation, and status messages: ### Other Colors ## How to Use Colors ### In Your Components ```jsx // Use Tailwind classes
``` ### In CSS Files ```css title="global.css" /* Direct CSS variables */ .my-component { background: var(--accent); color: var(--accent-foreground); border: 1px solid var(--border); } /* With @apply and @layer */ @layer components { .button { @apply bg-accent text-accent-foreground; &:hover, &[data-hover="true"] { @apply bg-accent-hover; } &:active, &[data-pressed="true"] { @apply bg-accent-hover; transform: scale(0.97); } } } ``` ## Default Theme The complete theme definition can be found in ([default.css](https://github.com/heroui-inc/heroui/blob/v3/packages/styles/themes/default/index.css)). This theme automatically switches between light and dark modes based on the `class="dark"` or `data-theme="dark"` attributes. > **Note**: Colors like `--color-neutral-*`, `--color-white`, and `--color-black` come from [Tailwind CSS v4's built-in theme](https://tailwindcss.com/docs/colors). ## Customizing Colors ### Add Your Own Colors ```css :root, [data-theme="light"] { --info: oklch(0.6 0.15 210); --info-foreground: oklch(0.98 0 0); } .dark, [data-theme="dark"] { --info: oklch(0.7 0.12 210); --info-foreground: oklch(0.15 0 0); } /* Make the color available to Tailwind */ @theme inline { --color-info: var(--info); --color-info-foreground: var(--info-foreground); } ``` Now you can use it: ```tsx
Info message
``` > **Note**: To learn more about theme variables and how they work in Tailwind CSS v4, see the [Tailwind CSS Theme documentation](https://tailwindcss.com/docs/theme). ### Override Existing Colors ```css :root { /* Override default colors */ --accent: oklch(0.7 0.15 250); --success: oklch(0.65 0.15 155); } [data-theme="dark"] { /* Override dark theme colors */ --accent: oklch(0.8 0.12 250); --success: oklch(0.75 0.12 155); } ``` **Tip**: Convert colors at [oklch.com](https://oklch.com) ## Quick Tips * Always use color variables, not hard-coded values * Use foreground/background pairs for good contrast * Test in both light and dark modes * The system respects user's theme preference automatically ## Related * [Theming](/docs/handbook/theming) - Learn about the theming system * [Styling](/docs/handbook/styling) - Styling components with CSS * [Design Principles](/docs/design-principles) - Understanding HeroUI's design philosophy # HeroUI v3 > handbook > Composition URL: /docs/handbook/composition Source: https://raw.githubusercontent.com/heroui-inc/heroui/refs/heads/v3/apps/docs/content/docs/handbook/composition.mdx Build flexible UI with component composition patterns *** title: Composition description: Build flexible UI with component composition patterns icon: layers ------------ ## Overview HeroUI uses composition patterns to create flexible, customizable components. This allows you to: * Change the rendered element or component * Compose components together * Maintain full control over markup ## The asChild Prop The `asChild` prop lets you change what element a component renders. When `asChild` is true, HeroUI won't render its default element - instead, it clones the child element and merges props. ### Basic Usage ```tsx import { Button } from '@heroui/react'; import Link from 'next/link'; // Renders as a Next.js Link // Renders as a regular anchor ``` ### Available Components These components support `asChild`: * `Button` - Change button element * `Alert` parts - Root, Icon, Content, Title, Description, Action, Close * `Avatar` - Change root element * More components coming soon ## Compound Components HeroUI components are built as compound components - they export multiple parts that work together: ```tsx import { Alert } from '@heroui/react'; Success Your changes have been saved. ``` This pattern provides: * **Flexibility** - Arrange parts as needed * **Customization** - Style each part independently * **Control** - Add or remove parts ## Style Variants HeroUI exports variant functions that can be applied to any component. This allows you to use HeroUI's design system with any element or component: ### Using buttonVariants Apply button styles to any component: ```tsx import { Link, buttonVariants } from '@heroui/react'; // Link styled as a tertiary button HeroUI // Native anchor styled as primary button Go to Dashboard ``` ### Available Variant Functions Each component exports its variant function: * `buttonVariants` - Button styles * `chipVariants` - Chip styles * `linkVariants` - Link styles * `spinnerVariants` - Spinner styles * More variant functions for each component ## Custom Components Create your own components by composing HeroUI primitives: ```tsx import { Button, Tooltip } from '@heroui/react'; // Link button component function LinkButton({ href, children, ...props }) { return ( ); } // Icon button with tooltip function IconButton({ icon, label, ...props }) { return ( ); } ``` ## Custom Variants You can create your own custom variants by extending the component's variant function. ```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({ extend: buttonVariants, base: "text-md text-shadow-lg font-semibold shadow-md data-[pending=true]:opacity-40", variants: { radius: { lg: "rounded-lg", md: "rounded-md", sm: "rounded-sm", full: "rounded-full", }, size: { sm: "h-10 px-4", md: "h-11 px-6", lg: "h-12 px-8", xl: "h-13 px-10", }, variant: { primary: "text-white dark:bg-white/10 dark:text-white dark:hover:bg-white/15", }, }, defaultVariants: { radius: "full", variant: "primary", }, }); type MyButtonVariants = VariantProps; export type MyButtonProps = Omit & MyButtonVariants & {className?: string}; function CustomButton({className, radius, variant, ...props}: MyButtonProps) { return ``` ## With React Router Use `asChild` to integrate with routing libraries: ```tsx import { Link } from 'react-router-dom'; import { Button } from '@heroui/react'; ``` ## Next Steps * Learn about [Styling](/docs/handbook/styling) components * Explore [Animation](/docs/handbook/animation) options * Browse [Components](/docs/components) for more examples # HeroUI v3 > handbook > Styling URL: /docs/handbook/styling Source: https://raw.githubusercontent.com/heroui-inc/heroui/refs/heads/v3/apps/docs/content/docs/handbook/styling.mdx Style HeroUI components with CSS, Tailwind, or CSS-in-JS *** title: Styling description: Style HeroUI components with CSS, Tailwind, or CSS-in-JS icon: brush links: themes: true tailwind: theme --------------- ## Overview HeroUI components are built on React Aria and provide flexible styling options: * **Tailwind CSS** - Use utility classes directly * **CSS** - Target BEM classes or data attributes * **CSS-in-JS** - Integrate with styled-components, Emotion, etc. * **Render props** - Dynamic styling based on component state ## Basic Styling ### Using className All HeroUI components accept `className` props: ```tsx {/* content */} ``` ### Using style Components also accept inline styles: ```tsx ``` ## State-Based Styling HeroUI components expose their state through data attributes, similar to CSS pseudo-classes: ```css /* Target different states */ .button[data-hover="true"], .button:hover { background: var(--accent-hover); } .button[data-pressed="true"], .button:active { transform: scale(0.97); } .button[data-focus-visible="true"], .button:focus-visible { outline: 2px solid var(--focus); } ``` ## Render Props Use render props for dynamic styling based on component state: ```tsx // Dynamic classes // Dynamic content ``` ## BEM Classes HeroUI uses [BEM methodology](https://getbem.com/) for consistent class naming: ```css /* Block */ .button { } .accordion { } /* Element */ .accordion__trigger { } .accordion__panel { } /* Modifier */ .button--primary { } .button--lg { } .accordion--outline { } ``` ### Customizing Components Globally ```css /* global.css */ @layer components { /* Override button styles */ .button { @apply font-semibold uppercase; } .button--primary { @apply bg-indigo-600 hover:bg-indigo-700; } /* Add custom variant */ .button--gradient { @apply bg-gradient-to-r from-purple-500 to-pink-500; } } ``` ## Creating Wrapper Components For reusable custom components, create wrappers using [tailwind-variants](https://tailwind-variants.org/) - a Tailwind CSS first-class variant API created by us as well: ```tsx import { Button as HeroButton, buttonVariants, type ButtonProps } from '@heroui/react'; import { tv, type VariantProps } from 'tailwind-variants'; const customButtonVariants = tv({ extend: buttonVariants, base: 'font-medium transition-all', variants: { intent: { primary: 'bg-blue-500 hover:bg-blue-600 text-white', secondary: 'bg-gray-200 hover:bg-gray-300', danger: 'bg-red-500 hover:bg-red-600 text-white', }, size: { small: 'text-sm px-2 py-1', medium: 'text-base px-4 py-2', large: 'text-lg px-6 py-3', }, }, defaultVariants: { intent: 'primary', size: 'medium', }, }); type CustomButtonVariants = VariantProps; interface CustomButtonProps extends Omit, CustomButtonVariants { className?: string; } export function CustomButton({ intent, size, className, ...props }: CustomButtonProps) { return ( ); } ``` ## CSS-in-JS Integration ### Styled Components ```tsx import styled from 'styled-components'; import { Button } from '@heroui/react'; const StyledButton = styled(Button)` background: linear-gradient(45deg, #FE6B8B 30%, #FF8E53 90%); border-radius: 8px; color: white; padding: 12px 24px; &:hover { box-shadow: 0 3px 10px rgba(255, 105, 135, 0.3); } `; ``` ### Emotion ```tsx import { css } from '@emotion/css'; import { Button } from '@heroui/react'; const buttonStyles = css` background: linear-gradient(45deg, #FE6B8B 30%, #FF8E53 90%); border-radius: 8px; color: white; padding: 12px 24px; &:hover { box-shadow: 0 3px 10px rgba(255, 105, 135, 0.3); } `; ``` ## Responsive Design Use Tailwind's responsive utilities: ```tsx ``` Or with CSS: ```css .button { font-size: 0.875rem; padding: 0.5rem 1rem; } @media (min-width: 768px) { .button { font-size: 1rem; padding: 0.75rem 1.5rem; } } ``` ## CSS Modules For scoped styles, use CSS Modules: ```css /* Button.module.css */ .button { background: linear-gradient(135deg, #667eea, #764ba2); color: white; padding: 12px 24px; border-radius: 8px; } .button:hover { transform: translateY(-2px); } .button--primary { background: linear-gradient(135deg, #667eea, #764ba2); color: white; padding: 12px 24px; border-radius: 8px; } ``` ```tsx import styles from './Button.module.css'; import { Button } from '@heroui/react'; ``` ## Component Classes Reference ### Button * `.button` - Base * `.button--{variant}` - Variants * `.button--{size}` - Sizes * `.button--icon-only` - Icon button > **Note**: See [Button](/docs/components/button#css-classes) for more information on button classes. ### Accordion * `.accordion` - Container * `.accordion__item` - Item * `.accordion__trigger` - Header * `.accordion__panel` - Content * `.accordion--outline` - Variant > **Note**: See [Accordion](/docs/components/accordion#css-classes) for more information on accordion classes. View all component classes in [@heroui/styles/components](https://github.com/heroui-inc/heroui/tree/main/packages/styles/components). ## Next Steps * Learn about [Animation](/docs/handbook/animation) techniques * Explore [Theming](/docs/handbook/theming) system * Browse [Component](/docs/components) examples # HeroUI v3 > handbook > Theming URL: /docs/handbook/theming Source: https://raw.githubusercontent.com/heroui-inc/heroui/refs/heads/v3/apps/docs/content/docs/handbook/theming.mdx Customize HeroUI's design system with CSS variables and global styles *** title: Theming description: Customize HeroUI's design system with CSS variables and global styles icon: palette links: themes: true tailwind: theme --------------- ## Overview HeroUI uses CSS variables and [BEM](https://getbem.com/) classes for theming. You can customize everything from colors to component styles using standard CSS. ## How It Works HeroUI's theming system is built on top of [Tailwind CSS v4](https://tailwindcss.com/docs/theme)'s theme. When you import `@heroui/styles`, it: 1. Uses Tailwind's built-in color palettes (like `--color-neutral-*`) 2. Maps them to semantic variables for easier use 3. Automatically switches between light and dark themes 4. Uses CSS layers and the `@theme` directive for organization The system follows a simple naming pattern: * Colors without a suffix are backgrounds (e.g., `--accent`) * Colors with `-foreground` are for text on that background (e.g., `--accent-foreground`) ## Quick Start ### Apply a Theme Add a theme class to your HTML and apply colors to the body: ```html ``` ### Switch Themes ```html ``` ### Override Colors ```css /* app/globals.css */ @import "tailwindcss"; @import "@heroui/styles"; :root { /* Override any color variable */ --accent: oklch(0.7 0.25 260); --success: oklch(0.65 0.15 155); } ``` > **Note**: See [Colors](/docs/handbook/colors) for the complete color palette and visual reference. ### Create your own theme Use your theme: ```css /* app/globals.css */ @layer theme, base, components, utilities; @import "tailwindcss"; @import "@heroui/styles"; @import "./src/themes/ocean.css" layer(theme); /* [!code highlight]*/ ``` Apply your theme: ```html ``` ## Customize Components ### Global Component Styles Override any component using BEM classes: ```css @layer components { /* Customize buttons */ .button { @apply font-semibold tracking-wide; } .button--primary { @apply bg-blue-600 hover:bg-blue-700; } /* Customize accordions */ .accordion__trigger { @apply text-lg font-bold; } } ``` > **Note**: See [Styling](/docs/handbook/styling) for the complete styling reference. ### Find Component Classes Each component docs page lists all available classes: * **Base classes**: `.button`, `.accordion` * **Modifiers**: `.button--primary`, `.button--icon-only` * **Elements**: `.accordion__trigger`, `.accordion__panel` * **States**: `[data-hover="true"]`, `[aria-expanded="true"]` Example: [Button classes](/docs/components/button#css-classes) ## Import Strategies ### Full Import (Recommended) Get everything with two lines: ```css @import "tailwindcss"; @import "@heroui/styles"; ``` ### Selective Import Import only what you need: ```css /* Define layers */ @layer theme, base, components, utilities; /* Base requirements */ @import "tailwindcss"; @import "@heroui/styles/base/base.css" layer(base); @import "@heroui/styles/themes/theme.css" layer(theme); @import "@heroui/styles/themes/default.css" layer(theme); /* Components (all components) */ @import "@heroui/styles/components/index.css" layer(components); /* OR specific components */ @import "@heroui/styles/components/button.css" layer(components); @import "@heroui/styles/components/accordion.css" layer(components); ``` ### Headless Mode Build your own styles from scratch: ```css @import "tailwindcss"; @import "@heroui/styles/base/base.css"; /* Your custom styles */ .button { /* Your button styles */ } ``` ## Adding Custom Colors You can add your own semantic colors to the theme: ```css /* Define in both light and dark themes */ :root, [data-theme="light"] { --info: oklch(0.6 0.15 210); --info-foreground: oklch(0.98 0 0); } .dark, [data-theme="dark"] { --info: oklch(0.7 0.12 210); --info-foreground: oklch(0.15 0 0); } /* Make the color available to Tailwind */ @theme inline { --color-info: var(--info); --color-info-foreground: var(--info-foreground); } ``` Now use it in your components: ```tsx
Info message
``` ## Variables Reference HeroUI defines three types of variables: 1. **Base Variables**: Non-changing values like `--white`, `--black`, spacing, and typography 2. **Theme Variables**: Colors that change between light/dark themes 3. **Calculated Variables**: Automatically generated hover states and size variants For a complete reference of all variables and their values, see: * [Colors Documentation](/docs/handbook/colors) - Visual color palette and base variables * [Default Theme Source](https://github.com/heroui-inc/heroui/blob/v3/packages/styles/themes/default/index.css) - Complete theme implementation ### Calculated Variables (Tailwind) We use Tailwind's `@theme` directive to automatically create calculated variables for hover states and radius variants: circ @made by https://twitter.com/bdc */ --ease-in-quad: cubic-bezier(0.55, 0.085, 0.68, 0.53); --ease-in-cubic: cubic-bezier(0.55, 0.055, 0.675, 0.19); --ease-in-quart: cubic-bezier(0.895, 0.03, 0.685, 0.22); --ease-in-quint: cubic-bezier(0.755, 0.05, 0.855, 0.06); --ease-in-expo: cubic-bezier(0.95, 0.05, 0.795, 0.035); --ease-in-circ: cubic-bezier(0.6, 0.04, 0.98, 0.335); --ease-out-quad: cubic-bezier(0.25, 0.46, 0.45, 0.94); --ease-out-cubic: cubic-bezier(0.215, 0.61, 0.355, 1); --ease-out-quart: cubic-bezier(0.165, 0.84, 0.44, 1); --ease-out-quint: cubic-bezier(0.23, 1, 0.32, 1); --ease-out-expo: cubic-bezier(0.19, 1, 0.22, 1); --ease-out-circ: cubic-bezier(0.075, 0.82, 0.165, 1); --ease-in-out-quad: cubic-bezier(0.455, 0.03, 0.515, 0.955); --ease-in-out-cubic: cubic-bezier(0.645, 0.045, 0.355, 1); --ease-in-out-quart: cubic-bezier(0.77, 0, 0.175, 1); --ease-in-out-quint: cubic-bezier(0.86, 0, 0.07, 1); --ease-in-out-expo: cubic-bezier(1, 0, 0, 1); --ease-in-out-circ: cubic-bezier(0.785, 0.135, 0.15, 0.86); /* Animations */ --animate-spin-fast: spin 0.75s linear infinite; --animate-skeleton: skeleton 2s linear infinite; } `} /> ## Resources * [Colors Documentation](/docs/handbook/colors) * [Styling Guide](/docs/handbook/styling) * [Tailwind CSS v4 Theming](https://tailwindcss.com/docs/theme) * [BEM Methodology](https://getbem.com/) * [OKLCH Color Tool](https://oklch.com)