# Animation **Category**: native **URL**: https://www.heroui.com/en/docs/native/getting-started/animation **Source**: https://raw.githubusercontent.com/heroui-inc/heroui/refs/heads/v3/apps/docs/content/docs/en/native/getting-started/(handbook)/animation.mdx > Add smooth animations and transitions to HeroUI Native components All animations in HeroUI Native are built with [react-native-reanimated](https://docs.swmansion.com/react-native-reanimated/) and gesture control is handled by [react-native-gesture-handler](https://docs.swmansion.com/react-native-gesture-handler/). It's worth familiarizing yourself with these libraries if you want more control over animations. ## The `animation` Prop Every animated component in HeroUI Native exposes a single `animation` prop that controls all animations for that component. This prop allows you to modify animation values, timing configurations, layout animations, or completely disable animations. **Approach**: If you're working with animations, first look for the `animation` prop on the component you're using. ## Modifying Animations You can customize animations by passing an object to the `animation` prop. Each component exposes different animation properties that you can modify. The approach is simple: if you want to slightly change the animation behavior of already written animations in components, we provide all necessary values for modification. If you want to write your own animations without relying on our written ones, you must create your own custom components with animations. ### Example 1: Simple Value Modification Modify animation values like scale, opacity, or colors: ```tsx import {Switch} from 'heroui-native'; ; ``` ### Example 2: Timing Configuration Customize animation timing and easing: ```tsx import {Accordion} from 'heroui-native'; ; ``` ### Example 3: Layout Animations (Entering/Exiting) Customize entering and exiting animations using Reanimated's layout animations: ```tsx import {Accordion} from 'heroui-native'; import {FadeInRight, FadeInLeft, ZoomIn} from 'react-native-reanimated'; import {Easing} from 'react-native-reanimated'; Content here ; ``` ### Example 4: State Prop for Granular Control The `state` prop allows you to disable animations while still customizing animation properties. This is useful when you want to fine-tune component behavior without enabling animations: ```tsx import {Switch} from 'heroui-native'; ``` The `state` prop accepts: * `'disabled'`: Disable animations while allowing property customization * `'disable-all'`: Disable all animations including children (only available at root level) * `boolean`: Simple enable/disable control (`true` enables, `false` disables) This provides more granular control over animation behavior, allowing you to customize properties without enabling animations. ## Disabling Animations You can disable animations at different levels using the `animation` prop. ### Disable Options * `animation={false}` or `animation="disabled"`: Disable animations for the specific component only * `animation="disable-all"`: Disable all animations including children (only available at root level) * `animation={true}` or `animation={undefined}`: Use default animations ### Component-Level Disabling Disable animations for a specific component: ```tsx ``` ### Root-Level Disabling (`disable-all`) The `"disable-all"` option is only available at the root level of compound components. When used, it disables all animations including children, even if those children are not part of the compound component structure: ```tsx // Disables all animations including Button components inside Card $450 Living room Sofa ``` **Important**: `"disable-all"` cascades down to all child components, including standalone components like `Button`, `Spinner`, etc., not just compound component parts. ## Global Animation Configuration You can disable all HeroUI Native animations globally using the `HeroUINativeProvider`: ```tsx import {HeroUINativeProvider} from 'heroui-native'; ; ``` This will disable all animations across your entire application, regardless of individual component `animation` prop settings. ## Accessibility Reduce motion is handled automatically under the hood. When a user enables "Reduce Motion" in their device accessibility settings, all animations are automatically disabled globally. This is handled by the `GlobalAnimationSettingsProvider` which checks `useReducedMotion()` from react-native-reanimated. You don't need to do anything - the library respects the user's accessibility preferences automatically. ## Animation State Management We keep disabled state of animations under control internally to ensure they look nice without unpredictable lags or jumps. When animations are disabled, components immediately jump to their final state rather than animating, preventing visual glitches or intermediate states. ## Children Render Function Many components support a render function pattern for children, which is particularly handy when working with state like `isSelected`: ```tsx import {Switch} from 'heroui-native'; {({isSelected, isDisabled}) => ( {isSelected ? : } )} ; ``` This pattern allows you to conditionally render content based on component state, making it easy to create dynamic UIs that respond to selection, disabled states, and other component properties. ## Next Steps * Learn about [Styling](/docs/native/getting-started/styling) approaches * View [Theming](/docs/native/getting-started/theming) documentation * Explore [Colors](/docs/native/getting-started/colors) documentation # Colors **Category**: native **URL**: https://www.heroui.com/en/docs/native/getting-started/colors **Source**: https://raw.githubusercontent.com/heroui-inc/heroui/refs/heads/v3/apps/docs/content/docs/en/native/getting-started/(handbook)/colors.mdx > Color palette and theming system for HeroUI Native import {ColorSectionSideBySide, ColorSectionStacked, ColorSectionFormField, ColorSectionPrimitive} from "@/components/color-section"; HeroUI Native's color system is built around semantic intent, not visual abundance. Instead of exposing large raw palettes, the system defines a small, meaningful set of color roles that cover the majority of interface needs. Most colors in the system are derived automatically from a limited number of base values. This allows HeroUI to maintain consistent contrast, hierarchy, and theming behavior while keeping the system easy to reason about and modify. Colors should communicate purpose and state first. Visual variation comes from scale, emphasis, and context. ## Accent The accent color represents the primary brand or product identity. It is used to draw attention to key actions, highlights, and moments of emphasis. Accent should be used intentionally and sparingly. Overuse reduces its impact and can harm visual hierarchy. In most cases, components derive multiple accent-related values (hover, subtle backgrounds, focus states) automatically from the base accent color. ## Default (neutrals) Default colors form the neutral backbone of the system. They are used for most non-emphasized UI elements. ## Success Success colors communicate positive outcomes, confirmations, and completed states. They are typically used in feedback components, status indicators, and validation states. ## Warning Warning colors indicate caution, risk, or actions that require attention but are not destructive. They are commonly used for alerts, messages, and transitional states where the user should pause or review information. ## Danger Danger colors represent destructive, irreversible, or critical actions and states. They should be immediately recognizable and used consistently for errors, destructive buttons, and critical alerts. ## Foreground Foreground colors are used for primary content such as text and icons. These colors are optimized for readability and accessibility and adapt automatically to background and surface contexts. Foreground colors should never be hard-coded at the component level. ## Background Background colors define the base canvas of the interface. They establish overall contrast and mood while staying visually quiet. ## Surface Surface colors sit on top of backgrounds and are used for containers such as cards, panels, modals, and dropdown. Surfaces help create visual separation and hierarchy through elevation, contrast, and layering rather than strong color shifts. ## Form field Form field colors are specialized tokens used for inputs, controls, and interactive fields. They account for multiple states such as default, focus, and hover. Isolating them ensures form elements have a distinct visual language from buttons and the rest of the UI. ## Separator Separator colors are used for dividers, outlines, and subtle boundaries. They exist to structure content and guide the eye without adding noise. Separator colors should remain low contrast and unobtrusive. ## Other Other colors serve specific utility roles across the interface. They exist to structure content and guide the eye without adding noise. ## Primitive Primitive colors are mode agnostic values used as foundations for semantic color tokens. They do not change between light and dark themes. ## How to Use Colors **In your components:** ```tsx import { View, Text } from 'react-native'; Content ; ``` **In CSS files:** ```css title="global.css" /* Direct CSS variables */ .container { flex: 1; background-color: var(--accent); width: 50px; height: 50px; border-radius: var(--radius); } ``` ## Default Theme The complete theme definition can be found in ([variables.css](https://github.com/heroui-inc/heroui-native/blob/main/src/styles/variables.css)). This theme automatically switches between light and dark modes through [Uniwind's theming system](https://docs.uniwind.dev/theming/basics), which supports system preferences and programmatic theme switching. ```css @theme { /* Primitive Colors (Do not change between light and dark) */ --white: oklch(100% 0 0); --black: oklch(0% 0 0); --snow: oklch(0.9911 0 0); --eclipse: oklch(0.2103 0.0059 285.89); /* Border */ --border-width: 1px; --field-border-width: 0px; /* Base radius */ --radius: 0.5rem; --field-radius: calc(var(--radius) * 1.5); /* Opacity */ --opacity-disabled: 0.5; } @layer theme { :root { @variant light { /* Base Colors */ --background: oklch(0.9702 0 0); --foreground: var(--eclipse); /* Surface */ --surface: var(--white); --surface-foreground: var(--foreground); --surface-secondary: oklch(0.9524 0.0013 286.37); --surface-secondary-foreground: var(--foreground); --surface-tertiary: oklch(0.9373 0.0013 286.37); --surface-tertiary-foreground: var(--foreground); /* Overlay */ --overlay: var(--white); --overlay-foreground: var(--foreground); --backdrop: oklch(0% 0 0 / 20%); --muted: oklch(0.5517 0.0138 285.94); --default: oklch(94% 0.001 286.375); --default-foreground: var(--eclipse); --accent: oklch(0.6204 0.195 253.83); --accent-foreground: var(--snow); /* Form Fields */ --field-background: var(--white); --field-foreground: oklch(0.2103 0.0059 285.89); --field-placeholder: var(--muted); --field-border: transparent; /* Status Colors */ --success: oklch(0.7329 0.1935 150.81); --success-foreground: var(--eclipse); --warning: oklch(0.7819 0.1585 72.33); --warning-foreground: var(--eclipse); --danger: oklch(0.6532 0.2328 25.74); --danger-foreground: var(--snow); /* Component Colors */ --segment: var(--white); --segment-foreground: var(--eclipse); /* Misc Colors */ --border: oklch(90% 0.004 286.32); --separator: oklch(74% 0.004 286.32); --focus: var(--accent); --link: var(--foreground); } @variant dark { /* Base Colors */ --background: oklch(12% 0.005 285.823); --foreground: var(--snow); /* Surface */ --surface: oklch(0.2103 0.0059 285.89); --surface-foreground: var(--foreground); --surface-secondary: oklch(0.257 0.0037 286.14); --surface-secondary-foreground: var(--foreground); --surface-tertiary: oklch(0.2721 0.0024 247.91); --surface-tertiary-foreground: var(--foreground); /* Overlay */ --overlay: oklch(0.2103 0.0059 285.89); --overlay-foreground: var(--foreground); --backdrop: oklch(0% 0 0 / 20%); --muted: oklch(70.5% 0.015 286.067); --default: oklch(27.4% 0.006 286.033); --default-foreground: var(--snow); --accent: oklch(0.6204 0.195 253.83); --accent-foreground: var(--snow); /* Form Fields */ --field-background: oklch(0.2103 0.0059 285.89); --field-foreground: var(--foreground); --field-placeholder: var(--muted); --field-border: transparent; /* Status Colors */ --success: oklch(0.7329 0.1935 150.81); --success-foreground: var(--eclipse); --warning: oklch(0.8203 0.1388 76.34); --warning-foreground: var(--eclipse); --danger: oklch(0.594 0.1967 24.63); --danger-foreground: var(--snow); /* Component Colors */ --segment: oklch(0.3964 0.01 285.93); --segment-foreground: var(--foreground); /* Misc Colors */ --border: oklch(28% 0.006 286.033); --separator: oklch(40% 0.006 286.033); --focus: var(--accent); --link: var(--foreground); } } } ``` ## Customizing Colors **Override existing colors:** ```css @layer theme { @variant light { /* Override default colors */ --accent: oklch(0.65 0.25 270); /* Custom indigo accent */ --success: oklch(0.65 0.15 155); } @variant dark { /* Override dark theme colors */ --accent: oklch(0.65 0.25 270); --success: oklch(0.75 0.12 155); } } ``` **Tip:** Convert colors at [oklch.com](https://oklch.com) **Add your own colors:** ```css @layer theme { @variant light { --info: oklch(0.6 0.15 210); --info-foreground: oklch(0.98 0 0); } @variant dark { --info: oklch(0.7 0.12 210); --info-foreground: oklch(0.15 0 0); } } @theme inline { --color-info: var(--info); --color-info-foreground: var(--info-foreground); } ``` Now you can use it: ```tsx import { View, Text } from 'react-native'; Info message ; ``` > **Note**: To learn more about theme variables and how they work in Tailwind CSS v4, see the [Tailwind CSS Theme documentation](https://tailwindcss.com/docs/theme). ## useThemeColor Hook The `useThemeColor` hook has been enhanced to support multiple colors selection, making it more flexible for complex theming scenarios. **Multiple Colors Selection:** You can now select multiple colors at once, which is useful when you need to work with related color values together: ```tsx import { useThemeColor } from 'heroui-native'; // Select multiple colors at once const [accent, accentForeground, success, danger] = useThemeColor([ 'accent', 'accentForeground', 'success', 'danger', ]); // Use the selected colors Accent Text ; ``` This enhancement improves performance when working with multiple color values and makes it easier to manage complex theming scenarios where multiple colors need to be selected and applied together. # Composition **Category**: native **URL**: https://www.heroui.com/en/docs/native/getting-started/composition **Source**: https://raw.githubusercontent.com/heroui-inc/heroui/refs/heads/v3/apps/docs/content/docs/en/native/getting-started/(handbook)/composition.mdx > Build flexible UI with component composition patterns HeroUI Native uses composition patterns to create flexible, customizable components. Change the rendered element, compose components together, and maintain full control over markup. ## Compound Components HeroUI Native components use a compound component pattern with dot notation—components export sub-components as properties (e.g., `Button.Label`, `Dialog.Trigger`, `Accordion.Item`) that work together to form complete UI elements. ```tsx import { Button, Dialog } from 'heroui-native'; function DialogExample() { return ( Open Dialog Dialog Title Dialog description ); } ``` ## The asChild Prop The `asChild` prop lets you change what element a component renders. When `asChild` is true, HeroUI Native clones the child element and merges props instead of rendering its default element. ```tsx import { Button, Dialog } from 'heroui-native'; function DialogExample() { return ( {/* With asChild: Button becomes the trigger directly, no wrapper element */} {/* Dialog.Close can also use asChild */} Dialog Title Dialog description ); } ``` ## Custom Components Create your own components by composing HeroUI Native primitives: ```tsx import { Button, Card, Popover } from 'heroui-native'; import { View } from 'react-native'; // Product card component function ProductCard({ title, description, price, onBuy, ...props }) { return ( {price} {title} {description} ); } // Popover button component function PopoverButton({ children, popoverContent, ...props }) { return ( {popoverContent} ); } // Usage console.log('Buy')} /> Information Additional details here }> Show Info ``` ## Custom Variants Create custom variants using `tailwind-variants` to extend component styling. Note that text color classes must be applied to `Button.Label`, not the parent `Button`: ```tsx import { Button } from 'heroui-native'; import type { ButtonRootProps } from 'heroui-native'; import { tv, type VariantProps } from 'tailwind-variants'; const customButtonVariants = tv({ base: 'font-semibold rounded-lg', variants: { intent: { primary: 'bg-blue-500', secondary: 'bg-gray-200', danger: 'bg-red-500', }, }, defaultVariants: { intent: 'primary', }, }); const customLabelVariants = tv({ base: '', variants: { intent: { primary: 'text-white', secondary: 'text-gray-800', danger: 'text-white', }, }, defaultVariants: { intent: 'primary', }, }); type CustomButtonVariants = VariantProps; interface CustomButtonProps extends Omit, CustomButtonVariants { className?: string; labelClassName?: string; } export function CustomButton({ intent, className, labelClassName, children, ...props }: CustomButtonProps) { return ( ); } ``` ## Next Steps * Learn about [Styling](/docs/native/getting-started/styling) system * Explore [Theming](/docs/native/getting-started/theming) documentation * Explore [Animation](/docs/native/getting-started/animation) options # Portal **Category**: native **URL**: https://www.heroui.com/en/docs/native/getting-started/portal **Source**: https://raw.githubusercontent.com/heroui-inc/heroui/refs/heads/v3/apps/docs/content/docs/en/native/getting-started/(handbook)/portal.mdx Portals let you render its children into a different part of your app. This is particularly useful for components that need to render above other content, such as modals, overlays, and popups. ## Default Setup By default, the `PortalHost` is included in the `HeroUINativeProvider`, so there is no need to add it manually. The provider automatically sets up the portal system for all components that use portals. ## Advanced Use Cases For advanced use cases, you can import `Portal` and `PortalHost` directly from `heroui-native` to create custom portal implementations: ```tsx import { Portal, PortalHost } from "heroui-native"; import { View, Text } from "react-native"; function AppLayout() { return ( Header Content Main Content Area {/* Portal host positioned at the top of the screen */} ); } function CustomNotification() { return ( This notification appears at the top via Portal ); } ``` In this example, the `CustomNotification` component uses a `Portal` to render its content at the location of the `PortalHost`, which is positioned at the top of the screen. This allows the notification to appear above all other content regardless of where it's defined in the component tree. ## State Management Considerations State changes in parent components can cause unexpected issues with components rendered inside portals. For example, when a text input is placed directly inside a portal and the parent component re-renders, it can reset the input's auto-suggestions or cause other UI disruptions. To avoid this, keep the state of interactive components (like text inputs) inside the portal by creating a separate component for the portal content. This isolates the state from parent re-renders. ### Example Pattern ```tsx // ❌ Problematic: State in parent causes re-renders that affect portal content function ParentComponent() { const [dialogOpen, setDialogOpen] = useState(false); const [inputValue, setInputValue] = useState(""); // State in parent return ( ); } // ✅ Correct: State managed inside separate component within portal function ParentComponent() { const [dialogOpen, setDialogOpen] = useState(false); return ( setDialogOpen(false)} // Form state isolated from parent /> ); } function DialogFormContent({ onClose }: { onClose: () => void }) { const [inputValue, setInputValue] = useState(""); // State inside portal const [error, setError] = useState(""); return ( {error} ); } ``` In the correct pattern, the `DialogFormContent` component manages its own state independently of the parent component. This ensures that parent re-renders (such as when `dialogOpen` changes) don't affect the input's internal state, preserving auto-suggestions and other input behaviors. ## API Reference ### PortalHost By default, children of all Portal components will be rendered as its own children. | Prop | Type | Note | | ---- | -------- | --------------------------------------------------- | | name | `string` | Provide when it is used as a custom host (optional) | ### Portal | Prop | Type | Note | | -------- | ----------------- | ------------------------------------------------------------------------------------- | | name\* | `string` | Unique value otherwise the portal with the same name will replace the original portal | | hostName | `string` | Provide when its children are to be rendered in a custom host (optional) | | children | `React.ReactNode` | The content to render in the portal | \* Required prop ## Related * [Quick Start](/docs/native/getting-started/quick-start) - Basic setup guide * View [Provider](/docs/native/getting-started/provider) documentation # Provider **Category**: native **URL**: https://www.heroui.com/en/docs/native/getting-started/provider **Source**: https://raw.githubusercontent.com/heroui-inc/heroui/refs/heads/v3/apps/docs/content/docs/en/native/getting-started/(handbook)/provider.mdx > Configure HeroUI Native provider with text, animation, and toast settings The `HeroUINativeProvider` is the root provider component that configures and initializes HeroUI Native in your React Native application. It provides global configuration and portal management for your application. ## Overview The provider serves as the main entry point for HeroUI Native, wrapping your application with essential contexts and configurations: * **Safe Area Insets**: Automatically handles safe area insets updates via `SafeAreaListener` and syncs them with Uniwind for use in Tailwind classes (e.g., `pb-safe-offset-3`) * **Text Configuration**: Global text component settings for consistency across all HeroUI components * **Animation Configuration**: Global animation control to disable all animations across the application * **Toast Configuration**: Global toast system configuration including insets, default props, and wrapper components * **Portal Management**: Handles overlays, modals, and other components that render on top of the app hierarchy ## Basic Setup Wrap your application root with the provider: ```tsx import { HeroUINativeProvider } from 'heroui-native'; import { GestureHandlerRootView } from 'react-native-gesture-handler'; export default function App() { return ( {/* Your app content */} ); } ``` ## Configuration Options The provider accepts a `config` prop with the following options: ### Text Component Configuration Global settings for all Text components within HeroUI Native. These props are carefully selected to include only those that make sense to configure globally across all Text components in the application: ```tsx import { HeroUINativeProvider } from 'heroui-native'; import type { HeroUINativeConfig } from 'heroui-native'; const config: HeroUINativeConfig = { textProps: { // Disable font scaling for accessibility allowFontScaling: false, // Auto-adjust font size to fit container adjustsFontSizeToFit: false, // Maximum font size multiplier when scaling maxFontSizeMultiplier: 1.5, // Minimum font scale (iOS only, 0.01-1.0) minimumFontScale: 0.5, }, }; export default function App() { return ( {/* Your app content */} ); } ``` ### Animation Configuration Global animation configuration for the entire application: ```tsx const config: HeroUINativeConfig = { // Disable all animations across the application (cascades to all children) animation: 'disable-all', }; ``` **Note**: When set to `'disable-all'`, all animations across the application will be disabled. This is useful for accessibility or performance optimization. ### Developer Information Configuration Control developer-facing informational messages displayed in the console: ```tsx const config: HeroUINativeConfig = { devInfo: { // Disable styling principles information message stylingPrinciples: false, }, }; ``` **Note**: By default, informational messages are enabled. Set `stylingPrinciples: false` to disable the styling principles message that appears in the console during development. ### Toast Configuration Configure the global toast system including insets, default props, and wrapper components. You can also disable the toast provider entirely: **Option 1: Disable Toast Provider** ```tsx const config: HeroUINativeConfig = { // Disable toast provider entirely toast: false, // or toast: 'disabled', }; ``` **Note**: When toast is disabled (`false` or `'disabled'`), the `ToastProvider` will not be rendered, and toast functionality will not be available in your application. **Option 2: Configure Toast Provider** ```tsx import { KeyboardAvoidingView } from 'react-native'; const config: HeroUINativeConfig = { toast: { // Global toast configuration (used as defaults for all toasts) defaultProps: { variant: 'default', placement: 'top', isSwipeable: true, animation: true, }, // Insets for spacing from screen edges (added to safe area insets) insets: { top: 0, // Default: iOS = 0, Android = 12 bottom: 6, // Default: iOS = 6, Android = 12 left: 12, // Default: 12 right: 12, // Default: 12 }, // Maximum number of visible toasts before opacity starts fading maxVisibleToasts: 3, // Custom wrapper function to wrap the toast content contentWrapper: (children) => ( {children} ), }, }; ``` ## Complete Example Here's a comprehensive example showing all configuration options: ```tsx import { HeroUINativeProvider } from 'heroui-native'; import type { HeroUINativeConfig } from 'heroui-native'; import { GestureHandlerRootView } from 'react-native-gesture-handler'; const config: HeroUINativeConfig = { // Global text configuration textProps: { minimumFontScale: 0.5, maxFontSizeMultiplier: 1.5, allowFontScaling: true, adjustsFontSizeToFit: false, }, // Global animation configuration animation: 'disable-all', // Optional: disable all animations // Developer information messages configuration devInfo: { stylingPrinciples: true, // Optional: disable styling principles message }, // Global toast configuration // Option 1: Configure toast with custom settings toast: { defaultProps: { variant: 'default', placement: 'top', }, insets: { top: 0, bottom: 6, left: 12, right: 12, }, maxVisibleToasts: 3, }, // Option 2: Disable toast entirely // toast: false, // or // toast: 'disabled', }; export default function App() { return ( ); } ``` ## Integration with Expo Router When using Expo Router, wrap your root layout: ```tsx // app/_layout.tsx import { HeroUINativeProvider } from 'heroui-native'; import type { HeroUINativeConfig } from 'heroui-native'; import { Stack } from 'expo-router'; const config: HeroUINativeConfig = { textProps: { minimumFontScale: 0.5, maxFontSizeMultiplier: 1.5, }, }; export default function RootLayout() { return ( ); } ``` ## Architecture ### Provider Hierarchy The `HeroUINativeProvider` internally composes multiple providers: ``` HeroUINativeProvider ├── SafeAreaListener (handles safe area insets updates) │ └── GlobalAnimationSettingsProvider (animation configuration) │ └── TextComponentProvider (text configuration) │ └── ToastProvider (toast configuration, conditionally rendered) │ └── Your App │ └── PortalHost (for overlays) ``` **Note**: The `ToastProvider` is conditionally rendered based on the `toast` configuration. If `toast` is set to `false` or `'disabled'`, the `ToastProvider` will not be rendered, and the app content and `PortalHost` will be rendered directly under `TextComponentProvider`. ### Safe Area Insets Handling The provider automatically wraps your application with [`SafeAreaListener`](https://appandflow.github.io/react-native-safe-area-context/api/safe-area-listener) from `react-native-safe-area-context`. This component listens to safe area insets and frame changes without triggering re-renders, and automatically updates Uniwind with the latest insets via the `onChange` callback. ## Raw Provider `HeroUINativeProviderRaw` is a lightweight variant of `HeroUINativeProvider` designed for bundle optimization. It excludes `ToastProvider` and `PortalHost`, giving you a bare minimum starting point where you only install and add what you actually need. ### When to Use Use `HeroUINativeProviderRaw` when you want full control over which dependencies are included in your bundle. With the raw provider imported from `heroui-native/provider-raw`, the following dependencies are optional and only required if you use the corresponding components: * **react-native-screens** -- required for overlay components (Popover, Dialog) * **@gorhom/bottom-sheet** -- required for BottomSheet component * **react-native-svg** -- required for components that use icons (Accordion, Alert, Checkbox, etc.) ### Setup ```tsx import { HeroUINativeProviderRaw, type HeroUINativeConfigRaw, } from 'heroui-native/provider-raw'; import { GestureHandlerRootView } from 'react-native-gesture-handler'; const config: HeroUINativeConfigRaw = { textProps: { maxFontSizeMultiplier: 1.5, }, }; export default function App() { return ( {/* Your app content */} ); } ``` ### Adding Toast and Portal Manually If you need toast or portal functionality with the raw provider, add them yourself: ```tsx import { HeroUINativeProviderRaw } from 'heroui-native/provider-raw'; import { PortalHost } from 'heroui-native/portal'; import { ToastProvider } from 'heroui-native/toast'; export default function App() { return ( {/* Your app content */} ); } ``` ### Provider Hierarchy ``` HeroUINativeProviderRaw ├── SafeAreaListener (handles safe area insets updates) │ └── GlobalAnimationSettingsProvider (animation configuration) │ └── TextComponentProvider (text configuration) │ └── Your App ``` ## Best Practices ### 1. Single Provider Instance Always use a single `HeroUINativeProvider` at the root of your app. Don't nest multiple providers: ```tsx // ❌ Bad {/* Don't do this */} // ✅ Good ``` ### 2. Configuration Object Define your configuration outside the component to prevent recreating on each render: ```tsx // ❌ Bad function App() { return ( {/* ... */} ); } // ✅ Good const config: HeroUINativeConfig = { textProps: { maxFontSizeMultiplier: 1.5, }, }; function App() { return ( {/* ... */} ); } ``` ### 3. Text Configuration Consider accessibility when configuring text props: ```tsx const config: HeroUINativeConfig = { textProps: { // Allow font scaling for accessibility allowFontScaling: true, // But limit maximum scale maxFontSizeMultiplier: 1.5, }, }; ``` ## TypeScript Support The provider is fully typed. Import types for better IDE support: ```tsx import { HeroUINativeProvider, type HeroUINativeConfig } from 'heroui-native'; const config: HeroUINativeConfig = { // Full type safety and autocomplete textProps: { allowFontScaling: true, maxFontSizeMultiplier: 1.5, }, animation: 'disable-all', // Optional: disable all animations devInfo: { stylingPrinciples: true, // Optional: disable styling principles message }, // Toast configuration options: // - false or 'disabled': Disable toast provider // - ToastProviderProps object: Configure toast settings toast: { defaultProps: { variant: 'default', placement: 'top', }, insets: { top: 0, bottom: 6, left: 12, right: 12, }, }, }; ``` ## Related * [Quick Start](/docs/native/getting-started/quick-start) - Basic setup guide * [Theming](/docs/native/getting-started/theming) - Customize colors and themes * [Styling](/docs/native/getting-started/styling) - Style components with Tailwind # Styling **Category**: native **URL**: https://www.heroui.com/en/docs/native/getting-started/styling **Source**: https://raw.githubusercontent.com/heroui-inc/heroui/refs/heads/v3/apps/docs/content/docs/en/native/getting-started/(handbook)/styling.mdx > Style HeroUI Native components with Tailwind or StyleSheet API HeroUI Native components provide flexible styling options: Tailwind CSS utilities, StyleSheet API, and render props for dynamic styling. ## Styling Principles HeroUI Native is built with `className` as the go-to styling solution. You can use Tailwind CSS classes via the `className` prop on all components. **StyleSheet precedence:** The `style` prop (StyleSheet API) can be used and has precedence over `className` when both are provided. This allows you to override Tailwind classes when needed. **Animated styles:** Some style properties are animated using `react-native-reanimated` and, like StyleSheet styles, they have precedence over `className`. To identify which styles are animated and cannot be used via `className`: * **Hover over `className` in your IDE** - The TypeScript definitions will show which properties are available * **Check component documentation** - Each component page includes a link to the component's style source at the top, which contains notes about animated properties **Customizing animated styles:** If styles are occupied by animation, you can modify them via the `animation` prop on components that support it. ## Basic Styling **Using className:** All HeroUI Native components accept `className` props: ```tsx import { Button } from 'heroui-native'; ; ``` **Using style:** Components also accept inline styles via the `style` prop: ```tsx import { Button } from 'heroui-native'; ; ``` ## Render Props Use a render function to access component state and customize content dynamically: ```tsx import { RadioGroup, Label, cn } from 'heroui-native'; {({ isSelected, isInvalid, isDisabled }) => ( <> {isSelected && } )} ; ``` ## Creating Wrapper Components Create reusable custom components using [tailwind-variants](https://tailwind-variants.org/)—a Tailwind CSS first-class variant API: ```tsx import { Button } from 'heroui-native'; import type { ButtonRootProps } from 'heroui-native'; import { tv, type VariantProps } from 'tailwind-variants'; const customButtonVariants = tv({ base: 'font-semibold rounded-lg', variants: { intent: { primary: 'bg-blue-500', secondary: 'bg-gray-200', danger: 'bg-red-500', }, }, defaultVariants: { intent: 'primary', }, }); const customLabelVariants = tv({ base: '', variants: { intent: { primary: 'text-white', secondary: 'text-gray-800', danger: 'text-white', }, }, defaultVariants: { intent: 'primary', }, }); type CustomButtonVariants = VariantProps; interface CustomButtonProps extends Omit, CustomButtonVariants { className?: string; labelClassName?: string; } export function CustomButton({ intent, className, labelClassName, children, ...props }: CustomButtonProps) { return ( ); } ``` ## Using Component classNames Each HeroUI Native component exports a `classNames` object that contains the same styling functions used internally by the component. This is particularly useful when you want to style your own custom components to match the appearance of HeroUI Native components. For example, you can style a custom `Link` component to look like a `Button`: ```tsx import { buttonClassNames, cn } from 'heroui-native'; import { Pressable, Text } from 'react-native'; interface LinkProps { href: string; variant?: 'primary' | 'secondary' | 'outline' | 'ghost'; size?: 'sm' | 'md' | 'lg'; children: React.ReactNode; className?: string; } export function Link({ href, variant = 'primary', size = 'md', children, className, }: LinkProps) { return ( { // Handle navigation }} > {children} ); } ``` **Available classNames exports:** Each component exports its `classNames` object. For example: * `buttonClassNames` - Contains `root` and `label` functions * `cardClassNames` - Contains `root`, `header`, `body`, `footer`, `label`, and `description` functions * `chipClassNames` - Contains `root` and `label` functions * And many more... **Usage pattern:** ```tsx import { buttonClassNames } from 'heroui-native'; // Use with variant and size options const rootClasses = buttonClassNames.root({ variant: 'primary', size: 'md', className: 'custom-class', // Optional: merge with your own classes }); const labelClasses = buttonClassNames.label({ variant: 'primary', size: 'md', }); ``` The `classNames` functions accept the same variant props as the components themselves, allowing you to maintain visual consistency across your custom components and HeroUI Native components. ## Responsive Design HeroUI Native supports Tailwind's responsive breakpoint system via [Uniwind](https://docs.uniwind.dev/breakpoints). Use breakpoint prefixes like `sm:`, `md:`, `lg:`, and `xl:` to apply styles conditionally based on screen width. **Mobile-first approach:** Start with mobile styles (no prefix), then use breakpoints to enhance for larger screens. ### Responsive Typography and Spacing ```tsx import { Button } from 'heroui-native'; import { View, Text } from 'react-native'; Responsive Heading ; ``` ### Responsive Layouts ```tsx import { View, Text } from 'react-native'; {/* Mobile: 1 column, Tablet: 2 columns, Desktop: 3 columns */} Item 1 ; ``` **Default breakpoints:** * `sm`: 640px * `md`: 768px * `lg`: 1024px * `xl`: 1280px * `2xl`: 1536px For custom breakpoints and more details, see the [Uniwind breakpoints documentation](https://docs.uniwind.dev/breakpoints). ## Utilities HeroUI Native provides utility functions to assist with styling components. ### cn Utility The `cn` utility function merges Tailwind CSS classes with proper conflict resolution. It's particularly useful when combining conditional classes or merging classes from props: ````tsx import { cn } from 'heroui-native'; import { View } from 'react-native'; function MyComponent({ className, isActive }) { return ( ); } ```; The `cn` utility is powered by `tailwind-variants` and includes: - Automatic Tailwind class merging (`twMerge: true`) - Custom opacity class group support - Proper conflict resolution (later classes override earlier ones) **Example with conflicts:** ```tsx // 'bg-accent' overrides 'bg-background' cn('bg-background p-4', 'bg-accent'); // Result: 'p-4 bg-accent' ```` ### useThemeColor Hook Retrieves theme color values from CSS variables. Supports both single color and multiple colors for efficient batch retrieval. **Single color usage:** ````tsx import { useThemeColor } from 'heroui-native'; function MyComponent() { const accentColor = useThemeColor('accent'); const dangerColor = useThemeColor('danger'); return ( Error message ); } ```; **Multiple colors usage (more efficient):** ```tsx import { useThemeColor } from 'heroui-native'; function MyComponent() { const [accentColor, backgroundColor, dangerColor] = useThemeColor([ 'accent', 'background', 'danger', ]); return ( Error message ); } ```; **Type signatures:** ```tsx // Single color useThemeColor(themeColor: ThemeColor): string // Multiple colors (with type inference for tuples) useThemeColor( themeColor: T ): CreateStringTuple // Multiple colors (array) useThemeColor(themeColor: ThemeColor[]): string[] ```` Available theme colors include: `background`, `foreground`, `surface`, `accent`, `default`, `success`, `warning`, `danger`, and all their variants (hover, soft, foreground, etc.), plus semantic colors like `muted`, `border`, `separator`, `field`, `overlay`, and more. ## Next Steps * Learn about [Animation](/docs/native/getting-started/animation) techniques * Explore [Theming](/docs/native/getting-started/theming) system * Explore [Colors](/docs/native/getting-started/colors) documentation # Theming **Category**: native **URL**: https://www.heroui.com/en/docs/native/getting-started/theming **Source**: https://raw.githubusercontent.com/heroui-inc/heroui/refs/heads/v3/apps/docs/content/docs/en/native/getting-started/(handbook)/theming.mdx > Customize HeroUI Native's design system with CSS variables and global styles HeroUI Native uses CSS variables for theming. Customize everything from colors to component styles using standard CSS. ## How It Works HeroUI Native's theming system is built on top of [Tailwind CSS v4](https://tailwindcss.com/docs/theme)'s theme via [Uniwind](https://uniwind.dev/). When you import `heroui-native/styles`, it uses Tailwind's built-in color palettes, maps them to semantic variables, automatically switches between light and dark themes, and uses CSS layers and the `@theme` directive for organization. **Naming pattern:** * Colors without a suffix are backgrounds (e.g., `--accent`) * Colors with `-foreground` are for text on that background (e.g., `--accent-foreground`) ## Quick Start **Apply colors in your components:** ```tsx import { View, Text } from 'react-native'; Your app content ; ``` **Switch themes:** HeroUI Native automatically supports dark mode through [Uniwind](https://docs.uniwind.dev/theming/basics). The theme switches between light and dark variants based on system preferences or manual selection: ```tsx import { Uniwind, useUniwind } from 'uniwind'; import { Button } from 'heroui-native'; function ThemeToggle() { const { theme } = useUniwind(); return ( ); } ``` **Override colors:** ```css /* global.css */ @layer theme { @variant light { /* Override any color variable */ --accent: oklch(0.65 0.25 270); /* Custom indigo accent */ --success: oklch(0.65 0.15 155); } @variant dark { --accent: oklch(0.65 0.25 270); --success: oklch(0.75 0.12 155); } } ``` > **Note**: See [Colors](/docs/native/getting-started/colors) for the complete color palette and visual reference. **Create your own theme:** Create multiple themes using Uniwind's variant system. For complete custom theme documentation, see the [Uniwind Custom Themes Guide](https://docs.uniwind.dev/theming/custom-themes). **Important:** All themes must define the same variables. See the [Default Theme](/docs/native/getting-started/colors#default-theme) section for a complete list of all required variables. ```css /* global.css */ @layer theme { :root { @variant ocean-light { /* Base Colors */ --background: oklch(0.95 0.02 230); --foreground: oklch(0.25 0.04 230); /* Surface: Used for non-overlay components (cards, accordions, disclosure groups) */ --surface: oklch(0.98 0.01 230); --surface-foreground: oklch(0.3 0.045 230); --surface-secondary: oklch(0.96 0.012 230); --surface-secondary-foreground: oklch(0.3 0.045 230); --surface-tertiary: oklch(0.94 0.015 230); --surface-tertiary-foreground: oklch(0.3 0.045 230); /* Overlay: Used for floating/overlay components (dialogs, popovers, modals, menus) */ --overlay: oklch(0.998 0.003 230); --overlay-foreground: oklch(0.3 0.045 230); --backdrop: oklch(0% 0 0 / 20%); --muted: oklch(0.55 0.035 230); --default: oklch(0.94 0.018 230); --default-foreground: oklch(0.4 0.05 230); /* Accent */ --accent: oklch(0.6 0.2 230); --accent-foreground: oklch(0.98 0.005 230); /* Form Field Defaults - Colors */ --field-background: oklch(0.98 0.01 230); --field-foreground: oklch(0.25 0.04 230); --field-placeholder: var(--muted); --field-border: transparent; /* Status Colors */ --success: oklch(0.72 0.14 165); --success-foreground: oklch(0.25 0.08 165); --warning: oklch(0.78 0.12 85); --warning-foreground: oklch(0.3 0.08 85); --danger: oklch(0.68 0.18 15); --danger-foreground: oklch(0.98 0.005 15); /* Component Colors */ --segment: oklch(0.98 0.01 230); --segment-foreground: oklch(0.25 0.04 230); /* Misc Colors */ --border: oklch(0 0 0 / 0%); --separator: oklch(0.91 0.015 230); --focus: var(--accent); --link: oklch(0.62 0.17 230); /* Shadows */ --surface-shadow: 0 2px 4px 0 rgba(0, 0, 0, 0.04), 0 1px 2px 0 rgba(0, 0, 0, 0.06), 0 0 1px 0 rgba(0, 0, 0, 0.06); --overlay-shadow: 0 2px 8px 0 rgba(0, 0, 0, 0.02), 0 -6px 12px 0 rgba(0, 0, 0, 0.01), 0 14px 28px 0 rgba(0, 0, 0, 0.03); --field-shadow: 0 2px 4px 0 rgba(0, 0, 0, 0.04), 0 1px 2px 0 rgba(0, 0, 0, 0.06), 0 0 1px 0 rgba(0, 0, 0, 0.06); } @variant ocean-dark { /* Base Colors */ --background: oklch(0.15 0.04 230); --foreground: oklch(0.94 0.01 230); /* Surface: Used for non-overlay components (cards, accordions, disclosure groups) */ --surface: oklch(0.2 0.048 230); --surface-foreground: oklch(0.9 0.015 230); --surface-secondary: oklch(0.24 0.046 230); --surface-secondary-foreground: oklch(0.9 0.015 230); --surface-tertiary: oklch(0.27 0.044 230); --surface-tertiary-foreground: oklch(0.9 0.015 230); /* Overlay: Used for floating/overlay components (dialogs, popovers, modals, menus) */ --overlay: oklch(0.23 0.045 230); --overlay-foreground: oklch(0.9 0.015 230); --backdrop: oklch(0% 0 0 / 20%); --muted: oklch(0.5 0.04 230); --default: oklch(0.25 0.05 230); --default-foreground: oklch(0.88 0.018 230); /* Accent */ --accent: oklch(0.72 0.21 230); --accent-foreground: oklch(0.15 0.04 230); /* Form Field Defaults - Colors */ --field-background: var(--default); --field-foreground: var(--foreground); --field-placeholder: var(--muted); --field-border: transparent; /* Status Colors */ --success: oklch(0.68 0.16 165); --success-foreground: oklch(0.95 0.008 165); --warning: oklch(0.75 0.14 90); --warning-foreground: oklch(0.2 0.04 90); --danger: oklch(0.65 0.2 20); --danger-foreground: oklch(0.95 0.008 20); /* Component Colors */ --segment: oklch(0.22 0.046 230); --segment-foreground: oklch(0.9 0.015 230); /* Misc Colors */ --border: oklch(0 0 0 / 0%); --separator: oklch(0.28 0.045 230); --focus: var(--accent); --link: oklch(0.75 0.18 230); /* Shadows */ --surface-shadow: 0 0 0 0 transparent inset; /* No shadow on dark mode */ --overlay-shadow: 0 0 1px 0 rgba(255, 255, 255, 0.3) inset; --field-shadow: 0 0 0 0 transparent inset; /* Transparent shadow to allow ring utilities to work */ } } } ``` **Important:** When adding custom themes, you must register them in your Metro config: ```js // metro.config.js const { withUniwindConfig } = require('uniwind/metro'); const { wrapWithReanimatedMetroConfig, } = require('react-native-reanimated/metro-config'); const config = { // ... your existing config }; module.exports = withUniwindConfig(wrapWithReanimatedMetroConfig(config), { cssEntryFile: './global.css', dtsFile: './src/uniwind.d.ts', extraThemes: ['ocean-light', 'ocean-dark'], }); ``` Apply themes in your app: ```tsx import { Uniwind } from 'uniwind'; import { Button } from 'heroui-native'; function App() { return ( ); } ``` ## Adding Custom Colors Add your own semantic colors to the theme: ```css @layer theme { @variant light { --info: oklch(0.6 0.15 210); --info-foreground: oklch(0.98 0 0); } @variant dark { --info: oklch(0.7 0.12 210); --info-foreground: oklch(0.15 0 0); } } /* Make the color available to Tailwind */ @theme inline { --color-info: var(--info); --color-info-foreground: var(--info-foreground); } ``` Now use it in your components: ```tsx import { View, Text } from 'react-native'; Info message ; ``` ## Custom Fonts To use a custom font family in your app, you need to load the fonts and then override the font CSS variables. ### 1. Load Fonts in Your App First, load your custom fonts (using Expo's `useFonts` hook for example): ```tsx import { useFonts } from 'expo-font'; import { HeroUINativeProvider } from 'heroui-native'; import { YourFont_400Regular, YourFont_500Medium, YourFont_600SemiBold, } from '@expo-google-fonts/your-font'; export default function App() { const [fontsLoaded] = useFonts({ YourFont_400Regular, YourFont_500Medium, YourFont_600SemiBold, }); if (!fontsLoaded) { return null; // Or return a loading screen } return {/* Your app content */}; } ``` ### 2. Configure Font CSS Variables After loading the fonts, override the font CSS variables in your `global.css` file: ```css @theme { --font-normal: 'YourFont-400Regular'; --font-medium: 'YourFont-500Medium'; --font-semibold: 'YourFont-600SemiBold'; } ``` **Note:** The font names in CSS variables should match the PostScript names of your loaded fonts. Check your font package documentation or use the font names exactly as they appear in your `useFonts` hook. All HeroUI Native components automatically use these font variables, ensuring consistent typography throughout your app. ## Variables Reference HeroUI defines three types of variables: 1. **Base Variables** — Non-changing values like `--white`, `--black` 2. **Theme Variables** — Colors that change between light/dark themes 3. **Calculated Variables** — Automatically generated hover (pressed) states and size variants For a complete reference, see: [Colors Documentation](/docs/native/getting-started/colors), [Default Theme Variables](https://github.com/heroui-inc/heroui-native/blob/main/src/styles/variables.css), [Shared Theme Utilities](https://github.com/heroui-inc/heroui-native/blob/main/src/styles/theme.css) **Calculated variables (Tailwind):** We use Tailwind's `@theme` directive to automatically create calculated variables for hover (pressed) states and radius variants. These are defined in [theme.css](https://github.com/heroui-inc/heroui-native/blob/main/src/styles/theme.css): ```css @theme inline static { --color-background: var(--background); --color-foreground: var(--foreground); --color-surface: var(--surface); --color-surface-foreground: var(--surface-foreground); --color-surface-hover: color-mix(in oklab, var(--surface) 92%, var(--surface-foreground) 8%); --color-surface-secondary: var(--surface-secondary); --color-surface-secondary-foreground: var(--surface-secondary-foreground); --color-surface-tertiary: var(--surface-tertiary); --color-surface-tertiary-foreground: var(--surface-tertiary-foreground); --color-overlay: var(--overlay); --color-overlay-foreground: var(--overlay-foreground); --color-backdrop: var(--backdrop); --color-muted: var(--muted); --color-accent: var(--accent); --color-accent-foreground: var(--accent-foreground); --color-segment: var(--segment); --color-segment-foreground: var(--segment-foreground); --color-border: var(--border); --color-separator: var(--separator); --color-focus: var(--focus); --color-link: var(--link); --color-default: var(--default); --color-default-foreground: var(--default-foreground); --color-success: var(--success); --color-success-foreground: var(--success-foreground); --color-warning: var(--warning); --color-warning-foreground: var(--warning-foreground); --color-danger: var(--danger); --color-danger-foreground: var(--danger-foreground); /* Form Field Tokens */ --color-field: var(--field-background, var(--default)); --color-field-foreground: var(--field-foreground, var(--foreground)); --color-field-placeholder: var(--field-placeholder, var(--muted)); --color-field-border: var(--field-border, var(--border)); --radius-field: var(--field-radius, var(--radius-xl)); --border-width-field: var(--field-border-width, var(--border-width)); --shadow-surface: var(--surface-shadow); --shadow-overlay: var(--overlay-shadow); --shadow-field: var(--field-shadow); /* Calculated Variables */ /* Colors */ /* --- background shades --- */ --color-background-secondary: color-mix(in oklab, var(--background) 96%, var(--foreground) 4%); --color-background-tertiary: color-mix(in oklab, var(--background) 92%, var(--foreground) 8%); --color-background-inverse: var(--foreground); /* ------------------------- */ --color-default-hover: color-mix(in oklab, var(--default) 96%, var(--default-foreground) 4%); --color-accent-hover: color-mix(in oklab, var(--accent) 90%, var(--accent-foreground) 10%); --color-success-hover: color-mix(in oklab, var(--success) 90%, var(--success-foreground) 10%); --color-warning-hover: color-mix(in oklab, var(--warning) 90%, var(--warning-foreground) 10%); --color-danger-hover: color-mix(in oklab, var(--danger) 90%, var(--danger-foreground) 10%); /* Form Field Colors */ --color-field-hover: color-mix(in oklab, var(--field-background, var(--default)) 90%, var(--field-foreground, var(--foreground)) 2%); --color-field-focus: var(--field-background, var(--default)); --color-field-border-hover: color-mix(in oklab, var(--field-border, var(--border)) 88%, var(--field-foreground, var(--foreground)) 10%); --color-field-border-focus: color-mix(in oklab, var(--field-border, var(--border)) 74%, var(--field-foreground, var(--foreground)) 22%); /* Soft Colors */ --color-accent-soft: color-mix(in oklab, var(--accent) 15%, transparent); --color-accent-soft-foreground: var(--accent); --color-accent-soft-hover: color-mix(in oklab, var(--accent) 20%, transparent); --color-danger-soft: color-mix(in oklab, var(--danger) 15%, transparent); --color-danger-soft-foreground: var(--danger); --color-danger-soft-hover: color-mix(in oklab, var(--danger) 20%, transparent); --color-warning-soft: color-mix(in oklab, var(--warning) 15%, transparent); --color-warning-soft-foreground: var(--warning); --color-warning-soft-hover: color-mix(in oklab, var(--warning) 20%, transparent); --color-success-soft: color-mix(in oklab, var(--success) 15%, transparent); --color-success-soft-foreground: var(--success); --color-success-soft-hover: color-mix(in oklab, var(--success) 20%, transparent); /* Separator Colors - Levels */ --color-separator-secondary: color-mix(in oklab, var(--surface) 85%, var(--surface-foreground) 15%); --color-separator-tertiary: color-mix(in oklab, var(--surface) 81%, var(--surface-foreground) 19%); /* Border Colors - Levels (progressive contrast: default → secondary → tertiary) */ /* Light mode: lighter → darker | Dark mode: darker → lighter */ --color-border-secondary: color-mix(in oklab, var(--surface) 78%, var(--surface-foreground) 22%); --color-border-tertiary: color-mix(in oklab, var(--surface) 66%, var(--surface-foreground) 34%); /* Radius and default sizes - defaults can change by just changing the --radius */ --radius-xs: calc(var(--radius) * 0.25); /* 0.125rem (2px) */ --radius-sm: calc(var(--radius) * 0.5); /* 0.25rem (4px) */ --radius-md: calc(var(--radius) * 0.75); /* 0.375rem (6px) */ --radius-lg: calc(var(--radius) * 1); /* 0.5rem (8px) */ --radius-xl: calc(var(--radius) * 1.5); /* 0.75rem (12px) */ --radius-2xl: calc(var(--radius) * 2); /* 1rem (16px) */ --radius-3xl: calc(var(--radius) * 3); /* 1.5rem (24px) */ --radius-4xl: calc(var(--radius) * 4); /* 2rem (32px) */ } ``` Form controls now rely on the `--field-*` variables and their calculated hover/focus variants. Update them in your theme to restyle inputs, checkboxes, radios, and OTP slots without impacting surfaces like buttons or cards. ## Vibrant Palette By default, HeroUI Native uses accessible soft foreground colors that mix the semantic color with the foreground for better contrast on soft backgrounds. If you prefer more saturated, vibrant soft foreground colors, import the optional `heroui-native/styles/vibrant` stylesheet alongside the base styles: ```css /* global.css */ @import "heroui-native/styles"; @import "heroui-native/styles/vibrant"; /* [!code highlight] */ ``` This switches all `*-soft-foreground` variables (accent, success, warning, danger) to use 92% of the semantic color with only 8% foreground mixed in — closer to the raw color but with a slight contrast boost. Components such as [Alert](/docs/native/components/alert), [Avatar](/docs/native/components/avatar), [Button](/docs/native/components/button), [Chip](/docs/native/components/chip), and [Toast](/docs/native/components/toast) automatically pick up the new soft foreground colors on their soft variants — no component prop changes are required. | Mode | Accessible (default) | Vibrant | | --------------- | -------------------------------------------- | ------------------------------------- | | Soft foreground | `color-mix(color 70-80%, foreground 30-40%)` | `color-mix(color 92%, foreground 8%)` | The vibrant palette prioritizes visual saturation over contrast. It may not meet WCAG accessibility guidelines for some color combinations, especially with lighter accent colors. The optional vibrant palette is available starting from [v1.0.4](/docs/native/releases/v1-0-4). ## Resources * [Colors Documentation](/docs/native/getting-started/colors) * [Styling Guide](/docs/native/getting-started/styling) * [Tailwind CSS v4 Theming](https://tailwindcss.com/docs/theme) * [OKLCH Color Tool](https://oklch.com) # Design Principles **Category**: native **URL**: https://www.heroui.com/en/docs/native/getting-started/design-principles **Source**: https://raw.githubusercontent.com/heroui-inc/heroui/refs/heads/v3/apps/docs/content/docs/en/native/getting-started/(overview)/design-principles.mdx > Core principles that guide HeroUI v3's design and development HeroUI Native follows 9 core principles that prioritize clarity, accessibility, customization, and developer experience. ## Core Principles ### 1. Semantic Intent Over Visual Style Use semantic naming (primary, secondary, tertiary) instead of visual descriptions (solid, flat, bordered). Inspired by [Uber's Base design system](https://base.uber.com/6d2425e9f/p/756216-button), variants follow a clear hierarchy: ```tsx // ✅ Semantic variants communicate hierarchy ``` | Variant | Purpose | Usage | | ------------- | --------------------------------- | ---------------- | | **Primary** | Main action to move forward | 1 per context | | **Secondary** | Alternative actions | Multiple allowed | | **Tertiary** | Dismissive actions (cancel, skip) | Sparingly | | **Danger** | Destructive actions | When needed | ### 2. Accessibility as Foundation Accessibility follows mobile development best practices with proper touch accessibility, focus management, and screen reader support built into every component. All components include proper accessibility labels and semantic structure for VoiceOver (iOS) and TalkBack (Android). ```tsx import { Tabs } from 'heroui-native'; Profile Security Content Content ``` ### 3. Composition Over Configuration Compound components let you rearrange, customize, or omit parts as needed. Use dot notation to compose components exactly as you need them. ```tsx // Compose parts to build exactly what you need import { Accordion } from 'heroui-native'; Question Text Answer content ``` ### 4. Progressive Disclosure Start simple, add complexity only when needed. Components work with minimal props and scale up as requirements grow. ```tsx import { Button, Spinner } from 'heroui-native'; import { Feather } from '@expo/vector-icons'; // Level 1: Minimal // Level 2: Enhanced // Level 3: Advanced ``` ### 5. Predictable Behavior Consistent patterns across all components: sizes (`sm`, `md`, `lg`), variants, and className support. Same API, same behavior. ```tsx import { Button, Chip, Avatar } from 'heroui-native'; // All components follow the same patterns Success JD ``` ### 6. Type Safety First Full TypeScript support with IntelliSense, auto-completion, and compile-time error detection. Extend types for custom components. ```tsx import type { ButtonRootProps } from 'heroui-native'; // Type-safe props and event handlers // Extend types for custom components interface CustomButtonProps extends Omit { intent: 'save' | 'cancel' | 'delete'; } ``` ### 7. Developer Experience Excellence Clear APIs, descriptive errors, IntelliSense and AI-friendly markdown docs. ### 8. Complete Customization Beautiful defaults out-of-the-box. Transform the entire look with CSS variables through [Uniwind's theming system](https://docs.uniwind.dev/theming/basics). Every slot is customizable. ```css /* Custom colors using Uniwind's theme layer */ @layer theme { @variant light { --accent: oklch(0.65 0.25 270); /* Custom indigo accent */ --background: oklch(0.98 0 0); /* Custom background */ } @variant dark { --accent: oklch(0.65 0.25 270); --background: oklch(0.15 0 0); } } /* Radius customization */ @theme { --radius: 0.75rem; /* Increase for rounder components */ } ``` ### 9. Open and Extensible Wrap, extend, and customize components to match your needs. Create custom wrappers or apply custom styles using className. ```tsx import { Button } from 'heroui-native'; import type { ButtonRootProps } from 'heroui-native'; // Custom wrapper component interface CTAButtonProps extends Omit { intent?: 'primary-cta' | 'secondary-cta' | 'minimal'; } const CTAButton = ({ intent = 'primary-cta', children, ...props }: CTAButtonProps) => { const variantMap = { 'primary-cta': 'primary', 'secondary-cta': 'secondary', 'minimal': 'ghost' } as const; return ( ); }; // Usage Get Started Learn More ``` **Extend with Tailwind Variants:** ```tsx import { Button } from 'heroui-native'; import { tv } from 'tailwind-variants'; // Extend button styles with custom variants const myButtonVariants = tv({ base: 'px-4 py-2 rounded-lg', variants: { variant: { 'primary-cta': 'bg-accent px-8 py-4 shadow-lg', 'secondary-cta': 'border-2 border-accent px-6 py-3', } }, defaultVariants: { variant: 'primary-cta', } }); // Label variants for text colors (must be applied to Button.Label) const myLabelVariants = tv({ base: '', variants: { variant: { 'primary-cta': 'text-accent-foreground', 'secondary-cta': 'text-accent', } }, defaultVariants: { variant: 'primary-cta', } }); // Use the custom variants function CustomButton({ variant, className, labelClassName, children, ...props }) { return ( ); } // Usage Get Started Learn More ``` # Quick Start **Category**: native **URL**: https://www.heroui.com/en/docs/native/getting-started/quick-start **Source**: https://raw.githubusercontent.com/heroui-inc/heroui/refs/heads/v3/apps/docs/content/docs/en/native/getting-started/(overview)/quick-start.mdx > Get up and running with HeroUI Native Choose the path that fits your project: * **Option 1** — Scaffold a new, preconfigured project with our CLI. Zero setup. * **Option 2** — Add HeroUI Native to an existing React Native or Expo project. ## Option 1: Create a New Project The fastest way to start. The CLI scaffolds an Expo project with HeroUI Native, all required peer dependencies, Uniwind / Tailwind CSS, global styles, and the `HeroUINativeProvider` already wired up — so you can jump straight to building. ```bash npx create-heroui-native-app@latest ``` ```bash pnpm create heroui-native-app@latest ``` ```bash yarn create heroui-native-app ``` ```bash bun create heroui-native-app@latest ``` Follow the interactive prompts, then start the dev server: ```bash cd my-app npm run start ``` You're ready to build. Skip ahead to [Use Your First Component](#use-your-first-component) or [browse components](/docs/native/components). The scaffold includes Expo with TypeScript, Uniwind + Tailwind CSS preconfigured, `global.css` with the required imports, and the app entry already wrapped in `GestureHandlerRootView` and `HeroUINativeProvider`. ## Option 2: Add to an Existing Project If you already have a React Native or Expo app, follow these steps to install and configure HeroUI Native manually. **Prefer to let your AI assistant do it?** Install the [HeroUI Native MCP Server](/docs/native/getting-started/mcp-server) in your editor, then paste the prompt into your AI assistant — it will analyze your project and handle the entire setup for you. ### 1. Install HeroUI Native ```bash npm install heroui-native ``` ```bash pnpm add heroui-native ``` ```bash yarn add heroui-native ``` ```bash bun add heroui-native ``` ### 2. Install Mandatory Peer Dependencies ```bash npm install react-native-reanimated@^4.1.1 react-native-gesture-handler@^2.28.0 react-native-worklets@^0.5.1 react-native-safe-area-context@^5.6.0 react-native-svg@^15.12.1 tailwind-variants@^3.2.2 tailwind-merge@^3.4.0 ``` ```bash pnpm add react-native-reanimated@^4.1.1 react-native-gesture-handler@^2.28.0 react-native-worklets@^0.5.1 react-native-safe-area-context@^5.6.0 react-native-svg@^15.12.1 tailwind-variants@^3.2.2 tailwind-merge@^3.4.0 ``` ```bash yarn add react-native-reanimated@^4.1.1 react-native-gesture-handler@^2.28.0 react-native-worklets@^0.5.1 react-native-safe-area-context@^5.6.0 react-native-svg@^15.12.1 tailwind-variants@^3.2.2 tailwind-merge@^3.4.0 ``` ```bash bun add react-native-reanimated@^4.1.1 react-native-gesture-handler@^2.28.0 react-native-worklets@^0.5.1 react-native-safe-area-context@^5.6.0 react-native-svg@^15.12.1 tailwind-variants@^3.2.2 tailwind-merge@^3.4.0 ``` It's recommended to use the exact versions specified above to avoid compatibility issues. Version mismatches may cause unexpected bugs. ### 3. Optional Dependencies These packages are only needed if you use specific components or features: | Package | Version | Required for | | ---------------------- | --------- | ----------------------------------------------------------------------- | | `react-native-screens` | `^4.16.0` | BottomSheet, Dialog, Menu, Popover, Select, Toast | | `@gorhom/bottom-sheet` | `^5.2.9` | BottomSheet, Menu / Popover / Select when `presentation="bottom-sheet"` | ### 4. Set Up Uniwind Follow the [Uniwind installation guide](https://docs.uniwind.dev/quickstart) to set up Tailwind CSS for React Native. If you're migrating from NativeWind, see the [migration guide](https://docs.uniwind.dev/migration-from-nativewind). ### 5. Configure global.css Inside your `global.css` file add the following imports: ```css @import 'tailwindcss'; @import 'uniwind'; @import 'heroui-native/styles'; /* Path to the heroui-native lib inside node_modules relative to global.css */ /* Examples: * - If global.css is at project root: ./node_modules/heroui-native/lib * - If global.css is in app/: ../node_modules/heroui-native/lib * - If global.css is in src/styles/: ../../node_modules/heroui-native/lib */ @source './node_modules/heroui-native/lib'; ``` ### 6. Wrap Your App with Provider Wrap your application with `HeroUINativeProvider`. You must wrap it with `GestureHandlerRootView`: ```tsx import { HeroUINativeProvider } from 'heroui-native'; import { GestureHandlerRootView } from 'react-native-gesture-handler'; export default function App() { return ( {/* Your app content */} ); } ``` > **Note**: For advanced configuration options including text props, animation settings, and toast configuration, see the [Provider documentation](/docs/native/getting-started/provider). ## Use Your First Component ```tsx import { Button } from 'heroui-native'; import { View } from 'react-native'; export default function MyComponent() { return ( ); } ``` ## Reduce Bundle Size with Granular Exports If you want to reduce bundle size and import only the components you need, our library provides granular exports for each component: ```tsx // Granular imports - use when you need only a few components import { HeroUINativeProvider } from "heroui-native/provider"; import { Button } from "heroui-native/button"; import { Card } from "heroui-native/card"; // General import - imports the whole library, use when you're using many components import { Button, Card } from "heroui-native"; ``` Granular imports are ideal when you only need a few components, as they help keep your bundle size smaller. General imports from `heroui-native` will include the entire library, which is convenient when you're using many components throughout your app. **Available granular exports:** * `heroui-native/provider` - Provider component * `heroui-native/provider-raw` - Lightweight provider (keeps bare minimum to start) * `heroui-native/[component-name]` - Individual components * `heroui-native/portal` - Portal utilities * `heroui-native/toast` - Toast provider and utilities * `heroui-native/utils` - Utility functions * `heroui-native/hooks` - Custom hooks **Important**: To keep the bundle size under control, you must follow the pattern with granular imports consistently. Even one general import from `heroui-native` will break this optimization strategy. > **Tip**: For even more control over your bundle, consider using [`HeroUINativeProviderRaw`](/docs/native/getting-started/provider#raw-provider) — a lightweight provider that excludes `ToastProvider` and `PortalHost`. ## What's Next? * [HeroUI Native Provider](/docs/native/getting-started/provider) * [Styling Guide](/docs/native/getting-started/styling) * [Theming Documentation](/docs/native/getting-started/theming) ## Running on Web (Expo) HeroUI Native is currently not recommended for web use. We are focusing on mobile platforms (iOS and Android) at this time. For web development, please use [HeroUI React](/docs/react/getting-started/quick-start) instead. # Agent Skills **Category**: native **URL**: https://www.heroui.com/en/docs/native/getting-started/agent-skills **Source**: https://raw.githubusercontent.com/heroui-inc/heroui/refs/heads/v3/apps/docs/content/docs/en/native/getting-started/(ui-for-agents)/agent-skills.mdx > Enable AI assistants to build mobile UIs with HeroUI Native components HeroUI Native Skills give your AI assistant comprehensive knowledge of HeroUI Native components, patterns, and best practices for React Native development. ### Installation ```bash curl -fsSL https://heroui.com/install | bash -s heroui-native ``` Or using the skills package: ```bash npx skills add heroui-inc/heroui ``` Support Claude Code, Cursor, OpenCode and more. ### Usage Skills are **automatically discovered** by your AI assistant, or call it directly using `/heroui-native` command. Simply ask your AI assistant to: * Build mobile components using HeroUI Native * Create screens with HeroUI Native components * Customize themes and styles * Access component documentation For more complex use cases, use the [MCP Server](/docs/native/getting-started/mcp-server) which provides real-time access to component documentation and source code. ### What's Included * HeroUI Native installation guide * All HeroUI Native components with props, examples, and usage patterns * Theming and styling guidelines with Uniwind * Design principles and composition patterns ### Structure ``` skills/heroui-native/ ├── SKILL.md # Main skill documentation ├── LICENSE.txt # Apache License 2.0 └── scripts/ # Utility scripts ├── list_components.mjs ├── get_component_docs.mjs ├── get_theme.mjs └── get_docs.mjs ``` ### Related Documentation * [Agent Skills Specification](https://agentskills.io/home) - Learn about the Agent Skills format * [Claude Agent Skills](https://platform.claude.com/docs/en/agents-and-tools/agent-skills/overview) - Claude's Skills documentation * [Cursor Skills](https://cursor.com/docs/context/skills) - Using Skills in Cursor * [OpenCode Skills](https://opencode.ai/docs/skills) - Using Skills in OpenCode # AGENTS.md **Category**: native **URL**: https://www.heroui.com/en/docs/native/getting-started/agents-md **Source**: https://raw.githubusercontent.com/heroui-inc/heroui/refs/heads/v3/apps/docs/content/docs/en/native/getting-started/(ui-for-agents)/agents-md.mdx > Download HeroUI Native documentation for AI coding agents Download HeroUI Native documentation directly into your project for AI assistants to reference. **Note:** The `agents-md` command is specifically for HeroUI React v3 and HeroUI Native. Other CLI commands (like `add`, `init`, `upgrade`, etc.) are for HeroUI v2 (for now). ### Usage ```bash npx heroui-cli@latest agents-md --native ``` Or specify output file: ```bash npx heroui-cli@latest agents-md --native --output AGENTS.md ``` ### What It Does * Downloads latest HeroUI Native docs to `.heroui-docs/native/` * Generates an index in `AGENTS.md` or `CLAUDE.md` * Adds `.heroui-docs/` to `.gitignore` automatically ### Options * `--native` - Download Native docs only * `--output ` - Target file(s) (e.g., `AGENTS.md` or `AGENTS.md CLAUDE.md`) * `--ssh` - Use SSH for git clone ### Requirements * Tailwind CSS >= v4 (via Uniwind) ### Related Documentation * [AGENTS.md](https://agents.md/) - Learn about the AGENTS.md format for coding agents * [CLAUDE.md](https://code.claude.com/docs/en/best-practices#write-an-effective-claude-md) - Claude equivalent of AGENTS.md * [AGENTS.md vs Skills](https://vercel.com/blog/agents-md-outperforms-skills-in-our-agent-evals) - AGENTS.md performance # LLMs.txt **Category**: native **URL**: https://www.heroui.com/en/docs/native/getting-started/llms-txt **Source**: https://raw.githubusercontent.com/heroui-inc/heroui/refs/heads/v3/apps/docs/content/docs/en/native/getting-started/(ui-for-agents)/llms-txt.mdx > Enable AI assistants like Claude, Cursor, and Windsurf to understand HeroUI Native We provide [LLMs.txt](https://llmstxt.org/) files to make HeroUI Native documentation accessible to AI coding assistants. ## Available Files **Core documentation:** * [/native/llms.txt](/native/llms.txt) — Quick reference index for Native documentation * [/native/llms-full.txt](/native/llms-full.txt) — Complete HeroUI Native documentation **For limited context windows:** * [/native/llms-components.txt](/native/llms-components.txt) — Component documentation only * [/native/llms-patterns.txt](/native/llms-patterns.txt) — Common patterns and recipes **All platforms:** * [/llms.txt](/llms.txt) — Quick reference index (React + Native) * [/llms-full.txt](/llms-full.txt) — Complete documentation (React + Native) * [/llms-components.txt](/llms-components.txt) — All component documentation * [/llms-patterns.txt](/llms-patterns.txt) — All patterns and recipes ## Integration **Claude Code:** Tell Claude to reference the documentation: ``` Use HeroUI Native documentation from https://heroui.com/native/llms.txt ``` Or add to your project's `.claude` file for automatic loading. **Cursor:** Use the `@Docs` feature: ``` @Docs https://heroui.com/native/llms-full.txt ``` [Learn more](https://docs.cursor.com/context/@-symbols/@-docs) **Windsurf:** Add to your `.windsurfrules` file: ``` #docs https://heroui.com/native/llms-full.txt ``` [Learn more](https://docs.codeium.com/windsurf/memories#memories-and-rules) **Other AI tools:** Most AI assistants can reference documentation by URL. Simply provide: ``` https://heroui.com/native/llms.txt ``` **For component-specific documentation:** ``` https://heroui.com/native/llms-components.txt ``` **For patterns and best practices:** ``` https://heroui.com/native/llms-patterns.txt ``` ## Contributing Found an issue with AI-generated code? Help us improve our LLMs.txt files on [GitHub](https://github.com/heroui-inc/heroui). # MCP Server **Category**: native **URL**: https://www.heroui.com/en/docs/native/getting-started/mcp-server **Source**: https://raw.githubusercontent.com/heroui-inc/heroui/refs/heads/v3/apps/docs/content/docs/en/native/getting-started/(ui-for-agents)/mcp-server.mdx > Access HeroUI Native documentation directly in your AI assistant The HeroUI MCP Server gives AI assistants direct access to HeroUI Native component documentation, making it easier to build with HeroUI in AI-powered development environments. The MCP server currently supports **heroui-native** and [stdio transport](https://modelcontextprotocol.io/specification/2025-06-18/basic/transports#stdio). Published at `@heroui/native-mcp` on npm. View the source code on [GitHub](https://github.com/heroui-inc/heroui-mcp). As we add more components to HeroUI Native, they'll be available in the MCP server too. ## Quick Setup **Cursor:**
Install in Cursor
Or manually add to **Cursor Settings** → **Tools** → **MCP Servers**: ```json title=".cursor/mcp.json" { "mcpServers": { "heroui-native": { "command": "npx", "args": ["-y", "@heroui/native-mcp@latest"] } } } ``` Alternatively, add the following to your `~/.cursor/mcp.json` file. To learn more, see the [Cursor documentation](https://cursor.com/docs/context/mcp). **Claude Code:** Run this command in your terminal: ```bash claude mcp add heroui-native -- npx -y @heroui/native-mcp@latest ``` Or manually add to your project's `.mcp.json` file: ```json title=".mcp.json" { "mcpServers": { "heroui-native": { "command": "npx", "args": ["-y", "@heroui/native-mcp@latest"] } } } ``` After adding the configuration, restart Claude Code and run `/mcp` to see the HeroUI MCP server in the list. If you see **Connected**, you're ready to use it. See the [Claude Code MCP documentation](https://docs.claude.com/en/docs/claude-code/mcp) for more details. **Windsurf:** Add the HeroUI server to your project's `.windsurf/mcp.json` configuration file: ```json title=".windsurf/mcp.json" { "mcpServers": { "heroui-native": { "command": "npx", "args": ["-y", "@heroui/native-mcp@latest"] } } } ``` After adding the configuration, restart Windsurf to activate the MCP server. See the [Windsurf MCP documentation](https://docs.windsurf.com/windsurf/cascade/mcp) for more details. **Zed:** Add the HeroUI server to your `settings.json` configuration file. Open settings via Command Palette (`zed: open settings`) or use `Cmd-,` (Mac) / `Ctrl-,` (Linux): ```json title="settings.json" { "context_servers": { "heroui-native": { "command": "npx", "args": ["-y", "@heroui/native-mcp@latest"], "env": {} } } } ``` After adding the configuration, restart Zed and open the Agent Panel settings view. Check that the indicator dot next to the heroui-native server is green with "Server is active" tooltip. See the [Zed MCP documentation](https://zed.dev/docs/ai/mcp) for more details. **VS Code:** To configure MCP in VS Code with GitHub Copilot, add the HeroUI server to your project's `.vscode/mcp.json` configuration file: ```json title=".vscode/mcp.json" { "servers": { "heroui-native": { "type": "stdio", "command": "npx", "args": ["-y", "@heroui/native-mcp@latest"] } } } ``` After adding the configuration, open `.vscode/mcp.json` and click **Start** next to the heroui-native server. See the [VS Code MCP documentation](https://code.visualstudio.com/docs/copilot/customization/mcp-servers) for more details. **Codex:** Add the HeroUI server to your `~/.codex/config.toml` (or a project-scoped `.codex/config.toml`): ```toml title="config.toml" [mcp_servers.heroui-native] command = "npx" args = ["-y", "@heroui/native-mcp@latest"] ``` After adding the configuration, restart Codex and run `/mcp` in the TUI to verify the server is active. See the [Codex MCP documentation](https://developers.openai.com/codex/mcp) for more details. **OpenCode:** Add the HeroUI server to your project's `opencode.json` configuration file: ```json title="opencode.json" { "$schema": "https://opencode.ai/config.json", "mcp": { "heroui-native": { "type": "local", "command": ["npx", "-y", "@heroui/native-mcp@latest"] } } } ``` After adding the configuration, restart OpenCode to activate the MCP server. See the [OpenCode MCP documentation](https://open-code.ai/docs/en/mcp-servers) for more details. ## Usage Once configured, ask your AI assistant questions like: * "Help me install HeroUI Native in my Expo app" * "Show me all HeroUI Native components" * "What props does the Button component have?" * "Give me an example of using the Card component" * "What are the theme variables for dark mode?" ### Automatic Updates The MCP server can help you upgrade to the latest HeroUI Native version: ```bash "Hey Cursor, update HeroUI Native to the latest version" ``` Your AI assistant will automatically: * Compare your current version with the latest release * Review the changelog for breaking changes * Apply the necessary code updates to your project This works for any version upgrade, whether you're updating to the latest stable or pre-release version. ## Available Tools The MCP server provides these tools to AI assistants: | Tool | Description | | --------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------- | | `list_components` | List all available HeroUI Native components | | `get_component_docs` | Get complete component documentation including anatomy, props, examples, and usage patterns for one or more components | | `get_theme_variables` | Access theme variables for colors, typography, spacing with light/dark mode support | | `get_docs` | Browse the full HeroUI Native documentation including guides and principles (use path `/docs/native/getting-started/quick-start` for installation instructions) | ## Troubleshooting **Requirements:** Node.js 22 or higher. The package will be automatically downloaded when using `npx`. **Need help?** [GitHub Issues](https://github.com/heroui-inc/heroui-mcp/issues) | [Discord Community](https://discord.gg/heroui) ## Links * [npm Package](https://www.npmjs.com/package/@heroui/native-mcp) * [GitHub Repository](https://github.com/heroui-inc/heroui-mcp) * [Contributing Guide](https://github.com/heroui-inc/heroui-mcp/blob/main/CONTRIBUTING.md)
# Animation **Category**: react **URL**: https://www.heroui.com/en/docs/react/getting-started/animation **Source**: https://raw.githubusercontent.com/heroui-inc/heroui/refs/heads/v3/apps/docs/content/docs/en/react/getting-started/(handbook)/animation.mdx > Add smooth animations and transitions to HeroUI v3 components HeroUI components support multiple animation approaches: built-in CSS transitions, custom CSS animations, and JavaScript libraries like Framer Motion. ## 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 for styling:** * `[data-hovered="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:** ```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 Apply dynamic animations based on component state: ```tsx ``` ## Accessibility **Respecting motion preferences:** HeroUI automatically respects user motion preferences using Tailwind's `motion-reduce:` utility. All built-in transitions and animations are disabled when users enable "reduce motion" in their system settings. HeroUI extends Tailwind's `motion-reduce:` variant to support both the native `prefers-reduced-motion` media query and the `data-reduce-motion` attribute. ```css /* HeroUI pattern - uses Tailwind's motion-reduce: */ .button { @apply transition-colors motion-reduce:transition-none; } /* Expands to support both approaches: */ @media (prefers-reduced-motion: reduce) { .button { transition: none; } } [data-reduce-motion="true"] .button { transition: none; } ``` With Framer Motion: ```tsx import { useReducedMotion } from 'framer-motion'; function AnimatedCard() { const shouldReduceMotion = useReducedMotion(); return ( Content ); } ``` **Disabling animations globally:** Add `data-reduce-motion="true"` to the `` or `` tag: ```html ``` HeroUI automatically detects the user's `prefers-reduced-motion: reduce` setting and disables animations accordingly. ## 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:** Use `will-change` to optimize animations, but remove it when not animating: ```css .button { will-change: transform; } .button:not(:hover) { will-change: auto; } ``` ## Next Steps * Learn about [Styling](/docs/handbook/styling) approaches * Explore [Component](/docs/react/components) examples * View [Theming](/docs/handbook/theming) documentation
# Colors **Category**: react **URL**: https://www.heroui.com/en/docs/react/getting-started/colors **Source**: https://raw.githubusercontent.com/heroui-inc/heroui/refs/heads/v3/apps/docs/content/docs/en/react/getting-started/(handbook)/colors.mdx > Color palette and theming system for HeroUI v3 import {ColorSectionSideBySide, ColorSectionStacked, ColorSectionFormField, ColorSectionPrimitive} from "@/components/color-section"; HeroUI's color system is built around semantic intent, not visual abundance. Instead of exposing large raw palettes, the system defines a small, meaningful set of color roles that cover the majority of interface needs. Most colors in the system are derived automatically from a limited number of base values. This allows HeroUI to maintain consistent contrast, hierarchy, and theming behavior while keeping the system easy to reason about and modify. Colors should communicate purpose and state first. Visual variation comes from scale, emphasis, and context. **Want to create your own theme?** Try the [Theme Builder](/themes) to visually customize colors, radius, fonts, and more — then export the CSS to use in your project. ## Accent The accent color represents the primary brand or product identity. It is used to draw attention to key actions, highlights, and moments of emphasis. Accent should be used intentionally and sparingly. Overuse reduces its impact and can harm visual hierarchy. In most cases, components derive multiple accent-related values (hover, subtle backgrounds, focus states) automatically from the base accent color. ## Default (neutrals) Default colors form the neutral backbone of the system. They are used for most non-emphasized UI elements. ## Success Success colors communicate positive outcomes, confirmations, and completed states. They are typically used in feedback components, status indicators, and validation states. ## Warning Warning colors indicate caution, risk, or actions that require attention but are not destructive. They are commonly used for alerts, messages, and transitional states where the user should pause or review information. ## Danger Danger colors represent destructive, irreversible, or critical actions and states. They should be immediately recognizable and used consistently for errors, destructive buttons, and critical alerts. ## Foreground Foreground colors are used for primary content such as text and icons. These colors are optimized for readability and accessibility and adapt automatically to background and surface contexts. Foreground colors should never be hard-coded at the component level. ## Background Background colors define the base canvas of the interface. They establish overall contrast and mood while staying visually quiet. ## Surface Surface colors sit on top of backgrounds and are used for containers such as cards, panels, modals, and dropdown. Surfaces help create visual separation and hierarchy through elevation, contrast, and layering rather than strong color shifts. ## Form field Form field colors are specialized tokens used for inputs, controls, and interactive fields. They account for multiple states such as default, focus, and hover. Isolating them ensures form elements have a distinct visual language from buttons and the rest of the UI. ## Separator Separator colors are used for dividers, outlines, and subtle boundaries. They exist to structure content and guide the eye without adding noise. Separator colors should remain low contrast and unobtrusive. ## Other Other colors serve specific utility roles across the interface. They exist to structure content and guide the eye without adding noise. ## Primitive Primitive colors are mode agnostic values used as foundations for semantic color tokens. They do not change between light and dark themes. ## How to Use Colors **In your components:** ```jsx
``` **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-hovered="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 ([variables.css](https://github.com/heroui-inc/heroui/blob/v3/packages/styles/themes/default/variables.css)). This theme automatically switches between light and dark modes based on the `class="dark"` or `data-theme="dark"` attributes. ```css @layer base { /* HeroUI Default Theme */ :root { color-scheme: light; /* == Common Variables == */ /* Primitive Colors (Do not change between light and dark) */ --white: oklch(100% 0 0); --black: oklch(0% 0 0); --snow: oklch(0.9911 0 0); --eclipse: oklch(0.2103 0.0059 285.89); /* Spacing scale */ --spacing: 0.25rem; /* Border */ --border-width: 1px; --field-border-width: 0px; --disabled-opacity: 0.5; /* Ring offset - Used for focus ring */ --ring-offset-width: 2px; /* Cursor */ --cursor-interactive: pointer; --cursor-disabled: not-allowed; /* Radius */ --radius: 0.5rem; --field-radius: calc(var(--radius) * 1.5); /* == Light Theme Variables == */ /* Base Colors */ --background: oklch(0.9702 0 0); --foreground: var(--eclipse); /* Surface: Used for non-overlay components (cards, accordions, disclosure groups) */ --surface: var(--white); --surface-foreground: var(--foreground); /* Overlay: Used for floating/overlay components (tooltips, popovers, modals, menus) */ --overlay: var(--white); --overlay-foreground: var(--foreground); --muted: oklch(0.5517 0.0138 285.94); --scrollbar: oklch(87.1% 0.006 286.286); --default: oklch(94% 0.001 286.375); --default-foreground: var(--eclipse); --accent: oklch(0.6204 0.195 253.83); --accent-foreground: var(--snow); /* Form Field Defaults - Colors */ --field-background: var(--white); --field-foreground: oklch(0.2103 0.0059 285.89); --field-placeholder: var(--muted); --field-border: transparent; /* no border by default on form fields */ /* Status Colors */ --success: oklch(0.7329 0.1935 150.81); --success-foreground: var(--eclipse); --warning: oklch(0.7819 0.1585 72.33); --warning-foreground: var(--eclipse); --danger: oklch(0.6532 0.2328 25.74); --danger-foreground: var(--snow); /* Component Colors */ --segment: var(--white); --segment-foreground: var(--eclipse); /* Misc Colors */ --border: oklch(92% 0.004 286.32); --separator: oklch(92% 0.004 286.32); --focus: var(--accent); --link: var(--foreground); /* Backdrop */ --backdrop: rgba(0, 0, 0, 0.5); /* Shadows */ --surface-shadow: 0 2px 4px 0 rgba(0, 0, 0, 0.04), 0 1px 2px 0 rgba(0, 0, 0, 0.06), 0 0 1px 0 rgba(0, 0, 0, 0.06); /* Overlay shadow */ --overlay-shadow: 0 4px 16px 0 rgba(24, 24, 27, 0.08), 0 8px 24px 0 rgba(24, 24, 27, 0.09); --field-shadow: 0 2px 4px 0 rgba(0, 0, 0, 0.04), 0 1px 2px 0 rgba(0, 0, 0, 0.06), 0 0 1px 0 rgba(0, 0, 0, 0.06); /* Skeleton Default Global Animation */ --skeleton-animation: shimmer; /* shimmer, pulse, none */ /* Tooltip Default Delays */ --tooltip-delay: 1500ms; --tooltip-close-delay: 500ms; } .dark, [data-theme="dark"] { color-scheme: dark; /* == Dark Theme Variables == */ /* Base Colors */ --background: oklch(12% 0.005 285.823); --foreground: var(--snow); /* Surface: Used for non-overlay components (cards, accordions, disclosure groups) */ --surface: oklch(0.2103 0.0059 285.89); --surface-foreground: var(--foreground); /* Overlay: Used for floating/overlay components (tooltips, popovers, modals, menus) - lighter for contrast */ --overlay: oklch(0.22 0.0059 285.89); /* A bit lighter than surface for visibility in dark mode */ --overlay-foreground: var(--foreground); --muted: oklch(70.5% 0.015 286.067); --scrollbar: oklch(70.5% 0.015 286.067); --default: oklch(27.4% 0.006 286.033); --default-foreground: var(--snow); /* Form Field Defaults - Colors (only the ones that are different from light theme) */ --field-background: var(--default); --field-foreground: var(--foreground); /* Status Colors */ --warning: oklch(0.8203 0.1388 76.34); --warning-foreground: var(--eclipse); --danger: oklch(0.594 0.1967 24.63); --danger-foreground: var(--snow); /* Component Colors */ --segment: oklch(0.3964 0.01 285.93); --segment-foreground: var(--foreground); /* Misc Colors */ --border: oklch(22% 0.006 286.033); --separator: oklch(22% 0.006 286.033); --focus: var(--accent); --link: var(--foreground); /* Backdrop */ --backdrop: rgba(0, 0, 0, 0.6); /* Shadows */ --surface-shadow: 0 0 0 0 transparent inset; /* No shadow on dark mode */ --overlay-shadow: 0 0 0 0 transparent inset; /* No shadow on dark mode */ --field-shadow: 0 0 0 0 transparent inset; /* Transparent shadow to allow ring utilities to work */ } } ``` ## Customizing Colors **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) **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).
# Composition **Category**: react **URL**: https://www.heroui.com/en/docs/react/getting-started/composition **Source**: https://raw.githubusercontent.com/heroui-inc/heroui/refs/heads/v3/apps/docs/content/docs/en/react/getting-started/(handbook)/composition.mdx > Build flexible UI with component composition patterns HeroUI uses composition patterns to create flexible, customizable components. Change the rendered element, compose components together, and maintain full control over markup. ## Framework-Agnostic Styles HeroUI's variant functions are available in the `@heroui/styles` package, which can be used independently of React. This enables Vue, Svelte, and other frameworks to use HeroUI's design system: ```tsx // Import directly from @heroui/styles (framework-agnostic) import { buttonVariants } from '@heroui/styles'; // Or import from @heroui/react (re-exports the same functions) import { buttonVariants } from '@heroui/react'; ``` Both imports work identically. Use `@heroui/styles` when building for non-React frameworks or when you want to avoid pulling in React dependencies. ## Polymorphic Styling Apply HeroUI styles to any element using variant functions or BEM classes. Extend component styles to framework components, native HTML elements, or custom components with full type safety. **Example: Styling a Link as a Button** You can use `buttonVariants` to style a Link component with button styles: ```tsx import { buttonVariants } from '@heroui/styles'; import Link from 'next/link'; // Style a Next.js Link as a primary button About // Style a native anchor as a secondary button with custom size External Link ``` **Using BEM classes directly:** ```tsx import Link from 'next/link'; // Apply button styles directly using BEM classes About ``` **Working with Compound Components** When using a custom root element instead of HeroUI's Root component, child components cannot access context slots. You can manually pass `className` to child components using variant functions or BEM classes: ```tsx import { Link } from '@heroui/react'; import { linkVariants } from '@heroui/styles'; import NextLink from 'next/link'; // With custom root - pass className manually const slots = linkVariants(); About Page About Page ``` This approach works because HeroUI's variant functions and BEM classes can be applied to any element, giving you complete flexibility to style framework components, native elements, or custom components with HeroUI's design system. ## Direct Class Application The simplest way to style links or other elements is to apply HeroUI's [BEM](https://getbem.com/) classes directly. This approach is straightforward and works with any framework or vanilla HTML. **With Next.js Link:** ```tsx import Link from 'next/link'; Return Home ``` **With native anchor:** ```tsx Go to Dashboard ``` **Available button classes:** * `.button` — Base button styles * `.button--primary`, `.button--secondary`, `.button--tertiary`, `.button--danger`, `.button--ghost` — Variants * `.button--sm`, `.button--md`, `.button--lg` — Sizes * `.button--icon-only` — Icon-only button This approach works because HeroUI uses [BEM](https://getbem.com/) classes that can be applied to any element. It's perfect when you don't need the component's interactive features (like `onPress` handlers) and just want the visual styling. ## Using Variant Functions For more control and type safety, use variant functions to apply HeroUI styles to framework-specific components or custom elements. Variant functions are available from both `@heroui/styles` (framework-agnostic) and `@heroui/react` (re-exports). **With Next.js Link:** ```tsx import { Link } from '@heroui/react'; import { linkVariants } from '@heroui/styles'; import NextLink from 'next/link'; const slots = linkVariants(); About Page ``` **With Button styles:** ```tsx import { buttonVariants } from '@heroui/styles'; import Link from 'next/link'; Dashboard ``` **Available variant functions:** Each component exports its variant function (`buttonVariants`, `chipVariants`, `linkVariants`, `spinnerVariants`, and more) from `@heroui/styles`. Use them to apply HeroUI's design system to any element while maintaining type safety. ## Compound Components HeroUI components are built as compound components—they export multiple parts that work together. Use them in three flexible ways: **Option 1: Compound pattern (recommended)** — Use the main component directly without `.Root` suffix: ```tsx import { Alert } from '@heroui/react'; Success Your changes have been saved. ``` **Option 2: Compound pattern with .Root** — Use the `.Root` suffix if you prefer explicit naming: ```tsx import { Alert } from '@heroui/react'; Success Your changes have been saved. ``` **Option 3: Named exports** — Import each part separately: ```tsx import { AlertRoot, AlertIcon, AlertContent, AlertTitle, AlertDescription, AlertClose } from '@heroui/react'; Success Your changes have been saved. ``` **Mixed syntax:** Mix compound and named exports in the same component: ```tsx import { Alert, AlertTitle, AlertDescription } from '@heroui/react'; Success Your changes have been saved. ``` **Simple components:** Simple components like `Button` work the same way—no `.Root` needed: ```tsx import { Button } from '@heroui/react'; // Recommended - no .Root needed // Or with .Root Click me // Or named export import { ButtonRoot } from '@heroui/react'; Click me ``` **Benefits:** All three patterns provide flexibility, customization, control, and consistency. Choose the pattern that fits your codebase. ## Mixing Variant Functions You can combine variant functions from different components to create unique styles: ```tsx import { Link } from '@heroui/react'; import { linkVariants, buttonVariants } from '@heroui/styles'; // Link styled with button variants const buttonStyles = buttonVariants({ variant: "tertiary", size: "md" }); HeroUI ``` ## Custom Components Create your own components by composing HeroUI primitives: ```tsx import { Button, Tooltip } from '@heroui/react'; import { buttonVariants } from '@heroui/styles'; // Link button component using variant functions function LinkButton({ href, children, variant = "primary", ...props }) { return ( {children} ); } // Icon button with tooltip function IconButton({ icon, label, ...props }) { return ( {label} ); } ``` ## Custom Variants Create custom variants by extending the component's variant function: ```tsx import type { ButtonRootProps } from "@heroui/react"; import type { VariantProps } from "tailwind-variants"; import { Button } from "@heroui/react"; import { buttonVariants, tv } from "@heroui/styles"; 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 ``` The `render` prop is also useful for rendering link components from client-side routers, or reusing existing presentational components. ```tsx import {Link} from '@heroui/react'; import NextLink from 'next/link'; ( } href="/privacy-policy" /> )} > Privacy Policy ``` Follow these rules to avoid breaking the behavior and accessibility of the component: * Always render the expected element type (e.g. if ` ); } ``` ### Pages Router For `pages/`, wrap your application in `pages/_app.tsx`. ```tsx // pages/_app.tsx import "@/styles/globals.css"; import type {AppProps} from "next/app"; import {ThemeProvider as NextThemesProvider} from "next-themes"; export default function App({Component, pageProps}: AppProps) { return ( ); } ``` ## Using custom theme names The `attribute="class"` setup works well for the built-in `light` and `dark` themes. If your custom theme CSS is written with `data-theme` selectors, configure `next-themes` to write `data-theme` instead. ```tsx {children} ``` When you pass a custom `themes` list, include `"light"` and `"dark"` if you still want the built-in themes available. ## React with useTheme Use HeroUI's `useTheme` hook when you are building a plain React app, such as Vite or Create React App, and do not need `next-themes`. The hook is exported from `@heroui/react`. It stores the selected theme in `localStorage`, resolves `"system"` from the user's OS preference, and applies both the class and `data-theme` attribute to ``. ```tsx // src/components/theme-switcher.tsx import {Button, useTheme} from "@heroui/react"; export function ThemeSwitcher() { const {resolvedTheme, setTheme, theme} = useTheme("system"); return (
); } ``` Use one theme controller per app. In Next.js, prefer `next-themes` and its `useTheme` hook. In plain React apps, use `useTheme` from `@heroui/react`. ## Styling for both themes Theme-aware utilities work automatically because they read CSS variables: ```tsx
Theme-aware content
``` Use the `dark:` variant for one-off changes that only apply in dark mode: ```tsx
Custom dark-mode adjustment
```
# Styling **Category**: react **URL**: https://www.heroui.com/en/docs/react/getting-started/styling **Source**: https://raw.githubusercontent.com/heroui-inc/heroui/refs/heads/v3/apps/docs/content/docs/en/react/getting-started/(handbook)/styling.mdx > Style HeroUI components with CSS, Tailwind, or CSS-in-JS HeroUI components provide flexible styling options: Tailwind CSS utilities, CSS with [BEM](https://getbem.com/) classes or data attributes, CSS-in-JS libraries, and render props for dynamic styling. ## Basic Styling **Using className:** All HeroUI components accept `className` props: ```tsx {/* content */} ``` **Using style:** Components also accept inline styles: ```tsx ``` ## Scrollbars HeroUI scroll slots use `@apply scrollbar` in component CSS. For your own overflow containers, use the utilities from `@heroui/styles`: ```tsx
{/* long content */}
``` | Utility | Effect | | ------------------- | ---------------------------------------------------- | | `scrollbar` | HeroUI thumb (reads theme `--scrollbar-*` variables) | | `scrollbar-thin` | HeroUI themed thin scrollbar | | `scrollbar-default` | OS / browser scrollbars | | `scrollbar-none` | Hidden scrollbar | Global and per-subtree control uses `data-scrollbar` on an ancestor. See [Theming](/docs/handbook/theming#scrollbars) for tokens and modes. ## State-Based Styling HeroUI components expose their state through data attributes, similar to CSS pseudo-classes: ```css /* Target different states */ .button[data-hovered="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 Apply 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 Create reusable custom components using [tailwind-variants](https://tailwind-variants.org/)—a Tailwind CSS first-class variant API: ```tsx import { Button as HeroButton, type ButtonProps } from '@heroui/react'; import { buttonVariants, tv, type VariantProps } from '@heroui/styles'; 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 **Using Tailwind 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`, `.button--{variant}`, `.button--{size}`, `.button--icon-only` **Accordion:** `.accordion`, `.accordion__item`, `.accordion__trigger`, `.accordion__panel`, `.accordion--outline` > **Note:** See component docs for complete class references: [Button](/docs/components/button#css-classes), [Accordion](/docs/components/accordion#css-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/react/components) examples
# Theming **Category**: react **URL**: https://www.heroui.com/en/docs/react/getting-started/theming **Source**: https://raw.githubusercontent.com/heroui-inc/heroui/refs/heads/v3/apps/docs/content/docs/en/react/getting-started/(handbook)/theming.mdx > Customize HeroUI's design system with CSS variables and global styles HeroUI uses CSS variables and [BEM](https://getbem.com/) classes for theming. Customize everything from colors to component styles using standard CSS. **Want to create your own theme?** Try the [Theme Builder](/themes) to visually customize colors, radius, fonts, and more — then export the CSS to use in your project. ## 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 uses Tailwind's built-in color palettes, maps them to semantic variables, automatically switches between light and dark themes, and uses CSS layers and the `@theme` directive for organization. **Naming pattern:** * Colors without a suffix are backgrounds (e.g., `--accent`) * Colors with `-foreground` are for text on that background (e.g., `--accent-foreground`) ## Quick Start **Apply a theme:** Add a theme class to your HTML and apply colors to the body: ```html ``` **Switch themes:** ```html ``` **Switch themes programmatically with [next-themes](https://github.com/pacocoursey/next-themes) (For Next.js):** First, wrap your app with `ThemeProvider`: ```tsx // app/providers.tsx "use client"; import { ThemeProvider } from "next-themes"; export function Providers({ children }: { children: React.ReactNode }) { return ( {children} ); } ``` ```tsx // app/layout.tsx import { Providers } from "./providers"; export default function RootLayout({ children }: { children: React.ReactNode }) { return ( {children} ); } ``` Then use `useTheme` to toggle between themes: ```tsx "use client"; import { useTheme } from "next-themes"; export function ThemeSwitch() { const { theme, setTheme } = useTheme(); return ( ); } ``` **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. > **Dark mode**: For a complete setup guide with `next-themes` and HeroUI's `useTheme` hook, see [Dark Mode](/docs/handbook/dark-mode). **Create your own theme:** ```css /* src/themes/ocean.css */ @layer base { /* Ocean Light */ [data-theme="ocean"] { color-scheme: light; /* Primitive Colors (Do not change between light and dark) */ --white: oklch(100% 0 0); --black: oklch(0% 0 0); --snow: oklch(0.9911 0 0); --eclipse: oklch(0.2103 0.0059 285.89); /* Spacing & Layout */ --spacing: 0.25rem; --border-width: 1px; --field-border-width: 0px; --disabled-opacity: 0.5; --ring-offset-width: 2px; --cursor-interactive: pointer; --cursor-disabled: not-allowed; /* Radius */ --radius: 0.75rem; --field-radius: calc(var(--radius) * 1.5); /* Base Colors */ --background: oklch(0.985 0.015 225); --foreground: var(--eclipse); /* Surface: Used for non-overlay components */ --surface: var(--white); --surface-foreground: var(--foreground); /* Overlay: Used for floating/overlay components */ --overlay: var(--white); --overlay-foreground: var(--foreground); --muted: oklch(0.5517 0.0138 285.94); --scrollbar-thumb: color-mix(in oklch, var(--foreground) 15%, transparent); --scrollbar-track: transparent; --scrollbar-gutter: auto; --scrollbar-width: thin; --scrollbar-color: var(--scrollbar-thumb) var(--scrollbar-track); --scrollbar: var(--scrollbar-thumb); --default: oklch(94% 0.001 286.375); --default-foreground: var(--eclipse); /* Ocean accent */ --accent: oklch(0.450 0.150 230); --accent-foreground: var(--snow); /* Form Field Defaults */ --field-background: var(--white); --field-foreground: oklch(0.2103 0.0059 285.89); --field-placeholder: var(--muted); --field-border: transparent; /* Status (kept compatible) */ --success: oklch(0.7329 0.1935 150.81); --success-foreground: var(--eclipse); --warning: oklch(0.7819 0.1585 72.33); --warning-foreground: var(--eclipse); --danger: oklch(0.6532 0.2328 25.74); --danger-foreground: var(--snow); /* Component Colors */ --segment: var(--white); --segment-foreground: var(--foreground); /* Misc */ --border: oklch(0.50 0.060 230 / 22%); --separator: oklch(92% 0.004 286.32); --focus: var(--accent); --link: var(--accent); /* Shadows */ --surface-shadow: 0 2px 4px 0 rgba(0, 0, 0, 0.04), 0 1px 2px 0 rgba(0, 0, 0, 0.06), 0 0 1px 0 rgba(0, 0, 0, 0.06); --overlay-shadow: 0 4px 16px 0 rgba(24, 24, 27, 0.08), 0 8px 24px 0 rgba(24, 24, 27, 0.09); --field-shadow: 0 2px 4px 0 rgba(0, 0, 0, 0.04), 0 1px 2px 0 rgba(0, 0, 0, 0.06), 0 0 1px 0 rgba(0, 0, 0, 0.06); /* Skeleton Default Global Animation */ --skeleton-animation: shimmer; /* Possible values: shimmer, pulse, none */ /* Tooltip Default Delays */ --tooltip-delay: 1500ms; --tooltip-close-delay: 500ms; } /* Ocean Dark */ [data-theme="ocean-dark"] { color-scheme: dark; /* Base Colors */ --background: oklch(0.140 0.020 230); --foreground: var(--snow); /* Surface: Used for non-overlay components */ --surface: oklch(0.2103 0.0059 285.89); --surface-foreground: var(--foreground); /* Overlay: Used for floating/overlay components */ --overlay: oklch(0.22 0.0059 285.89); --overlay-foreground: var(--foreground); --muted: oklch(70.5% 0.015 286.067); --scrollbar-thumb: color-mix(in oklch, var(--foreground) 15%, transparent); --scrollbar-track: transparent; --scrollbar-gutter: auto; --scrollbar-width: thin; --scrollbar-color: var(--scrollbar-thumb) var(--scrollbar-track); --scrollbar: var(--scrollbar-thumb); --default: oklch(27.4% 0.006 286.033); --default-foreground: var(--snow); /* Form Field Defaults */ --field-background: var(--default); --field-foreground: var(--foreground); /* Ocean accent */ --accent: oklch(0.860 0.080 230); --accent-foreground: var(--eclipse); /* Status */ --success: oklch(0.7329 0.1935 150.81); --success-foreground: var(--eclipse); --warning: oklch(0.8203 0.1388 76.34); --warning-foreground: var(--eclipse); --danger: oklch(0.594 0.1967 24.63); --danger-foreground: var(--snow); /* Component Colors */ --segment: oklch(0.3964 0.01 285.93); --segment-foreground: var(--foreground); /* Misc */ --border: oklch(22% 0.006 286.033); --separator: oklch(22% 0.006 286.033); --focus: var(--accent); --link: var(--accent); /* Shadows */ --surface-shadow: 0 0 0 0 transparent inset; --overlay-shadow: 0 0 0 0 transparent inset; --field-shadow: 0 0 0 0 transparent inset; } } ``` 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, modifiers, elements, states). 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" layer(base); /* OR specific base file */ @import "@heroui/styles/base/base.css" layer(base); /* Theme variables */ @import "@heroui/styles/themes/shared/theme.css" layer(theme); @import "@heroui/styles/themes/default" layer(theme); /* OR specific theme files */ @import "@heroui/styles/themes/default/index.css" layer(theme); @import "@heroui/styles/themes/default/variables.css" layer(theme); /* Components (all components) */ @import "@heroui/styles/components" layer(components); /* OR specific component files */ @import "@heroui/styles/components/index.css" layer(components); @import "@heroui/styles/components/button.css" layer(components); @import "@heroui/styles/components/accordion.css" layer(components); /* Utilities (optional) */ @import "@heroui/styles/utilities" layer(utilities); /* Variants (optional) */ @import "@heroui/styles/variants" layer(utilities); ``` > **Note**: Directory imports (e.g., `@heroui/styles/components`) automatically resolve to their `index.css` file. Use explicit file paths (e.g., `@heroui/styles/components/button.css`) to import individual component styles. **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 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 in [`variables.css`](https://github.com/heroui-inc/heroui/blob/v3/packages/styles/themes/default/variables.css): 1. **Base Variables** — Non-changing values like `--white`, `--black`, spacing, and typography 2. **Theme Variables** — Colors that change between light/dark themes, plus scrollbar tokens (`--scrollbar-thumb`, `--scrollbar-width`, etc.) 3. **Calculated Variables** — Hover states, soft variants, and border/separator levels (the **Calculated Colors** block in each light/dark theme, using `color-mix()`) For a complete reference, see: [Colors Documentation](/docs/handbook/colors), [Default Theme Variables](https://github.com/heroui-inc/heroui/blob/v3/packages/styles/themes/default/variables.css), [Shared Theme Utilities](https://github.com/heroui-inc/heroui/blob/v3/packages/styles/themes/shared/theme.css) **Tailwind theme bridge (`@theme inline`):** [`themes/shared/theme.css`](https://github.com/heroui-inc/heroui/blob/v3/packages/styles/themes/shared/theme.css) maps semantic variables to Tailwind tokens (`--color-*`, `--radius-*`, `--ease-*`). Calculated colors reference underlying vars (e.g. `--surface-hover`, `--accent-soft`) from `variables.css` — they are not inlined with `color-mix()` in this file: ```css @theme inline { --color-background: var(--background); --color-foreground: var(--foreground); --color-surface: var(--surface); --color-surface-foreground: var(--surface-foreground); --color-surface-hover: var(--surface-hover); --color-surface-secondary: var(--surface-secondary); --color-surface-secondary-foreground: var(--surface-secondary-foreground); --color-surface-tertiary: var(--surface-tertiary); --color-surface-tertiary-foreground: var(--surface-tertiary-foreground); --color-overlay: var(--overlay); --color-overlay-foreground: var(--overlay-foreground); --color-muted: var(--muted); --color-accent: var(--accent); --color-accent-foreground: var(--accent-foreground); --color-segment: var(--segment); --color-segment-foreground: var(--segment-foreground); --color-border: var(--border); --color-separator: var(--separator); --color-focus: var(--focus); --color-link: var(--link); --color-default: var(--default); --color-default-foreground: var(--default-foreground); --color-success: var(--success); --color-success-foreground: var(--success-foreground); --color-warning: var(--warning); --color-warning-foreground: var(--warning-foreground); --color-danger: var(--danger); --color-danger-foreground: var(--danger-foreground); --color-backdrop: var(--backdrop); --shadow-surface: var(--surface-shadow); --shadow-overlay: var(--overlay-shadow); --shadow-field: var(--field-shadow); /* Form Field Tokens */ --color-field: var(--field-background, var(--default)); --color-field-hover: var(--field-hover); --color-field-foreground: var(--field-foreground, var(--foreground)); --color-field-placeholder: var(--field-placeholder, var(--muted)); --color-field-border: var(--field-border, var(--border)); --radius-field: var(--field-radius, calc(var(--radius) * 1.5)); --border-width-field: var(--field-border-width, var(--border-width)); /* Color Tokens */ --color-background-secondary: var(--background-secondary); --color-background-tertiary: var(--background-tertiary); --color-background-inverse: var(--background-inverse); --color-default-hover: var(--default-hover); --color-accent-hover: var(--accent-hover); --color-success-hover: var(--success-hover); --color-warning-hover: var(--warning-hover); --color-danger-hover: var(--danger-hover); /* Form Field Colors */ --color-field-focus: var(--field-focus); --color-field-border-hover: var(--field-border-hover); --color-field-border-focus: var(--field-border-focus); /* Soft Colors */ --color-default-soft: var(--default-soft); --color-default-soft-foreground: var(--default-soft-foreground); --color-default-soft-hover: var(--default-soft-hover); --color-accent-soft: var(--accent-soft); --color-accent-soft-foreground: var(--accent-soft-foreground); --color-accent-soft-hover: var(--accent-soft-hover); --color-danger-soft: var(--danger-soft); --color-danger-soft-foreground: var(--danger-soft-foreground); --color-danger-soft-hover: var(--danger-soft-hover); --color-warning-soft: var(--warning-soft); --color-warning-soft-foreground: var(--warning-soft-foreground); --color-warning-soft-hover: var(--warning-soft-hover); --color-success-soft: var(--success-soft); --color-success-soft-foreground: var(--success-soft-foreground); --color-success-soft-hover: var(--success-soft-hover); /* Separator Colors - Levels */ --color-separator-secondary: var(--separator-secondary); --color-separator-tertiary: var(--separator-tertiary); /* Border Colors - Levels */ --color-border-secondary: var(--border-secondary); --color-border-tertiary: var(--border-tertiary); /* Radius and default sizes - defaults can change by just changing the --radius */ --radius-xs: calc(var(--radius) * 0.25); /* 0.125rem (2px) */ --radius-sm: calc(var(--radius) * 0.5); /* 0.25rem (4px) */ --radius-md: calc(var(--radius) * 0.75); /* 0.375rem (6px) */ --radius-lg: calc(var(--radius) * 1); /* 0.5rem (8px) */ --radius-xl: calc(var(--radius) * 1.5); /* 0.75rem (12px) */ --radius-2xl: calc(var(--radius) * 2); /* 1rem (16px) */ --radius-3xl: calc(var(--radius) * 3); /* 1.5rem (24px) */ --radius-4xl: calc(var(--radius) * 4); /* 2rem (32px) */ /* Transition Timing Functions */ --ease-smooth: ease; /* same as transition: ease; */ /* These custom curves are made by https://twitter.com/bdc */ /* From smoother to faster */ --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); /* From slower to faster */ --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); /* Custom smooth-out curve: fast start, smooth stop - Apple style */ --ease-out-fluid: cubic-bezier(0.32, 0.72, 0, 1); /* From slower to faster */ --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); /* Linear */ --ease-linear: linear; /* Animations */ --animate-spin-fast: spin 0.75s linear infinite; --animate-skeleton: skeleton 2s linear infinite; --animate-caret-blink: caret-blink 1.2s ease-out infinite; @keyframes skeleton { 100% { transform: translateX(200%); } } @keyframes caret-blink { 0%, 70%, 100% { opacity: 1; } 20%, 50% { opacity: 0; } } } ``` Form controls rely on `--field-*` theme variables. Hover, focus, and border variants are defined under **Calculated Colors** in `variables.css` and mapped to Tailwind in `theme.css` (e.g. `--color-field-hover: var(--field-hover)`). Override `--field-background`, `--field-hover`, and related tokens in your theme to restyle inputs, checkboxes, radios, and OTP slots without affecting surfaces like buttons or cards. ## Scrollbars HeroUI applies a shared scrollbar style to component scroll areas (tables, popovers, drawers, and similar). Scrollbars use standard CSS properties (`scrollbar-width`, `scrollbar-color`, `scrollbar-gutter`) — no `::-webkit-scrollbar` overrides. **Modes** — set `data-scrollbar` on ``, a component root, or a scroll slot: | Mode | `data-scrollbar` | Behavior | | ------------ | ------------------- | ---------------------------------------------- | | HeroUI thin | *(unset)* or `thin` | Thin thumb from theme tokens | | OS / browser | `default` | Native scrollbars (`auto`) | | Hidden | `none` | No visible scrollbar (`scrollbar-width: none`) | ```html
...
...
``` **Theme variables** — defined in light and dark theme blocks in [`variables.css`](https://github.com/heroui-inc/heroui/blob/v3/packages/styles/themes/default/variables.css): | Variable | Description | | -------------------- | --------------------------------------------------------- | | `--scrollbar-thumb` | Thumb color (default: 15% `--foreground` via `color-mix`) | | `--scrollbar-track` | Track color (default: `transparent`) | | `--scrollbar-gutter` | Gutter (default: `auto`) | | `--scrollbar-width` | `scrollbar-width` (default: `thin`) | | `--scrollbar-color` | `scrollbar-color` (default: thumb + track) | | `--scrollbar` | Legacy alias of `--scrollbar-thumb` | **Customize globally:** ```css /* app/globals.css */ :root { --scrollbar-thumb: color-mix(in oklch, var(--accent) 30%, transparent); --scrollbar-gutter: auto; } ``` **Per scroll slot** — pass `data-scrollbar` on a component or override tokens on a wrapper: ```tsx ...
``` **Custom overflow areas** — use the `scrollbar`, `scrollbar-thin`, `scrollbar-default`, or `scrollbar-none` utilities from `@heroui/styles` on your own elements. See [Styling](/docs/handbook/styling) for class-based overrides. > **Note**: Some components hide scrollbars by default (date picker popovers, color picker, secondary tabs). Nested scroll slots (e.g. the calendar year picker inside a date picker) keep HeroUI scrollbars because `scrollbar-none` only affects the element it is applied to, not descendants using `@apply scrollbar`. ## Vibrant Palette By default, HeroUI uses accessible soft foreground colors that mix the semantic color with the foreground for better contrast. If you prefer more saturated, vibrant soft foreground colors, add the `data-vibrant-palette` attribute to your root element: ```html ``` This switches all `*-soft-foreground` variables (accent, success, warning, danger) to use 92% of the semantic color with only 8% foreground mixed in — closer to the raw color but with a slight contrast boost. | Mode | Accessible (default) | Vibrant | | --------------- | -------------------------------------------- | ------------------------------------- | | Soft foreground | `color-mix(color 70-80%, foreground 30-40%)` | `color-mix(color 92%, foreground 8%)` | The vibrant palette prioritizes visual saturation over contrast. It may not meet WCAG accessibility guidelines for some color combinations, especially with lighter accent colors. You can also enable vibrant palette in the [Theme Builder](/themes) via the "Vibrant palette" toggle in the theme popover. ## 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)
# CLI **Category**: react **URL**: https://www.heroui.com/en/docs/react/getting-started/cli **Source**: https://raw.githubusercontent.com/heroui-inc/heroui/refs/heads/v3/apps/docs/content/docs/en/react/getting-started/(overview)/cli.mdx > Use the CLI to manage HeroUI dependencies and initialize projects. The CLI offers a comprehensive suite of commands to initialize, manage, and improve your HeroUI projects. It enables you to `install`, `uninstall`, or `upgrade` individual components, assess the health of your project, download documentation for AI coding agents, and more. ## Installation Requirements: * [Node.js version 22.22.0 or later](https://nodejs.org/en/) ### Global Installation To install `heroui-cli` globally, execute one of the following commands in your terminal: npm pnpm yarn bun ```bash npm install heroui-cli@latest -g ``` ```bash pnpm add heroui-cli@latest -g ``` ```bash yarn global add heroui-cli@latest ``` ```bash bun add heroui-cli@latest --global ``` ### Without Installation Alternatively, you can use `heroui-cli` without a global installation by running one of the following: ```bash pnpm dlx heroui-cli@latest ``` ```bash npx heroui-cli@latest ``` ```bash yarn dlx heroui-cli@latest ``` ```bash bunx heroui-cli@latest ``` ## Quick Start Once `heroui-cli` is installed, run the following command to display available commands: ```bash heroui ``` This will produce the following help output: ```bash Usage: heroui [command] Options: -v, --version Output the current version --no-cache Disable cache, by default data will be cached for 30m after the first request -d, --debug Debug mode will not install dependencies -h --help Display help information for commands Commands: init [options] [projectName] Initializes a new project install [options] Installs @heroui/react and @heroui/styles to your project upgrade [options] Upgrades @heroui/react and @heroui/styles to the latest versions uninstall [options] Uninstall @heroui/react and @heroui/styles from the project list [options] Lists installed HeroUI packages (@heroui/react, @heroui/styles) env [options] Displays debugging information for the local environment doctor [options] Checks for issues in the project agents-md [options] Downloads HeroUI documentation for AI coding agents help [command] Display help for command ``` ### init Initialize a new HeroUI project using the `init` command. This sets up your project with the necessary configurations. ```bash heroui init [options] ``` **Options:** * `-t --template [string]` The template to use for the new project e.g. app, pages, vite * `-p --package [string]` The package manager to use for the new project output: ```bash HeroUI CLI ┌ Create a new project │ ◇ Select a template (Enter to select) │ ● App (A Next.js 16 with app directory template pre-configured with HeroUI (v3) and Tailwind CSS.) │ ○ Pages (A Next.js 16 with pages directory template pre-configured with HeroUI (v3) and Tailwind CSS.) │ ○ Vite (A Vite template pre-configured with HeroUI (v3) and Tailwind CSS.) │ ◇ New project name (Enter to skip with default name) │ my-heroui-app │ ◇ Select a package manager (Enter to select) │ ● npm │ ○ yarn │ ○ pnpm │ ○ bun │ ◇ Template created successfully! │ ◇ Next steps ───────╮ │ │ │ cd my-heroui-app │ │ npm install │ │ │ ├────────────────────╯ │ └ 🚀 Get started with npm run dev ``` Install the dependencies to start the local server: ```bash cd my-heroui-app && npm install ``` ```bash cd my-heroui-app && pnpm install ``` ```bash cd my-heroui-app && yarn install ``` ```bash cd my-heroui-app && bun install ``` Start the local server: npm pnpm yarn bun ```bash npm run dev ``` ```bash pnpm run dev ``` ```bash yarn dev ``` ```bash bun run dev ``` ### Install Install `@heroui/react` and `@heroui/styles` to your project, along with their peer dependencies. If they are already installed, the command does nothing. ```bash heroui install [options] ``` **Options:** * `-p --packagePath` \[string] The path to the package.json file **Output:** ```bash HeroUI CLI 📦 Packages to be installed: ╭─────────────────────────────────────────────────────────────────────────────╮ │ Package │ Version │ Status │ Docs │ │─────────────────────────────────────────────────────────────────────────────│ │ @heroui/react │ 3.0.0 │ stable │ https://heroui.com │ │ @heroui/styles │ 3.0.0 │ stable │ https://heroui.com │ ╰─────────────────────────────────────────────────────────────────────────────╯ ╭─────────────── PeerDependencies ────────────────╮ │ react@18.3.1 latest │ │ react-dom@18.3.1 latest │ │ tailwindcss@4.2.2 latest │ ╰─────────────────────────────────────────────────╯ ? Proceed with installation? › - Use arrow-keys. Return to submit. ❯ Yes No ✅ @heroui/react and @heroui/styles installed successfully ``` ### upgrade Upgrade `@heroui/react` and `@heroui/styles` with their peer dependencies to the latest versions. ```bash heroui upgrade [options] ``` **Options:** * `-p --packagePath` \[string] The path to the package.json file **Output:** ```bash HeroUI CLI ╭──────────────────────────── Upgrade ────────────────────────────╮ │ @heroui/react ^3.0.0 -> ^3.1.0 │ │ @heroui/styles ^3.0.0 -> ^3.1.0 │ ╰─────────────────────────────────────────────────────────────────╯ ? Would you like to proceed with the upgrade? › - Use arrow-keys. Return to submit. ❯ Yes No ✅ Upgrade complete. All packages are up to date. ``` ### uninstall Uninstall `@heroui/react` and `@heroui/styles` from your project. Peer dependencies will not be uninstalled. ```bash heroui uninstall [options] ``` **Options:** * `-p --packagePath` \[string] The path to the package.json file **Output:** ```bash HeroUI CLI ❗️ Packages slated for uninstallation: ╭──────────────────────────────────────────────────────────────────────────────────────╮ │ Package │ Version │ Status │ Docs │ │──────────────────────────────────────────────────────────────────────────────────────│ │ @heroui/react │ 3.0.0 │ stable │ https://heroui.com │ │ @heroui/styles │ 3.0.0 │ stable │ https://heroui.com │ ╰──────────────────────────────────────────────────────────────────────────────────────╯ ? Confirm uninstallation of these packages: › - Use arrow-keys. Return to submit. ❯ Yes No ✅ Successfully uninstalled: @heroui/react, @heroui/styles ``` ### list List the installed HeroUI packages (`@heroui/react`, `@heroui/styles`). ```bash heroui list [options] ``` **Options:** * `-p --packagePath` \[string] The path to the package.json file **Output:** ```bash HeroUI CLI Current installed packages: ╭──────────────────────────────────────────────────────────────────────────────────────╮ │ Package │ Version │ Status │ Docs │ │──────────────────────────────────────────────────────────────────────────────────────│ │ @heroui/react │ 3.0.0 🚀latest │ stable │ https://heroui.com │ │ @heroui/styles │ 3.0.0 🚀latest │ stable │ https://heroui.com │ ╰──────────────────────────────────────────────────────────────────────────────────────╯ ``` ### doctor Check for issues in your project. * Check whether `@heroui/react` and `@heroui/styles` are installed * Check whether `required peer dependencies` are installed and matched minimal requirements in the project ```bash heroui doctor [options] ``` **Options:** * `-p --packagePath` \[string] The path to the package.json file **Output:** If there is a problem in your project, the `doctor` command will display the problem information. ```bash HeroUI CLI HeroUI CLI: ❌ Your project has 1 issue that require attention ❗️Issue 1: missingHeroUIPackages The following HeroUI packages are not installed: - @heroui/styles Run `heroui install` to install them. ``` Otherwise, the `doctor` command will display the following message. ```bash HeroUI CLI ✅ Your project has no detected issues. ``` ### env Display debug information about the local environment. ```bash heroui env [options] ``` **Options:** * `-p --packagePath` \[string] The path to the package.json file **Output:** ```bash HeroUI CLI Current installed packages: ╭──────────────────────────────────────────────────────────────────────────────────────╮ │ Package │ Version │ Status │ Docs │ │──────────────────────────────────────────────────────────────────────────────────────│ │ @heroui/react │ 3.0.0 🚀latest │ stable │ https://heroui.com │ │ @heroui/styles │ 3.0.0 🚀latest │ stable │ https://heroui.com │ ╰──────────────────────────────────────────────────────────────────────────────────────╯ Environment Info: System: OS: darwin CPU: arm64 Binaries: Node: v25.8.1 ``` ### agents-md Download HeroUI documentation for AI coding agents (Claude, Cursor, etc.). The command clones the latest docs from the HeroUI repository and injects a compact index into `AGENTS.md` or `CLAUDE.md` so assistants can reference your project's HeroUI setup. ```bash heroui agents-md [options] ``` **Options:** * `--react` \[boolean] Include React docs only (one library at a time) * `--native` \[boolean] Include Native docs only * `--migration` \[boolean] Include HeroUI v2 to v3 migration docs only * `--output ` \[string] Target file path (e.g., `AGENTS.md`, `CLAUDE.md`) * `--ssh` \[boolean] Use SSH instead of HTTPS for git clone **Examples:** Run without flags to enter interactive mode: ```bash heroui agents-md ``` Download React docs to a specific file: ```bash heroui agents-md --react --output AGENTS.md ``` Download Native or migration docs: ```bash heroui agents-md --native --output CLAUDE.md heroui agents-md --migration --output AGENTS.md ``` **How it works:** 1. Clones documentation from the `v3` branch using git sparse-checkout 2. Generates a compact index of doc and demo files 3. Injects the index into your markdown file between markers (`` / ``, and similar for Native and Migration) 4. Adds `.heroui-docs/` to `.gitignore` Only one of `--react`, `--native`, or `--migration` can be selected at a time. For more details, see [AGENTS.md](/docs/react/getting-started/agents-md). The `agents-md` command collects anonymous usage data (selection, output file names, duration, success or error). Set `HEROUI_ANALYTICS_DISABLED=1` to opt out. ## Reporting issues If you found a bug, please report it in [heroui-cli Issues](https://github.com/heroui-inc/heroui-cli/issues). # Design Principles **Category**: react **URL**: https://www.heroui.com/en/docs/react/getting-started/design-principles **Source**: https://raw.githubusercontent.com/heroui-inc/heroui/refs/heads/v3/apps/docs/content/docs/en/react/getting-started/(overview)/design-principles.mdx > Core principles that guide HeroUI v3's design and development HeroUI v3 follows 10 core principles that prioritize clarity, accessibility, customization, and developer experience. ## Core Principles ### 1. Semantic Intent Over Visual Style Use semantic naming (primary, secondary, tertiary) instead of visual descriptions (solid, flat, bordered). Inspired by [Uber's Base design system](https://base.uber.com/6d2425e9f/p/756216-button), variants follow a clear hierarchy: ```tsx // ✅ Semantic variants communicate hierarchy ``` | Variant | Purpose | Usage | | ------------- | --------------------------------- | ---------------- | | **Primary** | Main action to move forward | 1 per context | | **Secondary** | Alternative actions | Multiple allowed | | **Tertiary** | Dismissive actions (cancel, skip) | Sparingly | | **Danger** | Destructive actions | When needed | ### 2. Accessibility as Foundation Built on [React Aria Components](https://react-spectrum.adobe.com/react-aria/) for WCAG 2.1 AA compliance. Automatic ARIA attributes, keyboard navigation, and screen reader support included. ```tsx import { Tabs, TabList, Tab, TabPanel } from '@heroui/react'; Profile Security Content Content ``` ### 3. Composition Over Configuration Compound components let you rearrange, customize, or omit parts as needed. Use dot notation, named exports, or mix both. ```tsx // Compose parts to build exactly what you need import { Accordion, AccordionItem, AccordionHeading, AccordionTrigger, AccordionIndicator, AccordionPanel, AccordionBody } from '@heroui/react'; Question Text Answer content ``` ### 4. Progressive Disclosure Start simple, add complexity only when needed. Components work with minimal props and scale up as requirements grow. ```tsx // 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. Same API, same behavior. ```tsx // All components follow the same patterns ``` or with React: ```tsx // Apply styles to any component import { buttonVariants } from '@heroui/styles'; 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](https://getbem.com/) classes. Every slot is customizable. ```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. Use variant functions, direct BEM class application, or create custom wrappers. **Apply styles with variant functions:** ```tsx import { Link } from '@heroui/react'; import { linkVariants } from '@heroui/styles'; import NextLink from 'next/link'; // Use variant functions to style framework-specific components const slots = linkVariants({ underline: "hover" }); About Page ``` **Apply BEM classes directly:** ```tsx import Link from 'next/link'; // Apply HeroUI's BEM classes directly to any element Dashboard ``` **Create custom wrapper components:** ```tsx // Custom wrapper component const CTAButton = ({ intent = 'primary-cta', children, ref, ...props }: CTAButtonProps) => { const variantMap = { 'primary-cta': 'primary', 'secondary-cta': 'secondary', 'minimal': 'ghost' }; return ( ); }; ``` **Extend with Tailwind Variants:** ```tsx import { Button } from '@heroui/react'; import { buttonVariants, tv } from '@heroui/styles'; // 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 ); } ``` Example: `pages/index.tsx` ```tsx import {Button} from "@heroui/react"; export default function HomePage() { return (
); } ```
HeroUI v3 does not require a provider. Components work directly after installation and style import. ### 3 Locale Setup (Optional) To integrate with Next.js, ensure the locale on the server matches the client. In your root layout, determine the user's preferred language and set the `lang` and `dir` attributes on the `` element. ```tsx // app/layout.tsx import {headers} from 'next/headers'; import {isRTL} from '@heroui/react'; import {ClientProviders} from './provider'; export default async function RootLayout({children}) { // Get the user's preferred language from the Accept-Language header. // You could also get this from a database, URL param, etc. const acceptLanguage = (await headers()).get('accept-language'); const lang = acceptLanguage?.split(/[,;]/)[0] || 'en-US'; return ( {children} ); } ``` Create `app/provider.tsx`. This should render an `I18nProvider` to set the locale used by React Aria. ```tsx // app/provider.tsx "use client"; import {I18nProvider} from '@heroui/react'; export function ClientProviders({lang, children}) { return ( {children} ); } ``` If you are using a [Content Security Policy](https://developer.mozilla.org/en-US/docs/Web/HTTP/Guides/CSP) (CSP) with a nonce, add a `` tag to your document head, setting the content attribute to the generated nonce value. React Aria automatically reads the nonce from this tag. ## Vite ### 1. Create a Vite project ```bash npx heroui-cli@latest init ``` When prompted, select the **Vite** template. Then open your new folder and install dependencies (for example `pnpm install`). ### 2. Use your first HeroUI component Example: `src/App.tsx` ```tsx import {Button} from "@heroui/react"; function App() { return (
); } export default App; ``` HeroUI v3 does not require a provider. Components work directly after installation and style import. ## Next steps * [Quick Start](/docs/react/getting-started/quick-start) for the fastest setup path * [Themes](/docs/react/getting-started/theming) to customize colors and tokens * [Components](/docs/react/components) to explore all available components
# Quick Start **Category**: react **URL**: https://www.heroui.com/en/docs/react/getting-started/quick-start **Source**: https://raw.githubusercontent.com/heroui-inc/heroui/refs/heads/v3/apps/docs/content/docs/en/react/getting-started/(overview)/quick-start.mdx > Get started with HeroUI v3 in minutes ## Requirements * [React 19+](https://reactjs.org/) * [Tailwind CSS v4](https://tailwindcss.com/docs/installation/framework-guides) ## Quick Install \` from \`@heroui/react\` somewhere visible to confirm styles are applied. When done, summarize the changes you made and tell me how to start the dev server.`} > **Prefer to let your AI assistant do it?** Install the [HeroUI MCP Server](/docs/react/getting-started/mcp-server) in your editor, then paste the prompt into your AI assistant — it will analyze your project and handle the entire setup for you. Install HeroUI and required dependencies: ```bash npm i @heroui/styles @heroui/react ``` ```bash pnpm add @heroui/styles @heroui/react ``` ```bash yarn add @heroui/styles @heroui/react ``` ```bash bun add @heroui/styles @heroui/react ``` ## Import Styles Add to your main CSS file `globals.css`: ```css @import "tailwindcss"; @import "@heroui/styles"; /* [!code highlight]*/ ``` Import order matters. Always import `tailwindcss` first. ## Use Components ```tsx import { Button } from '@heroui/react'; function App() { return ( ); } ``` ## What's Next? * [Themes](/themes) - Create and share your own themes * [Browse Components](/docs/react/components) - See all available components * [Learn Styling](/docs/handbook/styling) - Customize with Tailwind CSS * [Explore Patterns](/docs/handbook/composition) - Master compound components # Agent Skills **Category**: react **URL**: https://www.heroui.com/en/docs/react/getting-started/agent-skills **Source**: https://raw.githubusercontent.com/heroui-inc/heroui/refs/heads/v3/apps/docs/content/docs/en/react/getting-started/(ui-for-agents)/agent-skills.mdx > Enable AI assistants to build UIs with HeroUI v3 components HeroUI Skills give your AI assistant comprehensive knowledge of HeroUI v3 components, patterns, and best practices. ### Installation ```bash curl -fsSL https://heroui.com/install | bash -s heroui-react ``` Or using the skills package: ```bash npx skills add heroui-inc/heroui ``` Support Claude Code, Cursor, OpenCode and more. ### Usage Skills are **automatically discovered** by your AI assistant, or call it directly using `/heroui-react` command. Simply ask your AI assistant to: * Build components using HeroUI v3 * Create pages with HeroUI components * Customize themes and styles * Access component documentation For more complex use cases, use the [MCP Server](/docs/react/getting-started/mcp-server) which provides real-time access to component documentation and source code. ### What's Included * HeroUI v3 installation guide * All HeroUI v3 components with props, examples, and usage patterns * Theming and styling guidelines * Design principles and composition patterns ### Structure ``` skills/heroui-react/ ├── SKILL.md # Main skill documentation ├── LICENSE.txt # Apache License 2.0 └── scripts/ # Utility scripts ├── list_components.mjs ├── get_component_docs.mjs ├── get_source.mjs ├── get_styles.mjs ├── get_theme.mjs └── get_docs.mjs ``` ### Related Documentation * [Agent Skills Specification](https://agentskills.io/home) - Learn about the Agent Skills format * [Claude Agent Skills](https://platform.claude.com/docs/en/agents-and-tools/agent-skills/overview) - Claude's Skills documentation * [Cursor Skills](https://cursor.com/docs/context/skills) - Using Skills in Cursor * [OpenCode Skills](https://opencode.ai/docs/skills) - Using Skills in OpenCode # AGENTS.md **Category**: react **URL**: https://www.heroui.com/en/docs/react/getting-started/agents-md **Source**: https://raw.githubusercontent.com/heroui-inc/heroui/refs/heads/v3/apps/docs/content/docs/en/react/getting-started/(ui-for-agents)/agents-md.mdx > Download HeroUI v3 React documentation for AI coding agents Download HeroUI v3 React documentation directly into your project for AI assistants to reference. **Note:** The `agents-md` command is specifically for HeroUI React v3. Other CLI commands (like `add`, `init`, `upgrade`, etc.) are for HeroUI v2 (for now). ### Usage ```bash npx heroui-cli@latest agents-md --react ``` Or specify output file: ```bash npx heroui-cli@latest agents-md --react --output AGENTS.md ``` ### What It Does * Downloads latest HeroUI v3 React docs to `.heroui-docs/react/` * Generates an index in `AGENTS.md` or `CLAUDE.md` * Includes demo files for code examples * Adds `.heroui-docs/` to `.gitignore` automatically ### Options * `--react` - Download React docs only * `--output ` - Target file(s) (e.g., `AGENTS.md` or `AGENTS.md CLAUDE.md`) * `--ssh` - Use SSH for git clone ### Requirements * Tailwind CSS >= v4 * React >= 19.0.0 * `@heroui/react >= 3.0.0` or `@latest` ### Related Documentation * [AGENTS.md](https://agents.md/) - Learn about the AGENTS.md format for coding agents * [CLAUDE.md](https://code.claude.com/docs/en/best-practices#write-an-effective-claude-md) - Claude equivalent of AGENTS.md * [AGENTS.md vs Skills](https://vercel.com/blog/agents-md-outperforms-skills-in-our-agent-evals) - AGENTS.md performance # LLMs.txt **Category**: react **URL**: https://www.heroui.com/en/docs/react/getting-started/llms-txt **Source**: https://raw.githubusercontent.com/heroui-inc/heroui/refs/heads/v3/apps/docs/content/docs/en/react/getting-started/(ui-for-agents)/llms-txt.mdx > Enable AI assistants like Claude, Cursor, and Windsurf to understand HeroUI v3 We provide [LLMs.txt](https://llmstxt.org/) files to make HeroUI v3 documentation accessible to AI coding assistants. ## Available Files **Core documentation:** * [/react/llms.txt](/react/llms.txt) — Quick reference index for React documentation * [/react/llms-full.txt](/react/llms-full.txt) — Complete HeroUI React documentation **For limited context windows:** * [/react/llms-components.txt](/react/llms-components.txt) — Component documentation only * [/react/llms-patterns.txt](/react/llms-patterns.txt) — Common patterns and recipes **All platforms:** * [/llms.txt](/llms.txt) — Quick reference index (React + Native) * [/llms-full.txt](/llms-full.txt) — Complete documentation (React + Native) * [/llms-components.txt](/llms-components.txt) — All component documentation * [/llms-patterns.txt](/llms-patterns.txt) — All patterns and recipes ## Integration **Claude Code:** Tell Claude to reference the documentation: ``` Use HeroUI React documentation from https://heroui.com/react/llms.txt ``` Or add to your project's `.claude` file for automatic loading. **Cursor:** Use the `@Docs` feature: ``` @Docs https://heroui.com/react/llms-full.txt ``` [Learn more](https://docs.cursor.com/context/@-symbols/@-docs) **Windsurf:** Add to your `.windsurfrules` file: ``` #docs https://heroui.com/react/llms-full.txt ``` [Learn more](https://docs.codeium.com/windsurf/memories#memories-and-rules) **Other AI tools:** Most AI assistants can reference documentation by URL. Simply provide: ``` https://heroui.com/react/llms.txt ``` **For component-specific documentation:** ``` https://heroui.com/react/llms-components.txt ``` **For patterns and best practices:** ``` https://heroui.com/react/llms-patterns.txt ``` ## Contributing Found an issue with AI-generated code? Help us improve our LLMs.txt files on [GitHub](https://github.com/heroui-inc/heroui). # MCP Server **Category**: react **URL**: https://www.heroui.com/en/docs/react/getting-started/mcp-server **Source**: https://raw.githubusercontent.com/heroui-inc/heroui/refs/heads/v3/apps/docs/content/docs/en/react/getting-started/(ui-for-agents)/mcp-server.mdx > Access HeroUI v3 documentation directly in your AI assistant The HeroUI MCP Server gives AI assistants direct access to HeroUI v3 component documentation, making it easier to build with HeroUI in AI-powered development environments. The MCP server currently supports **@heroui/react v3** only and [stdio transport](https://modelcontextprotocol.io/specification/2025-06-18/basic/transports#stdio). Published at `@heroui/react-mcp` on npm. View the source code on [GitHub](https://github.com/heroui-inc/heroui-mcp). As we add more components to HeroUI v3, they'll be available in the MCP server too. ## Quick Setup ### Cursor
Install in Cursor
Or manually add to **Cursor Settings** → **Tools** → **MCP Servers**: ```json title=".cursor/mcp.json" { "mcpServers": { "heroui-react": { "command": "npx", "args": ["-y", "@heroui/react-mcp@latest"] } } } ``` Alternatively, add the following to your `~/.cursor/mcp.json` file. To learn more, see the [Cursor documentation](https://cursor.com/docs/context/mcp). ### Claude Code Run this command in your terminal: ```bash claude mcp add heroui-react -- npx -y @heroui/react-mcp@latest ``` Or manually add to your project's `.mcp.json` file: ```json title=".mcp.json" { "mcpServers": { "heroui-react": { "command": "npx", "args": ["-y", "@heroui/react-mcp@latest"] } } } ``` After adding the configuration, restart Claude Code and run `/mcp` to see the HeroUI MCP server in the list. If you see **Connected**, you're ready to use it. See the [Claude Code MCP documentation](https://docs.claude.com/en/docs/claude-code/mcp) for more details. ### Windsurf Add the HeroUI server to your project's `.windsurf/mcp.json` configuration file: ```json title=".windsurf/mcp.json" { "mcpServers": { "heroui-react": { "command": "npx", "args": ["-y", "@heroui/react-mcp@latest"] } } } ``` After adding the configuration, restart Windsurf to activate the MCP server. See the [Windsurf MCP documentation](https://docs.windsurf.com/windsurf/cascade/mcp) for more details. ### Zed Add the HeroUI server to your `settings.json` configuration file. Open settings via Command Palette (`zed: open settings`) or use `Cmd-,` (Mac) / `Ctrl-,` (Linux): ```json title="settings.json" { "context_servers": { "heroui-react": { "command": "npx", "args": ["-y", "@heroui/react-mcp@latest"], "env": {} } } } ``` After adding the configuration, restart Zed and open the Agent Panel settings view. Check that the indicator dot next to the heroui server is green with "Server is active" tooltip. See the [Zed MCP documentation](https://zed.dev/docs/ai/mcp) for more details. ### VS Code To configure MCP in VS Code with GitHub Copilot, add the HeroUI server to your project's `.vscode/mcp.json` configuration file: ```json title=".vscode/mcp.json" { "servers": { "heroui-react": { "type": "stdio", "command": "npx", "args": ["-y", "@heroui/react-mcp@latest"] } } } ``` After adding the configuration, open `.vscode/mcp.json` and click **Start** next to the heroui-react server. See the [VS Code MCP documentation](https://code.visualstudio.com/docs/copilot/customization/mcp-servers) for more details. ### Codex Add the HeroUI server to your `~/.codex/config.toml` (or a project-scoped `.codex/config.toml`): ```toml title="config.toml" [mcp_servers.heroui-react] command = "npx" args = ["-y", "@heroui/react-mcp@latest"] ``` After adding the configuration, restart Codex and run `/mcp` in the TUI to verify the server is active. See the [Codex MCP documentation](https://developers.openai.com/codex/mcp) for more details. ### OpenCode Add the HeroUI server to your project's `opencode.json` configuration file: ```json title="opencode.json" { "$schema": "https://opencode.ai/config.json", "mcp": { "heroui-react": { "type": "local", "command": ["npx", "-y", "@heroui/react-mcp@latest"] } } } ``` After adding the configuration, restart OpenCode to activate the MCP server. See the [OpenCode MCP documentation](https://open-code.ai/docs/en/mcp-servers) for more details. ## Usage Once configured, ask your AI assistant questions like: * "Help me install HeroUI v3 in my Next.js/Vite/Astro app" * "Show me all HeroUI components" * "What props does the Button component have?" * "Give me an example of using the Card component" * "Get the source code for the Button component" * "Show me the CSS styles for Card" * "What are the theme variables for dark mode?" ### Automatic Updates The MCP server can help you upgrade to the latest HeroUI version: ```bash "Hey Cursor, update HeroUI to the latest version" ``` Your AI assistant will automatically: * Compare your current version with the latest release * Review the changelog for breaking changes * Apply the necessary code updates to your project This works for any version upgrade, whether you're updating to the latest stable or pre-release version. ## Available Tools The MCP server provides these tools to AI assistants: | Tool | Description | | ----------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------- | | `list_components` | List all available HeroUI v3 components | | `get_component_docs` | Get complete component documentation including anatomy, props, examples, and usage patterns for one or more components | | `get_component_source_code` | Access the React/TypeScript source code (.tsx files) for components | | `get_component_source_styles` | View the CSS styles (.css files) for components | | `get_theme_variables` | Access theme variables for colors, typography, spacing with light/dark mode support | | `get_docs` | Browse the full HeroUI v3 documentation including guides and principles (use path `/docs/react/getting-started/quick-start` for installation instructions) | ## Troubleshooting **Requirements:** Node.js 22 or higher. The package will be automatically downloaded when using `npx`. **Need help?** [GitHub Issues](https://github.com/heroui-inc/heroui-mcp/issues) | [Discord Community](https://discord.gg/heroui) ## Links * [npm Package](https://www.npmjs.com/package/@heroui/react-mcp) * [GitHub Repository](https://github.com/heroui-inc/heroui-mcp) * [Contributing Guide](https://github.com/heroui-inc/heroui-mcp/blob/main/CONTRIBUTING.md) # 动画 **Category**: native **URL**: https://www.heroui.com/cn/docs/native/getting-started/animation **Source**: https://raw.githubusercontent.com/heroui-inc/heroui/refs/heads/v3/apps/docs/content/docs/cn/native/getting-started/(handbook)/animation.mdx > 为 HeroUI Native 组件添加流畅动画与过渡 HeroUI Native 的动画基于 [react-native-reanimated](https://docs.swmansion.com/react-native-reanimated/),手势由 [react-native-gesture-handler](https://docs.swmansion.com/react-native-gesture-handler/) 处理。若需更细粒度控制,建议先熟悉二者。 ## `animation` 属性 每个带动画的组件都暴露统一的 `animation` 属性,用于控制该组件上的全部动画:可调整数值、时间配置、布局动画,或完全关闭动画。 **做法:** 处理动画时,先查看目标组件是否提供 `animation` 属性。 ## 修改动画 向 `animation` 传入对象即可定制。不同组件暴露的可调属性不同。若只想微调内置动画,可使用我们提供的各项配置;若要完全自定义动画逻辑,通常需要自行编写带动画的自定义组件。 ### 示例 1:简单数值调整 调整缩放、透明度或颜色等数值: ```tsx import {Switch} from 'heroui-native'; ; ``` ### 示例 2:时间曲线配置 自定义时长与缓动: ```tsx import {Accordion} from 'heroui-native'; ; ``` ### 示例 3:布局动画(进入 / 退出) 使用 Reanimated 的布局动画 API: ```tsx import {Accordion} from 'heroui-native'; import {FadeInRight, FadeInLeft, ZoomIn} from 'react-native-reanimated'; import {Easing} from 'react-native-reanimated'; Content here ; ``` ### 示例 4:使用 `state` 精细控制 `state` 可在关闭动画的同时仍保留属性配置,便于微调而不真正播放动画: ```tsx import {Switch} from 'heroui-native'; ``` `state` 可取: * `'disabled'`:关闭动画,但仍可配置属性值 * `'disable-all'`:关闭自身及子级全部动画(仅在根级可用) * `boolean`:简单开关(`true` 启用,`false` 禁用) 这样既能精细控制动画行为,又能在不启用动画的情况下自定义属性值。 ## 关闭动画 可通过 `animation` 在不同层级关闭动画。 ### 关闭选项 * `animation={false}` 或 `animation="disabled"`:仅关闭当前组件动画 * `animation="disable-all"`:关闭根级及其子级全部动画(仅根级可用) * `animation={true}` 或 `animation={undefined}`:使用默认动画 ### 组件级关闭 仅关闭某个子部件的动画: ```tsx ``` ### 根级 `disable-all` `"disable-all"` 仅在复合组件根级可用,会向下级联,**包括**树中的独立组件(如 `Button`、`Spinner` 等),不仅限于复合子部件: ```tsx // Disables all animations including Button components inside Card $450 Living room Sofa ``` **注意:** `"disable-all"` 会级联到所有子组件,包括独立的 `Button`、`Spinner` 等。 ## 全局动画配置 在 `HeroUINativeProvider` 上统一关闭应用内全部 HeroUI Native 动画: ```tsx import {HeroUINativeProvider} from 'heroui-native'; ; ``` 这会覆盖各组件自身的 `animation` 设置,全局禁用动画。 ## 无障碍 系统「减少动态效果」会在底层自动处理:当用户开启该无障碍选项时,库会通过 `GlobalAnimationSettingsProvider` 与 Reanimated 的 `useReducedMotion()` 全局关闭动画。 你通常无需额外编码,库会尊重系统无障碍偏好。 ## 动画状态管理 内部会统一管理禁用态,避免关闭动画后出现卡顿或跳变:禁用时组件会直接落到终态,而不是播放到一半。 ## 子级渲染函数 许多组件支持将 `children` 设为函数,便于根据 `isSelected` 等状态渲染: ```tsx import {Switch} from 'heroui-native'; {({isSelected, isDisabled}) => ( {isSelected ? : } )} ; ``` 该模式便于根据选中、禁用等状态构建动态界面。 ## 下一步 * [样式](/docs/native/getting-started/styling) * [主题](/docs/native/getting-started/theming) * [颜色](/docs/native/getting-started/colors) # 颜色 **Category**: native **URL**: https://www.heroui.com/cn/docs/native/getting-started/colors **Source**: https://raw.githubusercontent.com/heroui-inc/heroui/refs/heads/v3/apps/docs/content/docs/cn/native/getting-started/(handbook)/colors.mdx > HeroUI Native 的调色板与主题系统 import {ColorSectionSideBySide, ColorSectionStacked, ColorSectionFormField, ColorSectionPrimitive} from "@/components/color-section"; HeroUI Native 的颜色体系围绕语义意图构建,而非堆砌视觉色板。系统不会暴露庞大的原始色表,而是定义一小套有意义的色彩角色,覆盖绝大多数界面需求。 系统中的多数颜色会由少量基础值自动派生。这样 HeroUI 能在保持对比度、层级与主题行为一致的同时,让整套体系易于理解与修改。 颜色应首先传达用途与状态;视觉变化来自尺度、强调与上下文。 ## 强调色 强调色代表品牌或产品的主识别色,用于吸引对关键操作、高亮与重点时刻的注意。 强调色应有意识地节制使用。滥用会削弱其冲击力,并破坏视觉层级。多数情况下,组件会从基础强调色自动派生悬停、柔和背景与聚焦等相关取值。 ## 默认(中性色) 默认色构成系统的中性骨架,用于大多数非强调的界面元素。 ## 成功 成功色传达积极结果、确认与完成状态,常见于反馈组件、状态指示与校验通过等场景。 ## 警告 警告色表示需谨慎、存在风险,或需要留意但非破坏性的操作,常用于提示、消息以及用户应暂停或复核信息的过渡状态。 ## 危险 危险色表示破坏性、不可逆或关键的操作与状态,应一眼可辨,并稳定用于错误、危险按钮与严重告警。 ## 前景色 前景色用于正文级内容,如文字与图标。这些颜色针对可读性与无障碍优化,并会随背景与表面上下文自动适配。请勿在组件内硬编码前景色。 ## 背景色 背景色定义界面的基底画布,在保持视觉克制的前提下建立整体对比与氛围。 ## 表面色 表面色叠在背景之上,用于卡片、面板、模态与下拉等容器。表面通过抬升、对比与分层形成区隔与层级,而非依赖强烈的色相跳跃。 ## 表单字段 表单字段色是面向输入、控件与可交互字段的专用令牌,覆盖默认、聚焦与悬停等多种状态。将其独立出来,可让表单元素在视觉上与按钮及界面其余部分保持清晰区分。 ## 分隔线 分隔线色用于分割线、描边与轻量边界,用来组织内容、引导视线而不增加噪点。分隔线色应保持低对比、不抢眼。 ## 其他 其他颜色在界面中承担特定工具性角色,用于组织内容、引导视线而不增加噪点。 ## 基础色 基础色是与模式无关的底层取值,作为语义色令牌的根基,在明暗主题之间不会改变。 ## 如何使用颜色 **在组件中:** ```tsx import { View, Text } from 'react-native'; 内容 ; ``` **在 CSS 文件中:** ```css title="global.css" /* 直接使用 CSS 变量 */ .container { flex: 1; background-color: var(--accent); width: 50px; height: 50px; border-radius: var(--radius); } ``` ## 默认主题 完整主题定义见仓库中的 [variables.css](https://github.com/heroui-inc/heroui-native/blob/main/src/styles/variables.css)。该主题通过 [Uniwind 主题系统](https://docs.uniwind.dev/theming/basics) 在明暗模式间自动切换,并支持跟随系统与在代码中切换主题。 ```css @theme { /* 基础色(在明暗模式间保持不变) */ --white: oklch(100% 0 0); --black: oklch(0% 0 0); --snow: oklch(0.9911 0 0); --eclipse: oklch(0.2103 0.0059 285.89); /* 边框 */ --border-width: 1px; --field-border-width: 0px; /* 基础圆角 */ --radius: 0.5rem; --field-radius: calc(var(--radius) * 1.5); /* 不透明度 */ --opacity-disabled: 0.5; } @layer theme { :root { @variant light { /* 基础颜色 */ --background: oklch(0.9702 0 0); --foreground: var(--eclipse); /* 表面 */ --surface: var(--white); --surface-foreground: var(--foreground); --surface-secondary: oklch(0.9524 0.0013 286.37); --surface-secondary-foreground: var(--foreground); --surface-tertiary: oklch(0.9373 0.0013 286.37); --surface-tertiary-foreground: var(--foreground); /* 覆盖层 */ --overlay: var(--white); --overlay-foreground: var(--foreground); --backdrop: oklch(0% 0 0 / 20%); --muted: oklch(0.5517 0.0138 285.94); --default: oklch(94% 0.001 286.375); --default-foreground: var(--eclipse); --accent: oklch(0.6204 0.195 253.83); --accent-foreground: var(--snow); /* 表单字段 */ --field-background: var(--white); --field-foreground: oklch(0.2103 0.0059 285.89); --field-placeholder: var(--muted); --field-border: transparent; /* 状态色 */ --success: oklch(0.7329 0.1935 150.81); --success-foreground: var(--eclipse); --warning: oklch(0.7819 0.1585 72.33); --warning-foreground: var(--eclipse); --danger: oklch(0.6532 0.2328 25.74); --danger-foreground: var(--snow); /* 组件颜色 */ --segment: var(--white); --segment-foreground: var(--eclipse); /* 杂项颜色 */ --border: oklch(90% 0.004 286.32); --separator: oklch(74% 0.004 286.32); --focus: var(--accent); --link: var(--foreground); } @variant dark { /* 基础颜色 */ --background: oklch(12% 0.005 285.823); --foreground: var(--snow); /* 表面 */ --surface: oklch(0.2103 0.0059 285.89); --surface-foreground: var(--foreground); --surface-secondary: oklch(0.257 0.0037 286.14); --surface-secondary-foreground: var(--foreground); --surface-tertiary: oklch(0.2721 0.0024 247.91); --surface-tertiary-foreground: var(--foreground); /* 覆盖层 */ --overlay: oklch(0.2103 0.0059 285.89); --overlay-foreground: var(--foreground); --backdrop: oklch(0% 0 0 / 20%); --muted: oklch(70.5% 0.015 286.067); --default: oklch(27.4% 0.006 286.033); --default-foreground: var(--snow); --accent: oklch(0.6204 0.195 253.83); --accent-foreground: var(--snow); /* 表单字段 */ --field-background: oklch(0.2103 0.0059 285.89); --field-foreground: var(--foreground); --field-placeholder: var(--muted); --field-border: transparent; /* 状态色 */ --success: oklch(0.7329 0.1935 150.81); --success-foreground: var(--eclipse); --warning: oklch(0.8203 0.1388 76.34); --warning-foreground: var(--eclipse); --danger: oklch(0.594 0.1967 24.63); --danger-foreground: var(--snow); /* 组件颜色 */ --segment: oklch(0.3964 0.01 285.93); --segment-foreground: var(--foreground); /* 杂项颜色 */ --border: oklch(28% 0.006 286.033); --separator: oklch(40% 0.006 286.033); --focus: var(--accent); --link: var(--foreground); } } } ``` ## 自定义颜色 **覆盖已有颜色:** ```css @layer theme { @variant light { /* 覆盖默认颜色 */ --accent: oklch(0.65 0.25 270); /* 自定义靛蓝强调色 */ --success: oklch(0.65 0.15 155); } @variant dark { /* 覆盖深色主题颜色 */ --accent: oklch(0.65 0.25 270); --success: oklch(0.75 0.12 155); } } ``` **提示:** 可在 [oklch.com](https://oklch.com) 转换颜色。 **添加自定义颜色:** ```css @layer theme { @variant light { --info: oklch(0.6 0.15 210); --info-foreground: oklch(0.98 0 0); } @variant dark { --info: oklch(0.7 0.12 210); --info-foreground: oklch(0.15 0 0); } } @theme inline { --color-info: var(--info); --color-info-foreground: var(--info-foreground); } ``` 随后即可使用: ```tsx import { View, Text } from 'react-native'; 提示信息 ; ``` > **注意:** 若要进一步了解主题变量及其在 Tailwind CSS v4 中的行为,请参阅 [Tailwind CSS 主题文档](https://tailwindcss.com/docs/theme)。 ## useThemeColor 钩子 `useThemeColor` 钩子已增强,支持一次选取多种颜色,在复杂主题场景下更灵活。 **一次选取多种颜色:** 现在可以同时选取多种颜色,在需要一并处理相关色值时很有用: ```tsx import { useThemeColor } from 'heroui-native'; // 一次选取多种颜色 const [accent, accentForeground, success, danger] = useThemeColor([ 'accent', 'accentForeground', 'success', 'danger', ]); // 使用所选颜色 强调色文字 ; ``` 该改进在需要同时选取并应用多种颜色时,可提升性能,也便于管理复杂的主题组合。 # 组合 **Category**: native **URL**: https://www.heroui.com/cn/docs/native/getting-started/composition **Source**: https://raw.githubusercontent.com/heroui-inc/heroui/refs/heads/v3/apps/docs/content/docs/cn/native/getting-started/(handbook)/composition.mdx > 用组件组合模式搭建灵活 UI HeroUI Native 通过组合模式实现灵活、可定制的组件:可更换实际渲染元素、将多个部件拼在一起,并完全掌控结构。 ## 复合组件 HeroUI Native 采用点记法的复合组件——子组件作为属性导出(如 `Button.Label`、`Dialog.Trigger`、`Accordion.Item`),共同构成完整界面。 ```tsx import { Button, Dialog } from 'heroui-native'; function DialogExample() { return ( 打开对话框 对话框标题 对话框说明 ); } ``` ## asChild 属性 `asChild` 用于改变组件实际渲染的元素。为 `true` 时,HeroUI Native 会克隆子元素并合并属性,而不是渲染默认包裹节点。 ```tsx import { Button, Dialog } from 'heroui-native'; function DialogExample() { return ( {/* asChild:Button 直接作为触发器,无额外包裹 */} {/* Dialog.Close 也可使用 asChild */} 对话框标题 对话框说明 ); } ``` ## 自定义组件 通过组合 HeroUI Native 原语封装自己的组件: ```tsx import { Button, Card, Popover } from 'heroui-native'; import { View } from 'react-native'; // 商品卡片 function ProductCard({ title, description, price, onBuy, ...props }) { return ( {price} {title} {description} ); } // 带 Popover 的按钮 function PopoverButton({ children, popoverContent, ...props }) { return ( {popoverContent} ); } // 用法 console.log('购买')} /> 说明 更多详情见此处 }> 显示说明 ``` ## 自定义变体 可用 `tailwind-variants` 扩展样式。**文字颜色类须加在 `Button.Label` 上,而不是父级 `Button`:** ```tsx import { Button } from 'heroui-native'; import type { ButtonRootProps } from 'heroui-native'; import { tv, type VariantProps } from 'tailwind-variants'; const customButtonVariants = tv({ base: 'font-semibold rounded-lg', variants: { intent: { primary: 'bg-blue-500', secondary: 'bg-gray-200', danger: 'bg-red-500', }, }, defaultVariants: { intent: 'primary', }, }); const customLabelVariants = tv({ base: '', variants: { intent: { primary: 'text-white', secondary: 'text-gray-800', danger: 'text-white', }, }, defaultVariants: { intent: 'primary', }, }); type CustomButtonVariants = VariantProps; interface CustomButtonProps extends Omit, CustomButtonVariants { className?: string; labelClassName?: string; } export function CustomButton({ intent, className, labelClassName, children, ...props }: CustomButtonProps) { return ( ); } ``` ## 下一步 * 了解 [样式](/docs/native/getting-started/styling) 体系 * 阅读 [主题](/docs/native/getting-started/theming) 文档 * 探索 [动画](/docs/native/getting-started/animation) 选项 # Portal **Category**: native **URL**: https://www.heroui.com/cn/docs/native/getting-started/portal **Source**: https://raw.githubusercontent.com/heroui-inc/heroui/refs/heads/v3/apps/docs/content/docs/cn/native/getting-started/(handbook)/portal.mdx Portal 可将子节点渲染到应用中的其他位置,特别适用于需要浮在其他内容之上的组件,例如模态框、覆盖层与弹出层。 ## 默认配置 默认情况下,`PortalHost` 已包含在 `HeroUINativeProvider` 中,无需手动添加。Provider 会自动为所有使用 Portal 的组件设置好Portal系统。 ## 进阶用法 如需自定义Portal实现,可直接从 `heroui-native` 导入 `Portal` 与 `PortalHost`: ```tsx import { Portal, PortalHost } from "heroui-native"; import { View, Text } from "react-native"; function AppLayout() { return ( Header Content Main Content Area {/* Portal host positioned at the top of the screen */} ); } function CustomNotification() { return ( This notification appears at the top via Portal ); } ``` 本例中,`CustomNotification` 组件通过 `Portal` 将内容渲染到位于屏幕顶部的 `PortalHost` 处,使通知浮于所有其他内容之上,无论它在组件树中的实际定义位置在哪。 ## 状态管理注意事项 父组件中的状态变化可能导致Portal内组件出现意外问题。例如,将文本输入框直接放入Portal内时,若父组件触发重渲染,可能会重置输入框的自动建议,或导致其他界面异常。 为避免该问题,请将交互组件(如输入框)的状态保留在Portal内部:把Portal内容拆分为独立组件,从而隔离父组件重渲染带来的影响。 ### 示例模式 ```tsx // ❌ 问题:父级状态导致重渲染,影响Portal内内容 function ParentComponent() { const [dialogOpen, setDialogOpen] = useState(false); const [inputValue, setInputValue] = useState(""); // State in parent return ( ); } // ✅ 正确:在Portal内的独立组件中管理状态 function ParentComponent() { const [dialogOpen, setDialogOpen] = useState(false); return ( setDialogOpen(false)} // Form state isolated from parent /> ); } function DialogFormContent({ onClose }: { onClose: () => void }) { const [inputValue, setInputValue] = useState(""); // State inside portal const [error, setError] = useState(""); return ( {error} ); } ``` 在正确示例中,`DialogFormContent` 独立于父组件管理自身状态。这样即便父组件因 `dialogOpen` 等变化而重渲染,也不会影响输入框的内部状态,从而保留自动建议等输入行为。 ## API 参考 ### PortalHost 默认情况下,所有 `Portal` 组件的子内容都会作为该 `PortalHost` 的子节点进行渲染。 | prop | type | description | | ---- | -------- | ---------------- | | name | `string` | 作为自定义宿主使用时提供(可选) | ### Portal | prop | type | description | | -------- | ----------------- | -------------------------- | | name\* | `string` | 唯一值;同名 Portal 会替换原有 Portal | | hostName | `string` | 子内容需要渲染到自定义宿主时提供(可选) | | children | `React.ReactNode` | 要渲染到Portal中的内容 | \* 必填属性 ## 相关链接 * [快速开始](/docs/native/getting-started/quick-start) — 基础搭建指南 * 查阅 [Provider](/docs/native/getting-started/provider) 文档 # Provider **Category**: native **URL**: https://www.heroui.com/cn/docs/native/getting-started/provider **Source**: https://raw.githubusercontent.com/heroui-inc/heroui/refs/heads/v3/apps/docs/content/docs/cn/native/getting-started/(handbook)/provider.mdx > 配置 HeroUI Native 的文本、动画与 Toast 等全局能力 `HeroUINativeProvider` 是根级 Provider,用于在 React Native 应用中初始化并配置 HeroUI Native,提供全局配置与Portal管理。 ## 概览 Provider 作为 HeroUI Native 的主入口,为应用包裹必要的上下文与配置: * **安全区内边距**:通过 `SafeAreaListener` 自动同步安全区变化,并写入 Uniwind,便于在 Tailwind 中使用(如 `pb-safe-offset-3`) * **文本配置**:全局 Text 相关设置,保证各 HeroUI 组件文本表现一致 * **动画配置**:全局控制是否关闭应用内全部动画 * **Toast 配置**:全局 Toast 系统(边距、默认属性、内容包裹层等) * **Portal管理**:处理叠层、模态等需要浮在应用层级之上的组件 ## 基础用法 在应用根节点使用 Provider: ```tsx import { HeroUINativeProvider } from 'heroui-native'; import { GestureHandlerRootView } from 'react-native-gesture-handler'; export default function App() { return ( {/* Your app content */} ); } ``` ## 配置项 Provider 接受 `config` 属性,常用分组如下。 ### 文本组件配置 面向 HeroUI Native 内所有 Text 的全局设置。仅包含适合「全局统一」调整的属性: ```tsx import { HeroUINativeProvider } from 'heroui-native'; import type { HeroUINativeConfig } from 'heroui-native'; const config: HeroUINativeConfig = { textProps: { // Disable font scaling for accessibility allowFontScaling: false, // Auto-adjust font size to fit container adjustsFontSizeToFit: false, // Maximum font size multiplier when scaling maxFontSizeMultiplier: 1.5, // Minimum font scale (iOS only, 0.01-1.0) minimumFontScale: 0.5, }, }; export default function App() { return ( {/* Your app content */} ); } ``` ### 动画配置 应用级动画开关: ```tsx const config: HeroUINativeConfig = { // Disable all animations across the application (cascades to all children) animation: 'disable-all', }; ``` **说明:** 设为 `'disable-all'` 后,应用内全部动画将被关闭,可用于无障碍或性能优化场景。 ### 开发者信息配置 控制开发环境下控制台中的提示信息: ```tsx const config: HeroUINativeConfig = { devInfo: { // Disable styling principles information message stylingPrinciples: false, }, }; ``` **说明:** 默认会输出信息类日志。将 `stylingPrinciples: false` 可关闭开发时关于样式原则的提示。 ### Toast 配置 配置全局 Toast(边距、默认属性、包裹层等),也可完全关闭 Toast: **方式一:关闭 Toast Provider** ```tsx const config: HeroUINativeConfig = { // Disable toast provider entirely toast: false, // or toast: 'disabled', }; ``` **说明:** 当 `toast` 为 `false` 或 `'disabled'` 时,不会渲染 `ToastProvider`,应用内无法使用 Toast。 **方式二:配置 Toast Provider** ```tsx import { KeyboardAvoidingView } from 'react-native'; const config: HeroUINativeConfig = { toast: { // Global toast configuration (used as defaults for all toasts) defaultProps: { variant: 'default', placement: 'top', isSwipeable: true, animation: true, }, // Insets for spacing from screen edges (added to safe area insets) insets: { top: 0, // Default: iOS = 0, Android = 12 bottom: 6, // Default: iOS = 6, Android = 12 left: 12, // Default: 12 right: 12, // Default: 12 }, // Maximum number of visible toasts before opacity starts fading maxVisibleToasts: 3, // Custom wrapper function to wrap the toast content contentWrapper: (children) => ( {children} ), }, }; ``` ## 完整示例 综合展示各项配置: ```tsx import { HeroUINativeProvider } from 'heroui-native'; import type { HeroUINativeConfig } from 'heroui-native'; import { GestureHandlerRootView } from 'react-native-gesture-handler'; const config: HeroUINativeConfig = { // Global text configuration textProps: { minimumFontScale: 0.5, maxFontSizeMultiplier: 1.5, allowFontScaling: true, adjustsFontSizeToFit: false, }, // Global animation configuration animation: 'disable-all', // Optional: disable all animations // Developer information messages configuration devInfo: { stylingPrinciples: true, // Optional: disable styling principles message }, // Global toast configuration // Option 1: Configure toast with custom settings toast: { defaultProps: { variant: 'default', placement: 'top', }, insets: { top: 0, bottom: 6, left: 12, right: 12, }, maxVisibleToasts: 3, }, // Option 2: Disable toast entirely // toast: false, // or // toast: 'disabled', }; export default function App() { return ( ); } ``` ## 与 Expo Router 集成 使用 Expo Router 时,在根布局中包裹: ```tsx // app/_layout.tsx import { HeroUINativeProvider } from 'heroui-native'; import type { HeroUINativeConfig } from 'heroui-native'; import { Stack } from 'expo-router'; const config: HeroUINativeConfig = { textProps: { minimumFontScale: 0.5, maxFontSizeMultiplier: 1.5, }, }; export default function RootLayout() { return ( ); } ``` ## 架构 ### Provider 层级 `HeroUINativeProvider` 内部由多层 Provider 组合而成: ``` HeroUINativeProvider ├── SafeAreaListener (handles safe area insets updates) │ └── GlobalAnimationSettingsProvider (animation configuration) │ └── TextComponentProvider (text configuration) │ └── ToastProvider (toast configuration, conditionally rendered) │ └── Your App │ └── PortalHost (for overlays) ``` **说明:** `ToastProvider` 是否渲染取决于 `toast` 配置。当 `toast` 为 `false` 或 `'disabled'` 时,不会渲染 `ToastProvider`,应用内容与 `PortalHost` 将直接挂在 `TextComponentProvider` 之下。 ### 安全区内边距处理 Provider 会自动使用 `react-native-safe-area-context` 的 [`SafeAreaListener`](https://appandflow.github.io/react-native-safe-area-context/api/safe-area-listener) 包裹应用。该组件监听安全区与帧的变化但不会触发重渲染,并通过 `onChange` 回调将最新的 insets 同步给 Uniwind。 ## 轻量 Provider(Raw) `HeroUINativeProviderRaw` 是面向包体优化的精简版,不包含 `ToastProvider` 与 `PortalHost`,仅保留最小起点,按需自行组合能力。 ### 何时使用 当你希望精确控制打包进应用的依赖时,可使用 Raw Provider。从 `heroui-native/provider-raw` 导入后,下列依赖仅在用到对应组件时才需要: * **react-native-screens** — 浮层类组件(Popover、Dialog)需要 * **@gorhom/bottom-sheet** — BottomSheet 需要 * **react-native-svg** — 使用图标的组件(Accordion、Alert、Checkbox 等)需要 ### 接入 ```tsx import { HeroUINativeProviderRaw, type HeroUINativeConfigRaw, } from 'heroui-native/provider-raw'; import { GestureHandlerRootView } from 'react-native-gesture-handler'; const config: HeroUINativeConfigRaw = { textProps: { maxFontSizeMultiplier: 1.5, }, }; export default function App() { return ( {/* Your app content */} ); } ``` ### 手动添加 Toast 与 Portal 使用 Raw Provider 且仍需要 Toast 或 Portal 时,请自行组合: ```tsx import { HeroUINativeProviderRaw } from 'heroui-native/provider-raw'; import { PortalHost } from 'heroui-native/portal'; import { ToastProvider } from 'heroui-native/toast'; export default function App() { return ( {/* Your app content */} ); } ``` ### Raw 的层级 ``` HeroUINativeProviderRaw ├── SafeAreaListener (handles safe area insets updates) │ └── GlobalAnimationSettingsProvider (animation configuration) │ └── TextComponentProvider (text configuration) │ └── Your App ``` ## 最佳实践 ### 1. 单一 Provider 实例 始终在应用根使用**一个** `HeroUINativeProvider`,不要嵌套多个: ```tsx // ❌ Bad {/* Don't do this */} // ✅ Good ``` ### 2. 配置对象外置 将 `config` 定义在组件外,避免每次渲染重新创建: ```tsx // ❌ Bad function App() { return ( {/* ... */} ); } // ✅ Good const config: HeroUINativeConfig = { textProps: { maxFontSizeMultiplier: 1.5, }, }; function App() { return ( {/* ... */} ); } ``` ### 3. 文本与无障碍 配置文本属性时请兼顾无障碍,例如允许系统字体缩放但限制上限: ```tsx const config: HeroUINativeConfig = { textProps: { // Allow font scaling for accessibility allowFontScaling: true, // But limit maximum scale maxFontSizeMultiplier: 1.5, }, }; ``` ## TypeScript 支持 Provider 具备完整类型,可导入类型以获得更好的 IDE 体验: ```tsx import { HeroUINativeProvider, type HeroUINativeConfig } from 'heroui-native'; const config: HeroUINativeConfig = { // Full type safety and autocomplete textProps: { allowFontScaling: true, maxFontSizeMultiplier: 1.5, }, animation: 'disable-all', // Optional: disable all animations devInfo: { stylingPrinciples: true, // Optional: disable styling principles message }, // Toast configuration options: // - false or 'disabled': Disable toast provider // - ToastProviderProps object: Configure toast settings toast: { defaultProps: { variant: 'default', placement: 'top', }, insets: { top: 0, bottom: 6, left: 12, right: 12, }, }, }; ``` ## 相关链接 * [快速开始](/docs/native/getting-started/quick-start) — 基础搭建指南 * [主题](/docs/native/getting-started/theming) — 颜色与主题定制 * [样式](/docs/native/getting-started/styling) — 使用 Tailwind 编写样式 # 样式 **Category**: native **URL**: https://www.heroui.com/cn/docs/native/getting-started/styling **Source**: https://raw.githubusercontent.com/heroui-inc/heroui/refs/heads/v3/apps/docs/content/docs/cn/native/getting-started/(handbook)/styling.mdx > 使用 Tailwind 或 StyleSheet API 为 HeroUI Native 组件编写样式 HeroUI Native 提供灵活的样式方案:Tailwind CSS 工具类、StyleSheet API,以及用于动态样式的 render props。 ## 样式原则 HeroUI Native 以 `className` 作为主要样式入口,所有组件均可通过 `className` 使用 Tailwind 类。 **StyleSheet 优先级:** 同时传入 `style`(StyleSheet)与 `className` 时,`style` 优先级更高,可在需要时覆盖 Tailwind。 **动画样式:** 部分样式属性由 `react-native-reanimated` 驱动,与 StyleSheet 类似,其优先级也高于 `className`。要确认哪些属性受动画占用、无法仅靠 `className` 设置: * **在 IDE 中悬停 `className`** — TypeScript 定义会提示可用属性 * **查阅组件文档** — 组件页顶部通常有样式源码链接,其中会标注动画相关限制 **自定义动画样式:** 若某属性被动画占用,可在支持 `animation` 属性的组件上通过 `animation` 进行调整。 ## 基础样式 **使用 className:** 所有 HeroUI Native 组件都支持 `className`: ```tsx import { Button } from 'heroui-native'; ; ``` **使用 style:** 也可通过 `style` 传入内联样式: ```tsx import { Button } from 'heroui-native'; ; ``` ## Render Props 使用渲染函数读取组件状态并动态定制内容: ```tsx import { RadioGroup, Label, cn } from 'heroui-native'; {({ isSelected, isInvalid, isDisabled }) => ( <> {isSelected && } )} ; ``` ## 封装可复用组件 结合 [tailwind-variants](https://tailwind-variants.org/)(Tailwind 优先的变体 API)封装自定义组件: ```tsx import { Button } from 'heroui-native'; import type { ButtonRootProps } from 'heroui-native'; import { tv, type VariantProps } from 'tailwind-variants'; const customButtonVariants = tv({ base: 'font-semibold rounded-lg', variants: { intent: { primary: 'bg-blue-500', secondary: 'bg-gray-200', danger: 'bg-red-500', }, }, defaultVariants: { intent: 'primary', }, }); const customLabelVariants = tv({ base: '', variants: { intent: { primary: 'text-white', secondary: 'text-gray-800', danger: 'text-white', }, }, defaultVariants: { intent: 'primary', }, }); type CustomButtonVariants = VariantProps; interface CustomButtonProps extends Omit, CustomButtonVariants { className?: string; labelClassName?: string; } export function CustomButton({ intent, className, labelClassName, children, ...props }: CustomButtonProps) { return ( ); } ``` ## 使用组件自带的 classNames 每个 HeroUI Native 组件都会导出与内部一致的 `classNames` 工具对象,便于让自定义组件在视觉上与库内组件保持一致。 例如,让自定义 `Link` 看起来像 `Button`: ```tsx import { buttonClassNames, cn } from 'heroui-native'; import { Pressable, Text } from 'react-native'; interface LinkProps { href: string; variant?: 'primary' | 'secondary' | 'outline' | 'ghost'; size?: 'sm' | 'md' | 'lg'; children: React.ReactNode; className?: string; } export function Link({ href, variant = 'primary', size = 'md', children, className, }: LinkProps) { return ( { // Handle navigation }} > {children} ); } ``` **可用的 classNames 导出:** 每个组件都会导出对应的 `classNames` 对象,例如: * `buttonClassNames` — 包含 `root` 与 `label` 函数 * `cardClassNames` — 包含 `root`、`header`、`body`、`footer`、`label` 与 `description` 函数 * `chipClassNames` — 包含 `root` 与 `label` 函数 * 其他组件同理…… **典型用法:** ```tsx import { buttonClassNames } from 'heroui-native'; // Use with variant and size options const rootClasses = buttonClassNames.root({ variant: 'primary', size: 'md', className: 'custom-class', // Optional: merge with your own classes }); const labelClasses = buttonClassNames.label({ variant: 'primary', size: 'md', }); ``` `classNames` 函数的变体参数与对应组件一致,便于在自定义组件与 HeroUI 组件之间保持视觉一致。 ## 响应式设计 HeroUI Native 通过 [Uniwind](https://docs.uniwind.dev/breakpoints) 支持 Tailwind 的响应式断点前缀,如 `sm:`、`md:`、`lg:`、`xl:`,按屏幕宽度条件应用样式。 **移动优先:** 先写无前缀的小屏样式,再用断点为大屏增强。 ### 响应式排版与间距 ```tsx import { Button } from 'heroui-native'; import { View, Text } from 'react-native'; Responsive Heading ; ``` ### 响应式布局 ```tsx import { View, Text } from 'react-native'; {/* Mobile: 1 column, Tablet: 2 columns, Desktop: 3 columns */} Item 1 ; ``` **默认断点:** * `sm`:640px * `md`:768px * `lg`:1024px * `xl`:1280px * `2xl`:1536px 自定义断点与更多说明见 [Uniwind 断点文档](https://docs.uniwind.dev/breakpoints)。 ## 工具函数 HeroUI Native 提供一些样式相关的工具。 ### cn `cn` 用于合并 Tailwind 类并处理冲突,适合条件类或与 props 传入的类合并: ```tsx import { cn } from 'heroui-native'; import { View } from 'react-native'; function MyComponent({ className, isActive }) { return ( ); } ``` `cn` 基于 `tailwind-variants`,具备: * 自动合并 Tailwind 类(`twMerge: true`) * 自定义透明度分组等能力 * 合理的冲突解决(靠后的类覆盖靠前的类) **冲突示例:** ```tsx // 'bg-accent' overrides 'bg-background' cn('bg-background p-4', 'bg-accent'); // Result: 'p-4 bg-accent' ``` ### useThemeColor 从 CSS 变量读取主题色,支持单色或一次读取多种颜色(后者更高效)。 **单色:** ```tsx import { useThemeColor } from 'heroui-native'; function MyComponent() { const accentColor = useThemeColor('accent'); const dangerColor = useThemeColor('danger'); return ( Error message ); } ``` **多色(推荐在需要多个 token 时使用):** ```tsx import { useThemeColor } from 'heroui-native'; function MyComponent() { const [accentColor, backgroundColor, dangerColor] = useThemeColor([ 'accent', 'background', 'danger', ]); return ( Error message ); } ``` **类型签名:** ```tsx // Single color useThemeColor(themeColor: ThemeColor): string // Multiple colors (with type inference for tuples) useThemeColor( themeColor: T ): CreateStringTuple // Multiple colors (array) useThemeColor(themeColor: ThemeColor[]): string[] ``` 可用主题色包括:`background`、`foreground`、`surface`、`accent`、`default`、`success`、`warning`、`danger` 及其 hover、soft、foreground 等变体,以及 `muted`、`border`、`separator`、`field`、`overlay` 等语义色。 ## 下一步 * [动画](/docs/native/getting-started/animation) * [主题](/docs/native/getting-started/theming) * [颜色](/docs/native/getting-started/colors) # 主题 **Category**: native **URL**: https://www.heroui.com/cn/docs/native/getting-started/theming **Source**: https://raw.githubusercontent.com/heroui-inc/heroui/refs/heads/v3/apps/docs/content/docs/cn/native/getting-started/(handbook)/theming.mdx > 使用 CSS 变量与全局样式定制 HeroUI Native 设计系统 HeroUI Native 使用 CSS 变量实现主题化,可用标准 CSS 覆盖从颜色到组件样式的一切。 ## 工作原理 主题系统建立在 [Tailwind CSS v4](https://tailwindcss.com/docs/theme) 的主题能力之上,并通过 [Uniwind](https://uniwind.dev/) 接入 React Native。导入 `heroui-native/styles` 后,会使用 Tailwind 内置色板并映射到语义变量,自动在明暗主题间切换,并借助 CSS 层与 `@theme` 进行组织。 **命名约定:** * 无后缀的颜色一般用作背景(如 `--accent`) * 带 `-foreground` 后缀的用于该背景上的文字(如 `--accent-foreground`) ## 快速开始 **在组件中应用颜色:** ```tsx import { View, Text } from 'react-native'; Your app content ; ``` **切换主题:** 通过 [Uniwind](https://docs.uniwind.dev/theming/basics),HeroUI Native 自动支持深色模式;可跟随系统,也可手动切换明暗变体: ```tsx import { Uniwind, useUniwind } from 'uniwind'; import { Button } from 'heroui-native'; function ThemeToggle() { const { theme } = useUniwind(); return ( ); } ``` **覆盖颜色:** ```css /* global.css */ @layer theme { @variant light { /* Override any color variable */ --accent: oklch(0.65 0.25 270); /* Custom indigo accent */ --success: oklch(0.65 0.15 155); } @variant dark { --accent: oklch(0.65 0.25 270); --success: oklch(0.75 0.12 155); } } ``` > **说明:** 完整色板与可视化参考见 [颜色](/docs/native/getting-started/colors)。 **创建自定义主题:** 可借助 Uniwind 的变体系统定义多套主题。完整自定义主题文档见 [Uniwind 自定义主题指南](https://docs.uniwind.dev/theming/custom-themes)。 **重要:** 所有主题必须定义**相同**的变量集合。必填变量清单见 [默认主题](/docs/native/getting-started/colors#default-theme)。 ```css /* global.css */ @layer theme { :root { @variant ocean-light { /* Base Colors */ --background: oklch(0.95 0.02 230); --foreground: oklch(0.25 0.04 230); /* Surface: Used for non-overlay components (cards, accordions, disclosure groups) */ --surface: oklch(0.98 0.01 230); --surface-foreground: oklch(0.3 0.045 230); --surface-secondary: oklch(0.96 0.012 230); --surface-secondary-foreground: oklch(0.3 0.045 230); --surface-tertiary: oklch(0.94 0.015 230); --surface-tertiary-foreground: oklch(0.3 0.045 230); /* Overlay: Used for floating/overlay components (dialogs, popovers, modals, menus) */ --overlay: oklch(0.998 0.003 230); --overlay-foreground: oklch(0.3 0.045 230); --backdrop: oklch(0% 0 0 / 20%); --muted: oklch(0.55 0.035 230); --default: oklch(0.94 0.018 230); --default-foreground: oklch(0.4 0.05 230); /* Accent */ --accent: oklch(0.6 0.2 230); --accent-foreground: oklch(0.98 0.005 230); /* Form Field Defaults - Colors */ --field-background: oklch(0.98 0.01 230); --field-foreground: oklch(0.25 0.04 230); --field-placeholder: var(--muted); --field-border: transparent; /* Status Colors */ --success: oklch(0.72 0.14 165); --success-foreground: oklch(0.25 0.08 165); --warning: oklch(0.78 0.12 85); --warning-foreground: oklch(0.3 0.08 85); --danger: oklch(0.68 0.18 15); --danger-foreground: oklch(0.98 0.005 15); /* Component Colors */ --segment: oklch(0.98 0.01 230); --segment-foreground: oklch(0.25 0.04 230); /* Misc Colors */ --border: oklch(0 0 0 / 0%); --separator: oklch(0.91 0.015 230); --focus: var(--accent); --link: oklch(0.62 0.17 230); /* Shadows */ --surface-shadow: 0 2px 4px 0 rgba(0, 0, 0, 0.04), 0 1px 2px 0 rgba(0, 0, 0, 0.06), 0 0 1px 0 rgba(0, 0, 0, 0.06); --overlay-shadow: 0 2px 8px 0 rgba(0, 0, 0, 0.02), 0 -6px 12px 0 rgba(0, 0, 0, 0.01), 0 14px 28px 0 rgba(0, 0, 0, 0.03); --field-shadow: 0 2px 4px 0 rgba(0, 0, 0, 0.04), 0 1px 2px 0 rgba(0, 0, 0, 0.06), 0 0 1px 0 rgba(0, 0, 0, 0.06); } @variant ocean-dark { /* Base Colors */ --background: oklch(0.15 0.04 230); --foreground: oklch(0.94 0.01 230); /* Surface: Used for non-overlay components (cards, accordions, disclosure groups) */ --surface: oklch(0.2 0.048 230); --surface-foreground: oklch(0.9 0.015 230); --surface-secondary: oklch(0.24 0.046 230); --surface-secondary-foreground: oklch(0.9 0.015 230); --surface-tertiary: oklch(0.27 0.044 230); --surface-tertiary-foreground: oklch(0.9 0.015 230); /* Overlay: Used for floating/overlay components (dialogs, popovers, modals, menus) */ --overlay: oklch(0.23 0.045 230); --overlay-foreground: oklch(0.9 0.015 230); --backdrop: oklch(0% 0 0 / 20%); --muted: oklch(0.5 0.04 230); --default: oklch(0.25 0.05 230); --default-foreground: oklch(0.88 0.018 230); /* Accent */ --accent: oklch(0.72 0.21 230); --accent-foreground: oklch(0.15 0.04 230); /* Form Field Defaults - Colors */ --field-background: var(--default); --field-foreground: var(--foreground); --field-placeholder: var(--muted); --field-border: transparent; /* Status Colors */ --success: oklch(0.68 0.16 165); --success-foreground: oklch(0.95 0.008 165); --warning: oklch(0.75 0.14 90); --warning-foreground: oklch(0.2 0.04 90); --danger: oklch(0.65 0.2 20); --danger-foreground: oklch(0.95 0.008 20); /* Component Colors */ --segment: oklch(0.22 0.046 230); --segment-foreground: oklch(0.9 0.015 230); /* Misc Colors */ --border: oklch(0 0 0 / 0%); --separator: oklch(0.28 0.045 230); --focus: var(--accent); --link: oklch(0.75 0.18 230); /* Shadows */ --surface-shadow: 0 0 0 0 transparent inset; /* No shadow on dark mode */ --overlay-shadow: 0 0 1px 0 rgba(255, 255, 255, 0.3) inset; --field-shadow: 0 0 0 0 transparent inset; /* Transparent shadow to allow ring utilities to work */ } } } ``` **重要:** 添加自定义主题后,必须在 Metro 配置中注册: ```js // metro.config.js const { withUniwindConfig } = require('uniwind/metro'); const { wrapWithReanimatedMetroConfig, } = require('react-native-reanimated/metro-config'); const config = { // ... your existing config }; module.exports = withUniwindConfig(wrapWithReanimatedMetroConfig(config), { cssEntryFile: './global.css', dtsFile: './src/uniwind.d.ts', extraThemes: ['ocean-light', 'ocean-dark'], }); ``` 在应用中切换主题: ```tsx import { Uniwind } from 'uniwind'; import { Button } from 'heroui-native'; function App() { return ( ); } ``` ## 添加自定义颜色 在主题中加入自定义语义色: ```css @layer theme { @variant light { --info: oklch(0.6 0.15 210); --info-foreground: oklch(0.98 0 0); } @variant dark { --info: oklch(0.7 0.12 210); --info-foreground: oklch(0.15 0 0); } } /* 让颜色可被 Tailwind 使用 */ @theme inline { --color-info: var(--info); --color-info-foreground: var(--info-foreground); } ``` 在组件中使用: ```tsx import { View, Text } from 'react-native'; Info message ; ``` ## 自定义字体 要在应用中使用自定义字体,需要先加载字体,再覆盖字体相关的 CSS 变量。 ### 1. 在应用中加载字体 先加载字体(例如使用 Expo 的 `useFonts`): ```tsx import { useFonts } from 'expo-font'; import { HeroUINativeProvider } from 'heroui-native'; import { YourFont_400Regular, YourFont_500Medium, YourFont_600SemiBold, } from '@expo-google-fonts/your-font'; export default function App() { const [fontsLoaded] = useFonts({ YourFont_400Regular, YourFont_500Medium, YourFont_600SemiBold, }); if (!fontsLoaded) { return null; // Or return a loading screen } return {/* Your app content */}; } ``` ### 2. 配置字体 CSS 变量 加载完成后,在 `global.css` 中覆盖字体变量: ```css @theme { --font-normal: 'YourFont-400Regular'; --font-medium: 'YourFont-500Medium'; --font-semibold: 'YourFont-600SemiBold'; } ``` **说明:** CSS 变量中的字体名应与已加载字体的 PostScript 名称一致。请查阅字体包文档,或直接使用 `useFonts` 中出现的名称。 所有 HeroUI Native 组件会自动使用这些字体变量,以保持排版一致。 ## 变量参考 HeroUI 定义三类变量: 1. **基础变量** — 如 `--white`、`--black` 等不随主题切换的值 2. **主题变量** — 随明暗主题切换的颜色 3. **计算变量** — 自动生成的按压态(hover)与尺寸变体等 完整参考:[颜色文档](/docs/native/getting-started/colors)、[默认主题变量](https://github.com/heroui-inc/heroui-native/blob/main/src/styles/variables.css)、[共享主题工具](https://github.com/heroui-inc/heroui-native/blob/main/src/styles/theme.css) **计算变量(Tailwind):** 我们通过 Tailwind 的 `@theme` 指令自动生成按压态与圆角等计算变量,定义见 [theme.css](https://github.com/heroui-inc/heroui-native/blob/main/src/styles/theme.css): ```css @theme inline static { --color-background: var(--background); --color-foreground: var(--foreground); --color-surface: var(--surface); --color-surface-foreground: var(--surface-foreground); --color-surface-hover: color-mix(in oklab, var(--surface) 92%, var(--surface-foreground) 8%); --color-surface-secondary: var(--surface-secondary); --color-surface-secondary-foreground: var(--surface-secondary-foreground); --color-surface-tertiary: var(--surface-tertiary); --color-surface-tertiary-foreground: var(--surface-tertiary-foreground); --color-overlay: var(--overlay); --color-overlay-foreground: var(--overlay-foreground); --color-backdrop: var(--backdrop); --color-muted: var(--muted); --color-accent: var(--accent); --color-accent-foreground: var(--accent-foreground); --color-segment: var(--segment); --color-segment-foreground: var(--segment-foreground); --color-border: var(--border); --color-separator: var(--separator); --color-focus: var(--focus); --color-link: var(--link); --color-default: var(--default); --color-default-foreground: var(--default-foreground); --color-success: var(--success); --color-success-foreground: var(--success-foreground); --color-warning: var(--warning); --color-warning-foreground: var(--warning-foreground); --color-danger: var(--danger); --color-danger-foreground: var(--danger-foreground); /* Form Field Tokens */ --color-field: var(--field-background, var(--default)); --color-field-foreground: var(--field-foreground, var(--foreground)); --color-field-placeholder: var(--field-placeholder, var(--muted)); --color-field-border: var(--field-border, var(--border)); --radius-field: var(--field-radius, var(--radius-xl)); --border-width-field: var(--field-border-width, var(--border-width)); --shadow-surface: var(--surface-shadow); --shadow-overlay: var(--overlay-shadow); --shadow-field: var(--field-shadow); /* Calculated Variables */ /* Colors */ /* --- background shades --- */ --color-background-secondary: color-mix(in oklab, var(--background) 96%, var(--foreground) 4%); --color-background-tertiary: color-mix(in oklab, var(--background) 92%, var(--foreground) 8%); --color-background-inverse: var(--foreground); /* ------------------------- */ --color-default-hover: color-mix(in oklab, var(--default) 96%, var(--default-foreground) 4%); --color-accent-hover: color-mix(in oklab, var(--accent) 90%, var(--accent-foreground) 10%); --color-success-hover: color-mix(in oklab, var(--success) 90%, var(--success-foreground) 10%); --color-warning-hover: color-mix(in oklab, var(--warning) 90%, var(--warning-foreground) 10%); --color-danger-hover: color-mix(in oklab, var(--danger) 90%, var(--danger-foreground) 10%); /* Form Field Colors */ --color-field-hover: color-mix(in oklab, var(--field-background, var(--default)) 90%, var(--field-foreground, var(--foreground)) 2%); --color-field-focus: var(--field-background, var(--default)); --color-field-border-hover: color-mix(in oklab, var(--field-border, var(--border)) 88%, var(--field-foreground, var(--foreground)) 10%); --color-field-border-focus: color-mix(in oklab, var(--field-border, var(--border)) 74%, var(--field-foreground, var(--foreground)) 22%); /* Soft Colors */ --color-accent-soft: color-mix(in oklab, var(--accent) 15%, transparent); --color-accent-soft-foreground: var(--accent); --color-accent-soft-hover: color-mix(in oklab, var(--accent) 20%, transparent); --color-danger-soft: color-mix(in oklab, var(--danger) 15%, transparent); --color-danger-soft-foreground: var(--danger); --color-danger-soft-hover: color-mix(in oklab, var(--danger) 20%, transparent); --color-warning-soft: color-mix(in oklab, var(--warning) 15%, transparent); --color-warning-soft-foreground: var(--warning); --color-warning-soft-hover: color-mix(in oklab, var(--warning) 20%, transparent); --color-success-soft: color-mix(in oklab, var(--success) 15%, transparent); --color-success-soft-foreground: var(--success); --color-success-soft-hover: color-mix(in oklab, var(--success) 20%, transparent); /* Separator Colors - Levels */ --color-separator-secondary: color-mix(in oklab, var(--surface) 85%, var(--surface-foreground) 15%); --color-separator-tertiary: color-mix(in oklab, var(--surface) 81%, var(--surface-foreground) 19%); /* Border Colors - Levels (progressive contrast: default → secondary → tertiary) */ /* Light mode: lighter → darker | Dark mode: darker → lighter */ --color-border-secondary: color-mix(in oklab, var(--surface) 78%, var(--surface-foreground) 22%); --color-border-tertiary: color-mix(in oklab, var(--surface) 66%, var(--surface-foreground) 34%); /* Radius and default sizes - defaults can change by just changing the --radius */ --radius-xs: calc(var(--radius) * 0.25); /* 0.125rem (2px) */ --radius-sm: calc(var(--radius) * 0.5); /* 0.25rem (4px) */ --radius-md: calc(var(--radius) * 0.75); /* 0.375rem (6px) */ --radius-lg: calc(var(--radius) * 1); /* 0.5rem (8px) */ --radius-xl: calc(var(--radius) * 1.5); /* 0.75rem (12px) */ --radius-2xl: calc(var(--radius) * 2); /* 1rem (16px) */ --radius-3xl: calc(var(--radius) * 3); /* 1.5rem (24px) */ --radius-4xl: calc(var(--radius) * 4); /* 2rem (32px) */ } ``` 表单控件依赖 `--field-*` 变量及其计算出的 hover/focus 变体。在主题中调整它们即可重塑输入框、复选框、单选与 OTP 等,而不会影响按钮、卡片等 Surface 组件的观感。 ## 鲜亮配色 默认情况下,HeroUI Native 使用可读性更好的柔和前景色,即将语义色与前景色按比例混合,以在 soft 背景上获得更佳对比度。如果你偏好饱和度更高、更鲜亮的柔和前景色,可以在引入基础样式之后,额外导入可选的 `heroui-native/styles/vibrant` 样式: ```css /* global.css */ @import "heroui-native/styles"; @import "heroui-native/styles/vibrant"; /* [!code highlight] */ ``` 这会将所有 `*-soft-foreground` 变量(accent、success、warning、danger)切换为「语义色 92% + 前景色 8%」的混合配方——更贴近原始色调,但仍带有轻微的对比度增强。[Alert](/docs/native/components/alert)、[Avatar](/docs/native/components/avatar)、[Button](/docs/native/components/button)、[Chip](/docs/native/components/chip)、[Toast](/docs/native/components/toast) 等组件会自动在其 soft 变体上使用新的柔和前景色——无需修改任何组件属性。 | 模式 | 可读性优先(默认) | 鲜亮 | | ------- | -------------------------------------------- | ------------------------------------- | | Soft 前景 | `color-mix(color 70-80%, foreground 30-40%)` | `color-mix(color 92%, foreground 8%)` | 鲜亮配色优先考虑视觉饱和度而非对比度。对某些颜色组合(尤其是更浅的强调色),它可能不满足 WCAG 无障碍准则。 可选的鲜亮配色自 [v1.0.4](/docs/native/releases/v1-0-4) 起提供。 ## 相关资源 * [颜色](/docs/native/getting-started/colors) * [样式指南](/docs/native/getting-started/styling) * [Tailwind CSS v4 主题](https://tailwindcss.com/docs/theme) * [OKLCH 调色工具](https://oklch.com) # 设计原则 **Category**: native **URL**: https://www.heroui.com/cn/docs/native/getting-started/design-principles **Source**: https://raw.githubusercontent.com/heroui-inc/heroui/refs/heads/v3/apps/docs/content/docs/cn/native/getting-started/(overview)/design-principles.mdx > 指导 HeroUI Native 设计与开发的核心理念 HeroUI Native 遵循 9 条核心原则,强调清晰、无障碍、可定制与开发者体验。 ## 核心原则 ### 1. 语义意图优先于视觉样式 使用语义化命名(primary、secondary、tertiary)而非纯视觉描述(solid、flat、bordered)。受 [Uber Base 设计系统](https://base.uber.com/6d2425e9f/p/756216-button) 启发,变体形成清晰层级: ```tsx // ✅ 语义变体传达层级 ``` | 变体 | 用途 | 使用建议 | | ------------- | --------- | ----------- | | **Primary** | 推进流程的主操作 | 同一上下文通常 1 个 | | **Secondary** | 备选操作 | 可多个 | | **Tertiary** | 取消、跳过等弱操作 | 谨慎使用 | | **Danger** | 破坏性操作 | 按需使用 | ### 2. 无障碍作为基础 遵循移动端无障碍最佳实践,内置合理的触控可达性、焦点管理与读屏支持。所有组件提供适当的无障碍标签与语义结构,以支持 VoiceOver(iOS)与 TalkBack(Android)。 ```tsx import { Tabs } from 'heroui-native'; Profile Security Content Content ``` ### 3. 组合优于配置 复合组件可按需重排、定制或省略子部件,通过点记法精确拼装。 ```tsx // 组合子部件得到所需结构 import { Accordion } from 'heroui-native'; Question Text Answer content ``` ### 4. 渐进式披露 从简单开始,仅在需要时增加复杂度。组件在最少配置下即可工作,并随需求增长而扩展。 ```tsx import { Button, Spinner } from 'heroui-native'; import { Feather } from '@expo/vector-icons'; // Level 1: Minimal // Level 2: Enhanced // Level 3: Advanced ``` ### 5. 可预测的行为 跨组件保持一致:`sm` / `md` / `lg` 尺寸、变体体系与 `className` 支持。API 一致,行为一致。 ```tsx import { Button, Chip, Avatar } from 'heroui-native'; // All components follow the same patterns Success JD ``` ### 6. 类型安全优先 完整的 TypeScript 支持:智能提示、自动补全与编译期检查。可为自定义组件扩展类型。 ```tsx import type { ButtonRootProps } from 'heroui-native'; // Type-safe props and event handlers // Extend types for custom components interface CustomButtonProps extends Omit { intent: 'save' | 'cancel' | 'delete'; } ``` ### 7. 卓越的开发者体验 清晰的 API、可读的错误信息、智能提示,以及对 AI 友好的 Markdown 文档。 ### 8. 完整可定制 默认即美观;也可通过 CSS 变量与 [Uniwind 主题系统](https://docs.uniwind.dev/theming/basics) 整体换肤。每个插槽都可定制。 ```css /* Custom colors using Uniwind's theme layer */ @layer theme { @variant light { --accent: oklch(0.65 0.25 270); /* Custom indigo accent */ --background: oklch(0.98 0 0); /* Custom background */ } @variant dark { --accent: oklch(0.65 0.25 270); --background: oklch(0.15 0 0); } } /* Radius customization */ @theme { --radius: 0.75rem; /* Increase for rounder components */ } ``` ### 9. 开放与可扩展 可包装、扩展与定制组件以匹配产品需求;也可用 `className` 应用自定义样式。 ```tsx import { Button } from 'heroui-native'; import type { ButtonRootProps } from 'heroui-native'; // Custom wrapper component interface CTAButtonProps extends Omit { intent?: 'primary-cta' | 'secondary-cta' | 'minimal'; } const CTAButton = ({ intent = 'primary-cta', children, ...props }: CTAButtonProps) => { const variantMap = { 'primary-cta': 'primary', 'secondary-cta': 'secondary', 'minimal': 'ghost' } as const; return ( ); }; // Usage Get Started Learn More ``` **结合 tailwind-variants 扩展:** ```tsx import { Button } from 'heroui-native'; import { tv } from 'tailwind-variants'; // Extend button styles with custom variants const myButtonVariants = tv({ base: 'px-4 py-2 rounded-lg', variants: { variant: { 'primary-cta': 'bg-accent px-8 py-4 shadow-lg', 'secondary-cta': 'border-2 border-accent px-6 py-3', } }, defaultVariants: { variant: 'primary-cta', } }); // Label variants for text colors (must be applied to Button.Label) const myLabelVariants = tv({ base: '', variants: { variant: { 'primary-cta': 'text-accent-foreground', 'secondary-cta': 'text-accent', } }, defaultVariants: { variant: 'primary-cta', } }); // Use the custom variants function CustomButton({ variant, className, labelClassName, children, ...props }) { return ( ); } // Usage Get Started Learn More ``` # 快速开始 **Category**: native **URL**: https://www.heroui.com/cn/docs/native/getting-started/quick-start **Source**: https://raw.githubusercontent.com/heroui-inc/heroui/refs/heads/v3/apps/docs/content/docs/cn/native/getting-started/(overview)/quick-start.mdx > 几分钟内上手 HeroUI Native 请根据项目情况选择适合的方案: * **方案 1** —— 通过我们的 CLI 一键创建预先配置好的新项目,无需手动设置。 * **方案 2** —— 将 HeroUI Native 添加到已有的 React Native 或 Expo 项目。 ## 方案 1:创建新项目 最快捷的启动方式。CLI 会生成一个 Expo 项目,内置 HeroUI Native、所有必需的 peer 依赖、Uniwind / Tailwind CSS、全局样式以及已配置好的 `HeroUINativeProvider`,让你可以直接进入开发。 ```bash npx create-heroui-native-app@latest ``` ```bash pnpm create heroui-native-app@latest ``` ```bash yarn create heroui-native-app ``` ```bash bun create heroui-native-app@latest ``` 按照交互提示完成配置,然后启动开发服务器: ```bash cd my-app npm run start ``` 到此即可开始开发。可直接跳到[使用第一个组件](#use-your-first-component),或[浏览组件](/docs/native/components)。 生成的项目自带 Expo + TypeScript、预配置的 Uniwind + Tailwind CSS、含必要导入的 `global.css`,并已在应用入口包裹 `GestureHandlerRootView` 与 `HeroUINativeProvider`。 ## 方案 2:添加到已有项目 如果你已经有一个 React Native 或 Expo 应用,请按以下步骤手动安装与配置 HeroUI Native。 **更喜欢让 AI 助手代劳?** 在编辑器中安装 [HeroUI Native MCP 服务器](/docs/native/getting-started/mcp-server),将上方提示词粘贴给你的 AI 助手 —— 它会分析你的项目并完成整套配置。 ### 1. 安装 HeroUI Native ```bash npm install heroui-native ``` ```bash pnpm add heroui-native ``` ```bash yarn add heroui-native ``` ```bash bun add heroui-native ``` ### 2. 安装必需的 peer 依赖 ```bash npm install react-native-reanimated@^4.1.1 react-native-gesture-handler@^2.28.0 react-native-worklets@^0.5.1 react-native-safe-area-context@^5.6.0 react-native-svg@^15.12.1 tailwind-variants@^3.2.2 tailwind-merge@^3.4.0 ``` ```bash pnpm add react-native-reanimated@^4.1.1 react-native-gesture-handler@^2.28.0 react-native-worklets@^0.5.1 react-native-safe-area-context@^5.6.0 react-native-svg@^15.12.1 tailwind-variants@^3.2.2 tailwind-merge@^3.4.0 ``` ```bash yarn add react-native-reanimated@^4.1.1 react-native-gesture-handler@^2.28.0 react-native-worklets@^0.5.1 react-native-safe-area-context@^5.6.0 react-native-svg@^15.12.1 tailwind-variants@^3.2.2 tailwind-merge@^3.4.0 ``` ```bash bun add react-native-reanimated@^4.1.1 react-native-gesture-handler@^2.28.0 react-native-worklets@^0.5.1 react-native-safe-area-context@^5.6.0 react-native-svg@^15.12.1 tailwind-variants@^3.2.2 tailwind-merge@^3.4.0 ``` 建议使用上文列出的确切版本,以避免兼容性问题。版本不一致可能导致难以预期的缺陷。 ### 3. 可选依赖 仅在用到对应组件或能力时需要安装: | Package | Version | 用途 | | ---------------------- | --------- | ---------------------------------------------------------------------- | | `react-native-screens` | `^4.16.0` | BottomSheet、Dialog、Menu、Popover、Select、Toast | | `@gorhom/bottom-sheet` | `^5.2.9` | BottomSheet;Menu / Popover / Select 使用 `presentation="bottom-sheet"` 时 | ### 4. 配置 Uniwind 请按 [Uniwind 安装指南](https://docs.uniwind.dev/quickstart) 为 React Native 接入 Tailwind CSS。 若从 NativeWind 迁移,参见 [迁移指南](https://docs.uniwind.dev/migration-from-nativewind)。 ### 5. 配置 global.css 在 `global.css` 中加入以下导入: ```css @import 'tailwindcss'; @import 'uniwind'; @import 'heroui-native/styles'; /* Path to the heroui-native lib inside node_modules relative to global.css */ /* Examples: * - If global.css is at project root: ./node_modules/heroui-native/lib * - If global.css is in app/: ../node_modules/heroui-native/lib * - If global.css is in src/styles/: ../../node_modules/heroui-native/lib */ @source './node_modules/heroui-native/lib'; ``` ### 6. 使用 Provider 包裹应用 使用 `HeroUINativeProvider` 包裹应用,并务必外层再包一层 `GestureHandlerRootView`: ```tsx import { HeroUINativeProvider } from 'heroui-native'; import { GestureHandlerRootView } from 'react-native-gesture-handler'; export default function App() { return ( {/* Your app content */} ); } ``` > **说明:** 关于文本属性、动画、Toast 等高级配置,请参阅 [Provider 文档](/docs/native/getting-started/provider)。 ## 使用第一个组件 ```tsx import { Button } from 'heroui-native'; import { View } from 'react-native'; export default function MyComponent() { return ( ); } ``` ## 通过细粒度导出减小包体 若希望减小包体、仅引入用到的组件,可使用细粒度导出: ```tsx // Granular imports - use when you need only a few components import { HeroUINativeProvider } from "heroui-native/provider"; import { Button } from "heroui-native/button"; import { Card } from "heroui-native/card"; // General import - imports the whole library, use when you're using many components import { Button, Card } from "heroui-native"; ``` 细粒度导入适合只用少量组件的场景,有助于控制包体。从 `heroui-native` 整体导入会包含完整库,适合在应用中广泛使用多组件时采用。 **可用的细粒度入口:** * `heroui-native/provider` — Provider * `heroui-native/provider-raw` — 轻量 Provider(最小依赖起点) * `heroui-native/[component-name]` — 单个组件 * `heroui-native/portal` — Portal 工具 * `heroui-native/toast` — Toast Provider 与工具 * `heroui-native/utils` — 工具函数 * `heroui-native/hooks` — 自定义 Hooks **重要:** 为控制包体,请**始终**坚持使用细粒度导入策略。只要存在一处从 `heroui-native` 的整体导入,就可能使上述优化失效。 > **提示:** 若需要更强控制,可使用 [`HeroUINativeProviderRaw`](/docs/native/getting-started/provider#raw-provider) — 轻量 Provider,不包含 `ToastProvider` 与 `PortalHost`。 ## 接下来 * [HeroUI Native Provider](/docs/native/getting-started/provider) * [样式指南](/docs/native/getting-started/styling) * [主题文档](/docs/native/getting-started/theming) ## 在 Web(Expo)上运行 HeroUI Native **目前不建议用于 Web**。我们优先聚焦 iOS 与 Android。Web 开发请使用 [HeroUI React](/docs/react/getting-started/quick-start)。 # Agent Skills **Category**: native **URL**: https://www.heroui.com/cn/docs/native/getting-started/agent-skills **Source**: https://raw.githubusercontent.com/heroui-inc/heroui/refs/heads/v3/apps/docs/content/docs/cn/native/getting-started/(ui-for-agents)/agent-skills.mdx > 让 AI 助手使用 HeroUI Native 组件构建移动端界面 HeroUI Native Skills 为 AI 助手提供组件、模式与 React Native 最佳实践等系统化知识。 ### 安装 ```bash curl -fsSL https://heroui.com/install | bash -s heroui-native ``` 或使用 skills 包: ```bash npx skills add heroui-inc/heroui ``` 支持 Claude Code、Cursor、OpenCode 等。 ### 用法 Skills 会被 AI **自动发现**,也可通过 `/heroui-native` 显式调用。 你可以让助手: * 使用 HeroUI Native 搭建移动组件 * 用 HeroUI Native 创建页面 * 定制主题与样式 * 查阅组件文档 更复杂的场景可配合 [MCP 服务器](/docs/native/getting-started/mcp-server),以实时访问组件文档与源码。 ### 包含内容 * HeroUI Native 安装指南 * 全部组件的 props、示例与用法模式 * 基于 Uniwind 的主题与样式指南 * 设计原则与组合模式 ### 目录结构 ``` skills/heroui-native/ ├── SKILL.md # 主说明 ├── LICENSE.txt # Apache License 2.0 └── scripts/ # 工具脚本 ├── list_components.mjs ├── get_component_docs.mjs ├── get_theme.mjs └── get_docs.mjs ``` ### 相关文档 * [Agent Skills 规范](https://agentskills.io/home) * [Claude Agent Skills](https://platform.claude.com/docs/en/agents-and-tools/agent-skills/overview) * [Cursor Skills](https://cursor.com/docs/context/skills) * [OpenCode Skills](https://opencode.ai/docs/skills) # AGENTS.md **Category**: native **URL**: https://www.heroui.com/cn/docs/native/getting-started/agents-md **Source**: https://raw.githubusercontent.com/heroui-inc/heroui/refs/heads/v3/apps/docs/content/docs/cn/native/getting-started/(ui-for-agents)/agents-md.mdx > 将 HeroUI Native 文档下载到项目中,供 AI 编程助手引用 可将 HeroUI Native 文档直接下载到项目内,供 AI 助手本地引用。 **说明:** `agents-md` 命令专用于 **HeroUI React v3** 与 **HeroUI Native**。其他 CLI 命令(如 `add`、`init`、`upgrade` 等)目前仍面向 HeroUI v2。 ### 用法 ```bash npx heroui-cli@latest agents-md --native ``` 指定输出文件: ```bash npx heroui-cli@latest agents-md --native --output AGENTS.md ``` ### 作用 * 将最新 HeroUI Native 文档下载到 `.heroui-docs/native/` * 在 `AGENTS.md` 或 `CLAUDE.md` 中生成索引 * 自动将 `.heroui-docs/` 加入 `.gitignore` ### 选项 * `--native` — 仅下载 Native 文档 * `--output ` — 输出文件(如 `AGENTS.md` 或 `AGENTS.md CLAUDE.md`) * `--ssh` — 使用 SSH 进行 git clone ### 要求 * Tailwind CSS >= v4(通过 Uniwind) ### 相关文档 * [AGENTS.md](https://agents.md/) — AGENTS.md 格式说明 * [CLAUDE.md](https://code.claude.com/docs/en/best-practices#write-an-effective-claude-md) — Claude 侧的等价物 * [AGENTS.md vs Skills](https://vercel.com/blog/agents-md-outperforms-skills-in-our-agent-evals) — 评测相关讨论 # LLMs.txt **Category**: native **URL**: https://www.heroui.com/cn/docs/native/getting-started/llms-txt **Source**: https://raw.githubusercontent.com/heroui-inc/heroui/refs/heads/v3/apps/docs/content/docs/cn/native/getting-started/(ui-for-agents)/llms-txt.mdx > 让 Claude、Cursor、Windsurf 等 AI 助手理解 HeroUI Native 文档 我们提供 [LLMs.txt](https://llmstxt.org/) 文件,便于 AI 编程助手读取 HeroUI Native 文档。 ## 可用文件 **核心文档:** * [/native/llms.txt](/native/llms.txt) — Native 文档快速索引 * [/native/llms-full.txt](/native/llms-full.txt) — HeroUI Native 完整文档 **上下文窗口较小时:** * [/native/llms-components.txt](/native/llms-components.txt) — 仅组件文档 * [/native/llms-patterns.txt](/native/llms-patterns.txt) — 常见模式与配方 **全平台:** * [/llms.txt](/llms.txt) — 快速索引(React + Native) * [/llms-full.txt](/llms-full.txt) — 完整文档(React + Native) * [/llms-components.txt](/llms-components.txt) — 全部组件文档 * [/llms-patterns.txt](/llms-patterns.txt) — 全部模式与配方 ## 接入方式 **Claude Code:** 让 Claude 引用文档,例如: ``` Use HeroUI Native documentation from https://heroui.com/native/llms.txt ``` 或在项目的 `.claude` 中配置以自动加载。 **Cursor:** 使用 `@Docs`: ``` @Docs https://heroui.com/native/llms-full.txt ``` [了解更多](https://docs.cursor.com/context/@-symbols/@-docs) **Windsurf:** 写入 `.windsurfrules`: ``` #docs https://heroui.com/native/llms-full.txt ``` [了解更多](https://docs.codeium.com/windsurf/memories#memories-and-rules) **其他 AI 工具:** 多数助手支持通过 URL 引用文档,直接提供: ``` https://heroui.com/native/llms.txt ``` **仅组件文档:** ``` https://heroui.com/native/llms-components.txt ``` **模式与最佳实践:** ``` https://heroui.com/native/llms-patterns.txt ``` ## 参与改进 若 AI 生成代码有问题,欢迎在 [GitHub](https://github.com/heroui-inc/heroui) 上协助改进 LLMs.txt 文件。 # MCP 服务器 **Category**: native **URL**: https://www.heroui.com/cn/docs/native/getting-started/mcp-server **Source**: https://raw.githubusercontent.com/heroui-inc/heroui/refs/heads/v3/apps/docs/content/docs/cn/native/getting-started/(ui-for-agents)/mcp-server.mdx > 在 AI 助手中直接访问 HeroUI Native 文档 HeroUI MCP 服务器让 AI 助手直接读取 HeroUI Native 组件文档,便于在 AI 驱动的开发流程中使用 HeroUI。 当前 MCP 服务器支持 **heroui-native** 与 [stdio 传输](https://modelcontextprotocol.io/specification/2025-06-18/basic/transports#stdio)。npm 包名为 `@heroui/native-mcp`。源码见 [GitHub](https://github.com/heroui-inc/heroui-mcp)。 随着 HeroUI Native 组件增加,MCP 中的可用内容也会同步扩展。 ## 快速配置 **Cursor:**
在 Cursor 中安装
或手动添加到 **Cursor 设置** → **Tools** → **MCP Servers**: ```json title=".cursor/mcp.json" { "mcpServers": { "heroui-native": { "command": "npx", "args": ["-y", "@heroui/native-mcp@latest"] } } } ``` 也可将以下内容加入 `~/.cursor/mcp.json`。详见 [Cursor 文档](https://cursor.com/docs/context/mcp)。 **Claude Code:** 在终端执行: ```bash claude mcp add heroui-native -- npx -y @heroui/native-mcp@latest ``` 或手动写入项目的 `.mcp.json`: ```json title=".mcp.json" { "mcpServers": { "heroui-native": { "command": "npx", "args": ["-y", "@heroui/native-mcp@latest"] } } } ``` 添加配置后重启 Claude Code,运行 `/mcp` 查看列表;若显示 **Connected** 即可使用。 更多说明见 [Claude Code MCP 文档](https://docs.claude.com/en/docs/claude-code/mcp)。 **Windsurf:** 在项目 `.windsurf/mcp.json` 中加入: ```json title=".windsurf/mcp.json" { "mcpServers": { "heroui-native": { "command": "npx", "args": ["-y", "@heroui/native-mcp@latest"] } } } ``` 保存后重启 Windsurf 以生效。 详见 [Windsurf MCP 文档](https://docs.windsurf.com/windsurf/cascade/mcp)。 **Zed:** 在 `settings.json` 中配置(命令面板 `zed: open settings` 或 `Cmd-,` / `Ctrl-,`): ```json title="settings.json" { "context_servers": { "heroui-native": { "command": "npx", "args": ["-y", "@heroui/native-mcp@latest"], "env": {} } } } ``` 重启 Zed 后,在 Agent 面板设置中确认 heroui-native 旁指示点为绿色,提示为「Server is active」。 详见 [Zed MCP 文档](https://zed.dev/docs/ai/mcp)。 **VS Code:** 若配合 GitHub Copilot 使用 MCP,在项目 `.vscode/mcp.json` 中添加: ```json title=".vscode/mcp.json" { "servers": { "heroui-native": { "type": "stdio", "command": "npx", "args": ["-y", "@heroui/native-mcp@latest"] } } } ``` 打开 `.vscode/mcp.json`,在 heroui-native 旁点击 **Start**。 详见 [VS Code MCP 文档](https://code.visualstudio.com/docs/copilot/customization/mcp-servers)。 **Codex:** 写入 `~/.codex/config.toml` 或项目内 `.codex/config.toml`: ```toml title="config.toml" [mcp_servers.heroui-native] command = "npx" args = ["-y", "@heroui/native-mcp@latest"] ``` 重启 Codex,在 TUI 中运行 `/mcp` 校验服务器已激活。 详见 [Codex MCP 文档](https://developers.openai.com/codex/mcp)。 **OpenCode:** 在项目 `opencode.json` 中添加: ```json title="opencode.json" { "$schema": "https://opencode.ai/config.json", "mcp": { "heroui-native": { "type": "local", "command": ["npx", "-y", "@heroui/native-mcp@latest"] } } } ``` 重启 OpenCode 后生效。 详见 [OpenCode MCP 文档](https://open-code.ai/docs/en/mcp-servers)。 ## 用法 配置完成后,可向 AI 提问,例如: * "Help me install HeroUI Native in my Expo app" * "Show me all HeroUI Native components" * "What props does the Button component have?" * "Give me an example of using the Card component" * "What are the theme variables for dark mode?" ### 自动升级 MCP 也可协助将 HeroUI Native 升级到最新版本,例如: ```bash "Hey Cursor, update HeroUI Native to the latest version" ``` 助手通常会: * 对比当前版本与最新发布 * 阅读变更日志中的破坏性变更 * 在项目中应用必要的代码更新 适用于升级到最新稳定版或预发布版本。 ## 可用工具 MCP 向 AI 暴露以下工具: | 工具 | 说明 | | --------------------- | ---------------------------------------------------------------------------------- | | `list_components` | 列出全部 HeroUI Native 组件 | | `get_component_docs` | 获取一个或多个组件的完整文档(结构、props、示例与用法模式) | | `get_theme_variables` | 读取颜色、排版、间距等主题变量,支持明暗模式 | | `get_docs` | 浏览 HeroUI Native 全部文档(指南与原则等);安装说明可使用路径 `/docs/native/getting-started/quick-start` | ## 故障排除 **环境要求:** Node.js 22 及以上。使用 `npx` 时会自动下载包。 **需要帮助?** [GitHub Issues](https://github.com/heroui-inc/heroui-mcp/issues) | [Discord 社区](https://discord.gg/heroui) ## 链接 * [npm 包](https://www.npmjs.com/package/@heroui/native-mcp) * [GitHub 仓库](https://github.com/heroui-inc/heroui-mcp) * [贡献指南](https://github.com/heroui-inc/heroui-mcp/blob/main/CONTRIBUTING.md)
# 动画 **Category**: react **URL**: https://www.heroui.com/cn/docs/react/getting-started/animation **Source**: https://raw.githubusercontent.com/heroui-inc/heroui/refs/heads/v3/apps/docs/content/docs/cn/react/getting-started/(handbook)/animation.mdx > 为 HeroUI v3 组件添加流畅的动画和过渡 HeroUI 组件支持多种动画方法:内置 CSS 过渡、自定义 CSS 动画以及 Framer Motion 等 JavaScript 库。 ## 内置动画 HeroUI 组件使用数据属性来公开其动画状态: ```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; } ``` **状态样式属性:** * `[data-hovered="true"]`- 悬停状态 * `[data-pressed="true"]`- 活动/按下状态 * `[data-focus-visible="true"]`- 键盘焦点 * `[data-disabled="true"]`- 禁用状态 * `[data-entering]` / `[data-exiting]`- 过渡状态 * `[aria-expanded="true"]`- 展开状态 ## CSS 动画 **使用 Tailwind 实用程序:** ```tsx // Pulse on hover // Fade in entrance Welcome message // Staggered list
Item 1 Item 2
``` **自定义过渡:** ```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 组件与 Framer Motion 无缝协作,实现高级动画。 **基本用法:** ```tsx import { motion } from 'framer-motion'; import { Button } from '@heroui/react'; const MotionButton = motion(Button); Animated Button ``` **入口动画:** ```tsx Welcome! ``` **布局动画:** ```tsx import { AnimatePresence, motion } from 'framer-motion'; function Tabs({ items, selected }) { return (
{items.map((item, i) => ( ))}
); } ``` ## 渲染属性 根据组件状态应用动态动画: ```tsx ``` ## 无障碍 **尊重动态偏好:** HeroUI 使用 Tailwind 的 motion-reduce 工具自动尊重用户动态效果偏好。当用户在系统设置中启用“减少动态效果”时,所有内置的过渡和动画效果都将被禁用。 HeroUI 扩展了 Tailwind 的 motion-reduce: 变体,以同时支持原生 `prefers-reduced-motion` 媒体查询和 `data-reduce-motion` 属性。 ```css /* HeroUI pattern - uses Tailwind's motion-reduce: */ .button { @apply transition-colors motion-reduce:transition-none; } /* Expands to support both approaches: */ @media (prefers-reduced-motion: reduce) { .button { transition: none; } } [data-reduce-motion="true"] .button { transition: none; } ``` 使用Framer Motion: ```tsx import { useReducedMotion } from 'framer-motion'; function AnimatedCard() { const shouldReduceMotion = useReducedMotion(); return ( Content ); } ``` **全局禁用动画:** 添加`data-reduce-motion="true"`到``或者``标签: ```html ``` HeroUI自动检测用户的`prefers-reduced-motion: reduce`相应地设置并禁用动画。 ## 性能技巧 **使用 GPU 加速属性**: 首选`transform`和`opacity`对于流畅的动画: ```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`优化**: 使用`will-change`优化动画,但在不设置动画时将其删除: ```css .button { will-change: transform; } .button:not(:hover) { will-change: auto; } ``` ## 下一步 * 了解[样式](/docs/handbook/styling)方法 * 探索[组件](/docs/react/components)示例 * 查看[主题](/docs/handbook/theming)文档
# 颜色 **Category**: react **URL**: https://www.heroui.com/cn/docs/react/getting-started/colors **Source**: https://raw.githubusercontent.com/heroui-inc/heroui/refs/heads/v3/apps/docs/content/docs/cn/react/getting-started/(handbook)/colors.mdx > HeroUI v3 的调色板与主题系统 import {ColorSectionSideBySide, ColorSectionStacked, ColorSectionFormField, ColorSectionPrimitive} from "@/components/color-section"; HeroUI 的颜色体系围绕语义意图构建,而非堆砌视觉色板。系统不会暴露庞大的原始色表,而是定义一小套有意义的色彩角色,覆盖绝大多数界面需求。 系统中的多数颜色会由少量基础值自动派生。这样 HeroUI 能在保持对比度、层级与主题行为一致的同时,让整套体系易于理解与修改。 颜色应首先传达用途与状态;视觉变化来自尺度、强调与上下文。 **想要创建你自己的主题?** 试试 [主题构建器](/themes),以可视化方式自定义颜色、圆角、字体等,然后导出 CSS 用于你的项目。 ## 强调色 强调色代表品牌或产品的主识别色,用于吸引对关键操作、高亮与重点时刻的注意。 强调色应有意识地节制使用。滥用会削弱其冲击力,并破坏视觉层级。多数情况下,组件会从基础强调色自动派生悬停、柔和背景与聚焦等相关取值。 ## 默认(中性色) 默认色构成系统的中性骨架,用于大多数非强调的界面元素。 ## 成功 成功色传达积极结果、确认与完成状态,常见于反馈组件、状态指示与校验通过等场景。 ## 警告 警告色表示需谨慎、存在风险,或需要留意但非破坏性的操作,常用于提示、消息以及用户应暂停或复核信息的过渡状态。 ## 危险 危险色表示破坏性、不可逆或关键的操作与状态,应一眼可辨,并稳定用于错误、危险按钮与严重告警。 ## 前景色 前景色用于正文级内容,如文字与图标。这些颜色针对可读性与无障碍优化,并会随背景与表面上下文自动适配。请勿在组件内硬编码前景色。 ## 背景色 背景色定义界面的基底画布,在保持视觉克制的前提下建立整体对比与氛围。 ## 表面色 表面色叠在背景之上,用于卡片、面板、模态与下拉等容器。表面通过抬升、对比与分层形成区隔与层级,而非依赖强烈的色相跳跃。 ## 表单字段 表单字段色是面向输入、控件与可交互字段的专用令牌,覆盖默认、聚焦与悬停等多种状态。将其独立出来,可让表单元素在视觉上与按钮及界面其余部分保持清晰区分。 ## 分隔线 分隔线色用于分割线、描边与轻量边界,用来组织内容、引导视线而不增加噪点。分隔线色应保持低对比、不抢眼。 ## 其他 其他颜色在界面中承担特定工具性角色,用于组织内容、引导视线而不增加噪点。 ## 基础色 基础色是与模式无关的底层取值,作为语义色令牌的根基,在明暗主题之间不会改变。 ## 如何使用颜色 **在组件中:** ```jsx
``` **在 CSS 文件中:** ```css title="global.css" /* 直接使用 CSS 变量 */ .my-component { background: var(--accent); color: var(--accent-foreground); border: 1px solid var(--border); } /* 配合 @apply 与 @layer */ @layer components { .button { @apply bg-accent text-accent-foreground; &:hover, &[data-hovered="true"] { @apply bg-accent-hover; } &:active, &[data-pressed="true"] { @apply bg-accent-hover; transform: scale(0.97); } } } ``` ## 默认主题 完整主题定义见仓库中的 [variables.css](https://github.com/heroui-inc/heroui/blob/v3/packages/styles/themes/default/variables.css)。该主题会根据 `class="dark"` 或 `data-theme="dark"` 属性在明暗模式间自动切换。 ```css @layer base { /* HeroUI 默认主题 */ :root { color-scheme: light; /* == 通用变量 == */ /* 基础色(在明暗模式下勿改动) */ --white: oklch(100% 0 0); --black: oklch(0% 0 0); --snow: oklch(0.9911 0 0); --eclipse: oklch(0.2103 0.0059 285.89); /* 间距刻度 */ --spacing: 0.25rem; /* 边框 */ --border-width: 1px; --field-border-width: 0px; --disabled-opacity: 0.5; /* 聚焦环偏移,用于聚焦环 */ --ring-offset-width: 2px; /* 光标 */ --cursor-interactive: pointer; --cursor-disabled: not-allowed; /* 圆角 */ --radius: 0.5rem; --field-radius: calc(var(--radius) * 1.5); /* == 浅色主题变量 == */ /* 基础颜色 */ --background: oklch(0.9702 0 0); --foreground: var(--eclipse); /* 表面:用于非浮层组件(卡片、手风琴、折叠组等) */ --surface: var(--white); --surface-foreground: var(--foreground); /* 遮罩层:用于悬浮/浮层组件(工具提示、气泡、模态框、菜单) */ --overlay: var(--white); --overlay-foreground: var(--foreground); --muted: oklch(0.5517 0.0138 285.94); --scrollbar: oklch(87.1% 0.006 286.286); --default: oklch(94% 0.001 286.375); --default-foreground: var(--eclipse); --accent: oklch(0.6204 0.195 253.83); --accent-foreground: var(--snow); /* 表单字段默认值 - 颜色 */ --field-background: var(--white); --field-foreground: oklch(0.2103 0.0059 285.89); --field-placeholder: var(--muted); --field-border: transparent; /* 表单字段默认无边框 */ /* 状态色 */ --success: oklch(0.7329 0.1935 150.81); --success-foreground: var(--eclipse); --warning: oklch(0.7819 0.1585 72.33); --warning-foreground: var(--eclipse); --danger: oklch(0.6532 0.2328 25.74); --danger-foreground: var(--snow); /* 组件颜色 */ --segment: var(--white); --segment-foreground: var(--eclipse); /* 杂项颜色 */ --border: oklch(92% 0.004 286.32); --separator: oklch(92% 0.004 286.32); --focus: var(--accent); --link: var(--foreground); /* 背衬 */ --backdrop: rgba(0, 0, 0, 0.5); /* 阴影 */ --surface-shadow: 0 2px 4px 0 rgba(0, 0, 0, 0.04), 0 1px 2px 0 rgba(0, 0, 0, 0.06), 0 0 1px 0 rgba(0, 0, 0, 0.06); /* 遮罩层阴影 */ --overlay-shadow: 0 4px 16px 0 rgba(24, 24, 27, 0.08), 0 8px 24px 0 rgba(24, 24, 27, 0.09); --field-shadow: 0 2px 4px 0 rgba(0, 0, 0, 0.04), 0 1px 2px 0 rgba(0, 0, 0, 0.06), 0 0 1px 0 rgba(0, 0, 0, 0.06); /* 骨架屏全局默认动画 */ --skeleton-animation: shimmer; /* shimmer, pulse, none */ /* Tooltip 默认延迟 */ --tooltip-delay: 1500ms; --tooltip-close-delay: 500ms; } .dark, [data-theme="dark"] { color-scheme: dark; /* == 深色主题变量 == */ /* 基础颜色 */ --background: oklch(12% 0.005 285.823); --foreground: var(--snow); /* 表面:用于非浮层组件(卡片、手风琴、折叠组等) */ --surface: oklch(0.2103 0.0059 285.89); --surface-foreground: var(--foreground); /* 遮罩层:用于悬浮/浮层组件(工具提示、气泡、模态框、菜单)——略浅于表面以提高对比度 */ --overlay: oklch(0.22 0.0059 285.89); /* 比表面色略浅,便于在深色模式下辨识 */ --overlay-foreground: var(--foreground); --muted: oklch(70.5% 0.015 286.067); --scrollbar: oklch(70.5% 0.015 286.067); --default: oklch(27.4% 0.006 286.033); --default-foreground: var(--snow); /* 表单字段默认值 - 颜色(仅列出与浅色主题不同的项) */ --field-background: var(--default); --field-foreground: var(--foreground); /* 状态色 */ --warning: oklch(0.8203 0.1388 76.34); --warning-foreground: var(--eclipse); --danger: oklch(0.594 0.1967 24.63); --danger-foreground: var(--snow); /* 组件颜色 */ --segment: oklch(0.3964 0.01 285.93); --segment-foreground: var(--foreground); /* 杂项颜色 */ --border: oklch(22% 0.006 286.033); --separator: oklch(22% 0.006 286.033); --focus: var(--accent); --link: var(--foreground); /* 背衬 */ --backdrop: rgba(0, 0, 0, 0.6); /* 阴影 */ --surface-shadow: 0 0 0 0 transparent inset; /* 深色模式下无阴影 */ --overlay-shadow: 0 0 0 0 transparent inset; /* 深色模式下无阴影 */ --field-shadow: 0 0 0 0 transparent inset; /* 透明阴影,以便环形工具类生效 */ } } ``` ## 自定义颜色 **覆盖已有颜色:** ```css :root { /* 覆盖默认颜色 */ --accent: oklch(0.7 0.15 250); --success: oklch(0.65 0.15 155); } [data-theme="dark"] { /* 覆盖深色主题颜色 */ --accent: oklch(0.8 0.12 250); --success: oklch(0.75 0.12 155); } ``` **提示:** 可在 [oklch.com](https://oklch.com) 转换颜色。 **添加自定义颜色:** ```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); } /* 将颜色暴露给 Tailwind */ @theme inline { --color-info: var(--info); --color-info-foreground: var(--info-foreground); } ``` 随后即可使用: ```tsx
提示信息
``` > **注意:** 若要进一步了解主题变量及其在 Tailwind CSS v4 中的行为,请参阅 [Tailwind CSS 主题文档](https://tailwindcss.com/docs/theme)。
# 组合 **Category**: react **URL**: https://www.heroui.com/cn/docs/react/getting-started/composition **Source**: https://raw.githubusercontent.com/heroui-inc/heroui/refs/heads/v3/apps/docs/content/docs/cn/react/getting-started/(handbook)/composition.mdx > 使用组件组合模式构建灵活的 UI HeroUI 使用组合模式来创建灵活、可定制的组件。你可以更换渲染的元素、把组件组合在一起,并完全掌控最终的标记结构。 ## 与框架无关的样式 HeroUI 的变体函数位于 `@heroui/styles` 包中,可以独立于 React 使用。这使得 Vue、Svelte 等其他框架也能使用 HeroUI 的设计系统: ```tsx // Import directly from @heroui/styles (framework-agnostic) import { buttonVariants } from '@heroui/styles'; // Or import from @heroui/react (re-exports the same functions) import { buttonVariants } from '@heroui/react'; ``` 两种导入方式的工作原理完全相同。在为非 React 框架构建,或希望避免引入 React 依赖时,请使用 `@heroui/styles`。 ## 多态样式 使用变体函数或 BEM 类,将 HeroUI 样式应用到任何元素上。可以把组件样式扩展到框架组件、原生 HTML 元素或自定义组件,并保持完整的类型安全。 **示例:将 Link 设置为按钮样式** 你可以使用 `buttonVariants` 为 Link 组件应用按钮样式: ```tsx import { buttonVariants } from '@heroui/styles'; import Link from 'next/link'; // Style a Next.js Link as a primary button About // Style a native anchor as a secondary button with custom size External Link ``` **直接使用 BEM 类:** ```tsx import Link from 'next/link'; // Apply button styles directly using BEM classes About ``` **配合复合组件使用** 当使用自定义根元素而非 HeroUI 的 Root 组件时,子组件无法访问 context slot。你可以使用变体函数或 BEM 类,手动将 `className` 传递给子组件: ```tsx import { Link } from '@heroui/react'; import { linkVariants } from '@heroui/styles'; import NextLink from 'next/link'; // With custom root - pass className manually const slots = linkVariants(); About Page About Page ``` 这种方法之所以可行,是因为 HeroUI 的变体函数和 BEM 类可以应用到任何元素上,让你能够灵活地用 HeroUI 的设计系统为框架组件、原生元素或自定义组件设置样式。 ## 直接应用类名 为链接或其他元素设置样式最简单的方法,就是直接使用 HeroUI 的 [BEM](https://getbem.com/) 类。这种方法简单直接,适用于任何框架或纯 HTML。 **配合 Next.js Link 使用:** ```tsx import Link from 'next/link'; Return Home ``` **配合原生 anchor 使用:** ```tsx Go to Dashboard ``` **可用的按钮类名:** * `.button` — 基础按钮样式 * `.button--primary`、`.button--secondary`、`.button--tertiary`、`.button--danger`、`.button--ghost` — 变体 * `.button--sm`、`.button--md`、`.button--lg` — 尺寸 * `.button--icon-only` — 仅图标按钮 这种方法之所以可行,是因为 HeroUI 使用了 [BEM](https://getbem.com/) 类,可以应用到任何元素上。当你不需要组件的交互功能(例如 `onPress` 事件处理器)、只想要视觉样式时,这种方式非常合适。 ## 使用变体函数 如需更多控制和类型安全,可以使用变体函数将 HeroUI 样式应用到特定框架的组件或自定义元素上。`@heroui/styles`(与框架无关)和 `@heroui/react`(重新导出)都提供了变体函数。 **配合 Next.js Link 使用:** ```tsx import { Link } from '@heroui/react'; import { linkVariants } from '@heroui/styles'; import NextLink from 'next/link'; const slots = linkVariants(); About Page ``` **配合 Button 样式:** ```tsx import { buttonVariants } from '@heroui/styles'; import Link from 'next/link'; Dashboard ``` **可用的变体函数:** 每个组件都从 `@heroui/styles` 导出其变体函数(`buttonVariants`、`chipVariants`、`linkVariants`、`spinnerVariants` 等)。使用它们可以在保持类型安全的同时,将 HeroUI 的设计系统应用到任何元素上。 ## 复合组件 HeroUI 组件以复合组件的方式构建 —— 它们会导出多个协同工作的子部件。你可以通过三种灵活的方式来使用它们: **选项 1:复合模式(推荐)** — 直接使用主组件,无需 `.Root` 后缀: ```tsx import { Alert } from '@heroui/react'; Success Your changes have been saved. ``` **选项 2:使用 .Root 的复合模式** — 如果你喜欢显式命名,可以添加 `.Root` 后缀: ```tsx import { Alert } from '@heroui/react'; Success Your changes have been saved. ``` **选项 3:命名导出** — 单独导入每个部分: ```tsx import { AlertRoot, AlertIcon, AlertContent, AlertTitle, AlertDescription, AlertClose } from '@heroui/react'; Success Your changes have been saved. ``` **混合语法:** 在同一组件中混合复合和命名导出: ```tsx import { Alert, AlertTitle, AlertDescription } from '@heroui/react'; Success Your changes have been saved. ``` **简单组件:** 像 `Button` 这样的简单组件以同样的方式工作 —— 无需 `.Root`: ```tsx import { Button } from '@heroui/react'; // Recommended - no .Root needed // Or with .Root Click me // Or named export import { ButtonRoot } from '@heroui/react'; Click me ``` **优点:** 这三种模式都能提供灵活性、可定制性、可控性和一致性。选择最适合你代码库的那一种即可。 ## 混合使用变体函数 你可以组合来自不同组件的变体函数,以创建独特的样式: ```tsx import { Link } from '@heroui/react'; import { linkVariants, buttonVariants } from '@heroui/styles'; // Link styled with button variants const buttonStyles = buttonVariants({ variant: "tertiary", size: "md" }); HeroUI ``` ## 自定义组件 通过组合 HeroUI 原语,创建你自己的组件: ```tsx import { Button, Tooltip } from '@heroui/react'; import { buttonVariants } from '@heroui/styles'; // Link button component using variant functions function LinkButton({ href, children, variant = "primary", ...props }) { return ( {children} ); } // Icon button with tooltip function IconButton({ icon, label, ...props }) { return ( {label} ); } ``` ## 自定义变体 通过扩展组件的变体函数来创建自定义变体: ```tsx import type { ButtonRootProps } from "@heroui/react"; import type { VariantProps } from "tailwind-variants"; import { Button } from "@heroui/react"; import { buttonVariants, tv } from "@heroui/styles"; 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 ``` `render` prop 对于从客户端路由库渲染链接组件,或复用已有的展示型组件也很有用。 ```tsx import {Link} from '@heroui/react'; import NextLink from 'next/link'; ( } href="/privacy-policy" /> )} > Privacy Policy ``` 请遵循以下规则,以免破坏组件的行为和无障碍能力: * 始终渲染期望的元素类型(例如,如果期望的是 ` ); } ``` ### Pages Router 如果使用 `pages/`,请在 `pages/_app.tsx` 中包裹你的应用。 ```tsx // pages/_app.tsx import "@/styles/globals.css"; import type {AppProps} from "next/app"; import {ThemeProvider as NextThemesProvider} from "next-themes"; export default function App({Component, pageProps}: AppProps) { return ( ); } ``` ## 使用自定义主题名称 `attribute="class"` 这套配置非常适合内置的 `light` 和 `dark` 主题。如果你的自定义主题 CSS 是基于 `data-theme` 选择器编写的,请改为让 `next-themes` 写入 `data-theme`。 ```tsx {children} ``` 当你传入自定义的 `themes` 列表时,如果仍然希望保留内置主题,请将 `"light"` 和 `"dark"` 一并包含进去。 ## 在 React 中使用 useTheme 当你正在构建一个普通的 React 应用(例如 Vite 或 Create React App),并且不需要 `next-themes` 时,可以使用 HeroUI 提供的 `useTheme` 钩子。 该钩子从 `@heroui/react` 中导出。它会将当前选择的主题保存到 `localStorage`,根据用户的操作系统偏好解析 `"system"`,并同时把对应的类与 `data-theme` 属性应用到 `` 上。 ```tsx // src/components/theme-switcher.tsx import {Button, useTheme} from "@heroui/react"; export function ThemeSwitcher() { const {resolvedTheme, setTheme, theme} = useTheme("system"); return (
); } ``` 每个应用只应使用一个主题控制器。在 Next.js 中,推荐使用 `next-themes` 及其 `useTheme` 钩子;在普通的 React 应用中,请使用 `@heroui/react` 提供的 `useTheme`。 ## 同时为两种主题设置样式 主题相关的工具类会自动生效,因为它们读取的是 CSS 变量: ```tsx
Theme-aware content
``` 对于仅在深色模式下生效的一次性样式调整,请使用 `dark:` 变体: ```tsx
Custom dark-mode adjustment
```
# 样式 **Category**: react **URL**: https://www.heroui.com/cn/docs/react/getting-started/styling **Source**: https://raw.githubusercontent.com/heroui-inc/heroui/refs/heads/v3/apps/docs/content/docs/cn/react/getting-started/(handbook)/styling.mdx > 使用 CSS、Tailwind 或 CSS-in-JS 为 HeroUI 组件设置样式 HeroUI 组件提供灵活的样式方案:Tailwind CSS 工具类、配合 [BEM](https://getbem.com/) 类名或数据属性的 CSS、CSS-in-JS 库,以及用于动态样式的渲染属性。 ## 基础样式 **使用 className:** 所有 HeroUI 组件都接受 `className` 属性: ```tsx {/* content */} ``` **使用 style:** 组件也接受内联样式: ```tsx ``` ## 滚动条 HeroUI 的滚动插槽在组件 CSS 中使用 `@apply scrollbar`。对于你自己的溢出容器,可使用 `@heroui/styles` 提供的工具类: ```tsx
{/* 长内容 */}
``` | 工具类 | 效果 | | ------------------- | -------------------------------------- | | `scrollbar` | HeroUI 滚动条滑块(读取主题的 `--scrollbar-*` 变量) | | `scrollbar-thin` | HeroUI 主题化纤细滚动条 | | `scrollbar-default` | 操作系统 / 浏览器默认滚动条 | | `scrollbar-none` | 隐藏滚动条 | 全局及子树级别的控制可通过在祖先元素上使用 `data-scrollbar` 实现。有关令牌(tokens)和模式的更多信息,请参阅 [主题](/docs/handbook/theming#scrollbars)。 ## 基于状态的样式 HeroUI 组件通过数据属性公开其状态,类似于 CSS 伪类: ```css /* Target different states */ .button[data-hovered="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); } ``` ## 渲染属性 根据组件状态动态应用样式: ```tsx // Dynamic classes // Dynamic content ``` ## BEM 类名 HeroUI 使用 [BEM 方法论](https://getbem.com/) 来保持类名命名的一致性: ```css /* Block */ .button { } .accordion { } /* Element */ .accordion__trigger { } .accordion__panel { } /* Modifier */ .button--primary { } .button--lg { } .accordion--outline { } ``` **全局自定义组件:** ```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; } } ``` ## 创建包装组件 使用 [tailwind-variants](https://tailwind-variants.org/) 创建可复用的自定义组件 —— 它是 Tailwind CSS 的一等公民变体 API: ```tsx import { Button as HeroButton, type ButtonProps } from '@heroui/react'; import { buttonVariants, tv, type VariantProps } from '@heroui/styles'; 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 集成 **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); } `; ``` ## 响应式设计 **使用 Tailwind 工具类:** ```tsx ``` **或者使用 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 模块 如需作用域化的样式,可以使用 CSS 模块: ```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'; ``` ## 组件类名参考 **Button:** `.button`、`.button--{variant}`、`.button--{size}`、`.button--icon-only` **Accordion:** `.accordion`、`.accordion__item`、`.accordion__trigger`、`.accordion__panel`、`.accordion--outline` > **注意:** 完整的类名参考请查看各组件文档:[Button](/docs/components/button#css-classes)、[Accordion](/docs/components/accordion#css-classes) 所有组件的类名请查看 [@heroui/styles/components](https://github.com/heroui-inc/heroui/tree/main/packages/styles/components)。 ## 下一步 * 了解 [动画](/docs/handbook/animation) 相关技巧 * 探索 [主题](/docs/handbook/theming) 系统 * 浏览 [组件](/docs/react/components) 示例
# 主题 **Category**: react **URL**: https://www.heroui.com/cn/docs/react/getting-started/theming **Source**: https://raw.githubusercontent.com/heroui-inc/heroui/refs/heads/v3/apps/docs/content/docs/cn/react/getting-started/(handbook)/theming.mdx > 使用 CSS 变量和全局样式自定义 HeroUI 的设计系统 HeroUI 使用 CSS 变量和 [BEM](https://getbem.com/) 类来实现主题化。你可以使用标准 CSS 自定义从颜色到组件样式的所有内容。 **想要创建你自己的主题?** 试试 [主题构建器](/themes),以可视化方式自定义颜色、圆角、字体等,然后导出 CSS 用于你的项目。 ## 工作原理 HeroUI 的主题系统构建于 [Tailwind CSS v4](https://tailwindcss.com/docs/theme) 的主题之上。当你导入 `@heroui/styles` 时,它会使用 Tailwind 的内置调色板,将其映射到语义化变量,自动在浅色和深色主题之间切换,并使用 CSS 层和 `@theme` 指令进行组织。 **命名规则:** * 不带后缀的颜色用作背景(例如 `--accent`) * 带 `-foreground` 后缀的颜色用于该背景上的文本(例如 `--accent-foreground`) ## 快速开始 **应用主题:** 将主题类添加到 HTML 并将颜色应用到 body 上: ```html ``` **切换主题:** ```html ``` **使用 [next-themes](https://github.com/pacocoursey/next-themes) 以编程方式切换主题(适用于 Next.js):** 首先,用 `ThemeProvider` 包装你的应用: ```tsx // app/providers.tsx "use client"; import { ThemeProvider } from "next-themes"; export function Providers({ children }: { children: React.ReactNode }) { return ( {children} ); } ``` ```tsx // app/layout.tsx import { Providers } from "./providers"; export default function RootLayout({ children }: { children: React.ReactNode }) { return ( {children} ); } ``` 然后使用 `useTheme` 在主题之间切换: ```tsx "use client"; import { useTheme } from "next-themes"; export function ThemeSwitch() { const { theme, setTheme } = useTheme(); return ( ); } ``` **覆盖颜色:** ```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); } ``` > **注意**:完整的调色板和视觉参考请参见 [颜色](/docs/handbook/colors)。 > **深色模式**:如需基于 `next-themes` 与 HeroUI `useTheme` 钩子的完整配置指南,请参见 [深色模式](/docs/handbook/dark-mode)。 **创建你自己的主题:** ```css /* src/themes/ocean.css */ @layer base { /* Ocean Light */ [data-theme="ocean"] { color-scheme: light; /* Primitive Colors (Do not change between light and dark) */ --white: oklch(100% 0 0); --black: oklch(0% 0 0); --snow: oklch(0.9911 0 0); --eclipse: oklch(0.2103 0.0059 285.89); /* Spacing & Layout */ --spacing: 0.25rem; --border-width: 1px; --field-border-width: 0px; --disabled-opacity: 0.5; --ring-offset-width: 2px; --cursor-interactive: pointer; --cursor-disabled: not-allowed; /* Radius */ --radius: 0.75rem; --field-radius: calc(var(--radius) * 1.5); /* Base Colors */ --background: oklch(0.985 0.015 225); --foreground: var(--eclipse); /* Surface: Used for non-overlay components */ --surface: var(--white); --surface-foreground: var(--foreground); /* Overlay: Used for floating/overlay components */ --overlay: var(--white); --overlay-foreground: var(--foreground); --muted: oklch(0.5517 0.0138 285.94); --scrollbar-thumb: color-mix(in oklch, var(--foreground) 15%, transparent); --scrollbar-track: transparent; --scrollbar-gutter: auto; --scrollbar-width: thin; --scrollbar-color: var(--scrollbar-thumb) var(--scrollbar-track); --scrollbar: var(--scrollbar-thumb); --default: oklch(94% 0.001 286.375); --default-foreground: var(--eclipse); /* Ocean accent */ --accent: oklch(0.450 0.150 230); --accent-foreground: var(--snow); /* Form Field Defaults */ --field-background: var(--white); --field-foreground: oklch(0.2103 0.0059 285.89); --field-placeholder: var(--muted); --field-border: transparent; /* Status (kept compatible) */ --success: oklch(0.7329 0.1935 150.81); --success-foreground: var(--eclipse); --warning: oklch(0.7819 0.1585 72.33); --warning-foreground: var(--eclipse); --danger: oklch(0.6532 0.2328 25.74); --danger-foreground: var(--snow); /* Component Colors */ --segment: var(--white); --segment-foreground: var(--foreground); /* Misc */ --border: oklch(0.50 0.060 230 / 22%); --separator: oklch(92% 0.004 286.32); --focus: var(--accent); --link: var(--accent); /* Shadows */ --surface-shadow: 0 2px 4px 0 rgba(0, 0, 0, 0.04), 0 1px 2px 0 rgba(0, 0, 0, 0.06), 0 0 1px 0 rgba(0, 0, 0, 0.06); --overlay-shadow: 0 4px 16px 0 rgba(24, 24, 27, 0.08), 0 8px 24px 0 rgba(24, 24, 27, 0.09); --field-shadow: 0 2px 4px 0 rgba(0, 0, 0, 0.04), 0 1px 2px 0 rgba(0, 0, 0, 0.06), 0 0 1px 0 rgba(0, 0, 0, 0.06); /* Skeleton Default Global Animation */ --skeleton-animation: shimmer; /* Possible values: shimmer, pulse, none */ /* Tooltip Default Delays */ --tooltip-delay: 1500ms; --tooltip-close-delay: 500ms; } /* Ocean Dark */ [data-theme="ocean-dark"] { color-scheme: dark; /* Base Colors */ --background: oklch(0.140 0.020 230); --foreground: var(--snow); /* Surface: Used for non-overlay components */ --surface: oklch(0.2103 0.0059 285.89); --surface-foreground: var(--foreground); /* Overlay: Used for floating/overlay components */ --overlay: oklch(0.22 0.0059 285.89); --overlay-foreground: var(--foreground); --muted: oklch(70.5% 0.015 286.067); --scrollbar-thumb: color-mix(in oklch, var(--foreground) 15%, transparent); --scrollbar-track: transparent; --scrollbar-gutter: auto; --scrollbar-width: thin; --scrollbar-color: var(--scrollbar-thumb) var(--scrollbar-track); --scrollbar: var(--scrollbar-thumb); --default: oklch(27.4% 0.006 286.033); --default-foreground: var(--snow); /* Form Field Defaults */ --field-background: var(--default); --field-foreground: var(--foreground); /* Ocean accent */ --accent: oklch(0.860 0.080 230); --accent-foreground: var(--eclipse); /* Status */ --success: oklch(0.7329 0.1935 150.81); --success-foreground: var(--eclipse); --warning: oklch(0.8203 0.1388 76.34); --warning-foreground: var(--eclipse); --danger: oklch(0.594 0.1967 24.63); --danger-foreground: var(--snow); /* Component Colors */ --segment: oklch(0.3964 0.01 285.93); --segment-foreground: var(--foreground); /* Misc */ --border: oklch(22% 0.006 286.033); --separator: oklch(22% 0.006 286.033); --focus: var(--accent); --link: var(--accent); /* Shadows */ --surface-shadow: 0 0 0 0 transparent inset; --overlay-shadow: 0 0 0 0 transparent inset; --field-shadow: 0 0 0 0 transparent inset; } } ``` 使用你的主题: ```css /* app/globals.css */ @layer theme, base, components, utilities; @import "tailwindcss"; @import "@heroui/styles"; @import "./src/themes/ocean.css" layer(theme); /* [!code highlight]*/ ``` 应用你的主题: ```html ``` ## 自定义组件 **全局组件样式:** 使用 BEM 类覆盖任何组件: ```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; } } ``` > **注意**:完整的样式参考请参见 [样式](/docs/handbook/styling)。 **查找组件类名:** 每个组件文档页面都会列出所有可用的类名(基类、修饰符、元素、状态)。示例:[Button 类名](/docs/components/button#css-classes) ## 导入策略 **完整导入(推荐):** 两行代码即可获得全部内容: ```css @import "tailwindcss"; @import "@heroui/styles"; ``` **按需导入:** 只导入你需要的内容: ```css /* Define layers */ @layer theme, base, components, utilities; /* Base requirements */ @import "tailwindcss"; @import "@heroui/styles/base" layer(base); /* OR specific base file */ @import "@heroui/styles/base/base.css" layer(base); /* Theme variables */ @import "@heroui/styles/themes/shared/theme.css" layer(theme); @import "@heroui/styles/themes/default" layer(theme); /* OR specific theme files */ @import "@heroui/styles/themes/default/index.css" layer(theme); @import "@heroui/styles/themes/default/variables.css" layer(theme); /* Components (all components) */ @import "@heroui/styles/components" layer(components); /* OR specific component files */ @import "@heroui/styles/components/index.css" layer(components); @import "@heroui/styles/components/button.css" layer(components); @import "@heroui/styles/components/accordion.css" layer(components); /* Utilities (optional) */ @import "@heroui/styles/utilities" layer(utilities); /* Variants (optional) */ @import "@heroui/styles/variants" layer(utilities); ``` > **注意**:目录导入(例如 `@heroui/styles/components`)会自动解析为其对应的 `index.css` 文件。使用显式文件路径(例如 `@heroui/styles/components/button.css`)来导入单个组件的样式。 **Headless 模式:** 从头开始构建你自己的样式: ```css @import "tailwindcss"; @import "@heroui/styles/base/base.css"; /* Your custom styles */ .button { /* Your button styles */ } ``` ## 添加自定义颜色 将你自己的语义化颜色添加到主题中: ```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); } ``` 现在你可以在组件中使用它: ```tsx
Info message
``` ## 变量参考 HeroUI 在 [`variables.css`](https://github.com/heroui-inc/heroui/blob/v3/packages/styles/themes/default/variables.css) 中定义了三种类型的变量: 1. **基础变量(Base Variables)** — 不会变化的值,例如 `--white`、`--black`、间距以及排版 2. **主题变量(Theme Variables)** — 在浅色 / 深色主题之间切换的颜色,以及滚动条令牌(`--scrollbar-thumb`、`--scrollbar-width` 等) 3. **计算变量(Calculated Variables)** — 悬停状态、柔和(soft)变体以及边框 / 分隔线层级(每个浅色 / 深色主题中的 **Calculated Colors** 区块,使用 `color-mix()` 计算) 如需完整参考,请查阅:[颜色文档](/docs/handbook/colors)、[默认主题变量](https://github.com/heroui-inc/heroui/blob/v3/packages/styles/themes/default/variables.css)、[共享主题工具](https://github.com/heroui-inc/heroui/blob/v3/packages/styles/themes/shared/theme.css) **Tailwind 主题桥接(`@theme inline`):** [`themes/shared/theme.css`](https://github.com/heroui-inc/heroui/blob/v3/packages/styles/themes/shared/theme.css) 将语义化变量映射为 Tailwind 令牌(`--color-*`、`--radius-*`、`--ease-*`)。计算颜色引用的是 `variables.css` 中的底层变量(例如 `--surface-hover`、`--accent-soft`)—— 它们并不会在该文件中通过 `color-mix()` 内联展开: ```css @theme inline { --color-background: var(--background); --color-foreground: var(--foreground); --color-surface: var(--surface); --color-surface-foreground: var(--surface-foreground); --color-surface-hover: var(--surface-hover); --color-surface-secondary: var(--surface-secondary); --color-surface-secondary-foreground: var(--surface-secondary-foreground); --color-surface-tertiary: var(--surface-tertiary); --color-surface-tertiary-foreground: var(--surface-tertiary-foreground); --color-overlay: var(--overlay); --color-overlay-foreground: var(--overlay-foreground); --color-muted: var(--muted); --color-accent: var(--accent); --color-accent-foreground: var(--accent-foreground); --color-segment: var(--segment); --color-segment-foreground: var(--segment-foreground); --color-border: var(--border); --color-separator: var(--separator); --color-focus: var(--focus); --color-link: var(--link); --color-default: var(--default); --color-default-foreground: var(--default-foreground); --color-success: var(--success); --color-success-foreground: var(--success-foreground); --color-warning: var(--warning); --color-warning-foreground: var(--warning-foreground); --color-danger: var(--danger); --color-danger-foreground: var(--danger-foreground); --color-backdrop: var(--backdrop); --shadow-surface: var(--surface-shadow); --shadow-overlay: var(--overlay-shadow); --shadow-field: var(--field-shadow); /* 表单字段令牌 */ --color-field: var(--field-background, var(--default)); --color-field-hover: var(--field-hover); --color-field-foreground: var(--field-foreground, var(--foreground)); --color-field-placeholder: var(--field-placeholder, var(--muted)); --color-field-border: var(--field-border, var(--border)); --radius-field: var(--field-radius, calc(var(--radius) * 1.5)); --border-width-field: var(--field-border-width, var(--border-width)); /* 颜色令牌 */ --color-background-secondary: var(--background-secondary); --color-background-tertiary: var(--background-tertiary); --color-background-inverse: var(--background-inverse); --color-default-hover: var(--default-hover); --color-accent-hover: var(--accent-hover); --color-success-hover: var(--success-hover); --color-warning-hover: var(--warning-hover); --color-danger-hover: var(--danger-hover); /* 表单字段颜色 */ --color-field-focus: var(--field-focus); --color-field-border-hover: var(--field-border-hover); --color-field-border-focus: var(--field-border-focus); /* 柔和(Soft)颜色 */ --color-default-soft: var(--default-soft); --color-default-soft-foreground: var(--default-soft-foreground); --color-default-soft-hover: var(--default-soft-hover); --color-accent-soft: var(--accent-soft); --color-accent-soft-foreground: var(--accent-soft-foreground); --color-accent-soft-hover: var(--accent-soft-hover); --color-danger-soft: var(--danger-soft); --color-danger-soft-foreground: var(--danger-soft-foreground); --color-danger-soft-hover: var(--danger-soft-hover); --color-warning-soft: var(--warning-soft); --color-warning-soft-foreground: var(--warning-soft-foreground); --color-warning-soft-hover: var(--warning-soft-hover); --color-success-soft: var(--success-soft); --color-success-soft-foreground: var(--success-soft-foreground); --color-success-soft-hover: var(--success-soft-hover); /* 分隔线颜色 - 层级 */ --color-separator-secondary: var(--separator-secondary); --color-separator-tertiary: var(--separator-tertiary); /* 边框颜色 - 层级 */ --color-border-secondary: var(--border-secondary); --color-border-tertiary: var(--border-tertiary); /* 圆角与默认尺寸 - 只需更改 --radius 即可调整默认值 */ --radius-xs: calc(var(--radius) * 0.25); /* 0.125rem (2px) */ --radius-sm: calc(var(--radius) * 0.5); /* 0.25rem (4px) */ --radius-md: calc(var(--radius) * 0.75); /* 0.375rem (6px) */ --radius-lg: calc(var(--radius) * 1); /* 0.5rem (8px) */ --radius-xl: calc(var(--radius) * 1.5); /* 0.75rem (12px) */ --radius-2xl: calc(var(--radius) * 2); /* 1rem (16px) */ --radius-3xl: calc(var(--radius) * 3); /* 1.5rem (24px) */ --radius-4xl: calc(var(--radius) * 4); /* 2rem (32px) */ /* 过渡缓动函数 */ --ease-smooth: ease; /* 等同于 transition: ease; */ /* 这些自定义曲线由 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); /* 自定义的平滑收尾曲线:快速启动、平滑结束 —— Apple 风格 */ --ease-out-fluid: cubic-bezier(0.32, 0.72, 0, 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); /* 线性 */ --ease-linear: linear; /* 动画 */ --animate-spin-fast: spin 0.75s linear infinite; --animate-skeleton: skeleton 2s linear infinite; --animate-caret-blink: caret-blink 1.2s ease-out infinite; @keyframes skeleton { 100% { transform: translateX(200%); } } @keyframes caret-blink { 0%, 70%, 100% { opacity: 1; } 20%, 50% { opacity: 0; } } } ``` 表单控件依赖 `--field-*` 主题变量。悬停、聚焦及边框变体定义于 `variables.css` 的 **Calculated Colors** 区块中,并在 `theme.css` 中映射到 Tailwind 令牌(例如 `--color-field-hover: var(--field-hover)`)。在你的主题中覆盖 `--field-background`、`--field-hover` 及相关令牌,即可重新设计输入框、复选框、单选框和 OTP 输入槽的样式,而不会影响按钮或卡片等表面(surface)。 ## 滚动条 HeroUI 为组件中的滚动区域(表格、弹出框、抽屉等)应用统一的滚动条样式。滚动条使用标准 CSS 属性(`scrollbar-width`、`scrollbar-color`、`scrollbar-gutter`),不再依赖 `::-webkit-scrollbar` 覆盖。 **模式** — 在 ``、组件根元素或滚动插槽上设置 `data-scrollbar`: | 模式 | `data-scrollbar` | 行为 | | ---------- | ---------------- | ------------------------------- | | HeroUI 纤细 | *(未设置)* 或 `thin` | 使用主题令牌呈现的纤细滑块 | | 操作系统 / 浏览器 | `default` | 原生滚动条(`auto`) | | 隐藏 | `none` | 不显示滚动条(`scrollbar-width: none`) | ```html
...
...
``` **主题变量** — 在 [`variables.css`](https://github.com/heroui-inc/heroui/blob/v3/packages/styles/themes/default/variables.css) 的浅色与深色主题区块中定义: | 变量 | 描述 | | -------------------- | ---------------------------------------------- | | `--scrollbar-thumb` | 滑块颜色(默认通过 `color-mix` 混入 15% 的 `--foreground`) | | `--scrollbar-track` | 轨道颜色(默认 `transparent`) | | `--scrollbar-gutter` | 滚动条间隙(默认 `auto`) | | `--scrollbar-width` | `scrollbar-width` 属性(默认 `thin`) | | `--scrollbar-color` | `scrollbar-color` 属性(默认为滑块颜色 + 轨道颜色) | | `--scrollbar` | `--scrollbar-thumb` 的旧版别名 | **全局自定义:** ```css /* app/globals.css */ :root { --scrollbar-thumb: color-mix(in oklch, var(--accent) 30%, transparent); --scrollbar-gutter: auto; } ``` **按滚动插槽** — 在组件上传入 `data-scrollbar`,或在外层包裹元素上覆盖相关令牌: ```tsx ...
``` **自定义溢出区域** — 在自己的元素上使用 `@heroui/styles` 提供的 `scrollbar`、`scrollbar-thin`、`scrollbar-default` 或 `scrollbar-none` 工具类。基于类的覆盖方式详见 [样式](/docs/handbook/styling)。 > **注意**:部分组件默认隐藏滚动条(日期选择器弹出框、颜色选择器、次级标签页)。嵌套的滚动插槽(例如日期选择器内部的日历年份选择器)会保留 HeroUI 滚动条,因为 `scrollbar-none` 只作用于其所在的元素本身,不会影响使用 `@apply scrollbar` 的后代元素。 ## 资源 * [颜色文档](/docs/handbook/colors) * [样式指南](/docs/handbook/styling) * [Tailwind CSS v4 主题](https://tailwindcss.com/docs/theme) * [BEM 方法论](https://getbem.com/) * [OKLCH 颜色工具](https://oklch.com)
# 命令行 **Category**: react **URL**: https://www.heroui.com/cn/docs/react/getting-started/cli **Source**: https://raw.githubusercontent.com/heroui-inc/heroui/refs/heads/v3/apps/docs/content/docs/cn/react/getting-started/(overview)/cli.mdx > 使用命令行管理 HeroUI 依赖并初始化项目。 `heroui-cli`是官方命令行工具,提供了一整套命令,用于初始化、管理和优化你的 HeroUI 项目。你可以 `install`、`uninstall` 或 `upgrade` 单个组件,检查项目健康状况,下载用于 AI 编程助手的文档,等等。 ## 安装 环境要求: * [Node.js 22.22.0 或更高版本](https://nodejs.org/en/) ### 全局安装 要全局安装 `heroui-cli`,请在终端中执行以下命令之一: npm pnpm yarn bun ```bash npm install heroui-cli@latest -g ``` ```bash pnpm add heroui-cli@latest -g ``` ```bash yarn global add heroui-cli@latest ``` ```bash bun add heroui-cli@latest --global ``` ### 无需安装直接使用 或者,你也可以在不进行全局安装的情况下使用 `heroui-cli`,运行以下命令之一即可: ```bash pnpm dlx heroui-cli@latest ``` ```bash npx heroui-cli@latest ``` ```bash yarn dlx heroui-cli@latest ``` ```bash bunx heroui-cli@latest ``` ## 快速开始 安装 `heroui-cli` 后,运行以下命令以查看可用命令: ```bash heroui ``` 将会输出如下帮助信息: ```bash Usage: heroui [command] Options: -v, --version Output the current version --no-cache Disable cache, by default data will be cached for 30m after the first request -d, --debug Debug mode will not install dependencies -h --help Display help information for commands Commands: init [options] [projectName] Initializes a new project install [options] Installs @heroui/react and @heroui/styles to your project upgrade [options] Upgrades @heroui/react and @heroui/styles to the latest versions uninstall [options] Uninstall @heroui/react and @heroui/styles from the project list [options] Lists installed HeroUI packages (@heroui/react, @heroui/styles) env [options] Displays debugging information for the local environment doctor [options] Checks for issues in the project agents-md [options] Downloads HeroUI documentation for AI coding agents help [command] Display help for command ``` ### init 使用 `init` 命令初始化一个新的 HeroUI 项目。该命令会为你的项目完成必要的配置。 ```bash heroui init [options] ``` **选项:** * `-t --template [string]` 新项目使用的模板,例如 app、pages、vite * `-p --package [string]` 新项目使用的包管理器 输出: ```bash HeroUI CLI ┌ Create a new project │ ◇ Select a template (Enter to select) │ ● App (A Next.js 16 with app directory template pre-configured with HeroUI (v3) and Tailwind CSS.) │ ○ Pages (A Next.js 16 with pages directory template pre-configured with HeroUI (v3) and Tailwind CSS.) │ ○ Vite (A Vite template pre-configured with HeroUI (v3) and Tailwind CSS.) │ ◇ New project name (Enter to skip with default name) │ my-heroui-app │ ◇ Select a package manager (Enter to select) │ ● npm │ ○ yarn │ ○ pnpm │ ○ bun │ ◇ Template created successfully! │ ◇ Next steps ───────╮ │ │ │ cd my-heroui-app │ │ npm install │ │ │ ├────────────────────╯ │ └ 🚀 Get started with npm run dev ``` 安装依赖以启动本地服务器: ```bash cd my-heroui-app && npm install ``` ```bash cd my-heroui-app && pnpm install ``` ```bash cd my-heroui-app && yarn install ``` ```bash cd my-heroui-app && bun install ``` 启动本地服务器: npm pnpm yarn bun ```bash npm run dev ``` ```bash pnpm run dev ``` ```bash yarn dev ``` ```bash bun run dev ``` ### Install 将 `@heroui/react` 和 `@heroui/styles` 及其对等依赖安装到你的项目中。若它们已安装,则该命令不会执行任何操作。 ```bash heroui install [options] ``` **选项:** * `-p --packagePath` \[string] package.json 文件的路径 **输出:** ```bash HeroUI CLI 📦 Packages to be installed: ╭─────────────────────────────────────────────────────────────────────────────╮ │ Package │ Version │ Status │ Docs │ │─────────────────────────────────────────────────────────────────────────────│ │ @heroui/react │ 3.0.0 │ stable │ https://heroui.com │ │ @heroui/styles │ 3.0.0 │ stable │ https://heroui.com │ ╰─────────────────────────────────────────────────────────────────────────────╯ ╭─────────────── PeerDependencies ────────────────╮ │ react@18.3.1 latest │ │ react-dom@18.3.1 latest │ │ tailwindcss@4.2.2 latest │ ╰─────────────────────────────────────────────────╯ ? Proceed with installation? › - Use arrow-keys. Return to submit. ❯ Yes No ✅ @heroui/react and @heroui/styles installed successfully ``` ### upgrade 将 `@heroui/react` 和 `@heroui/styles` 及其对等依赖升级到最新版本。 ```bash heroui upgrade [options] ``` **选项:** * `-p --packagePath` \[string] package.json 文件的路径 **输出:** ```bash HeroUI CLI ╭──────────────────────────── Upgrade ────────────────────────────╮ │ @heroui/react ^3.0.0 -> ^3.1.0 │ │ @heroui/styles ^3.0.0 -> ^3.1.0 │ ╰─────────────────────────────────────────────────────────────────╯ ? Would you like to proceed with the upgrade? › - Use arrow-keys. Return to submit. ❯ Yes No ✅ Upgrade complete. All packages are up to date. ``` ### uninstall 从你的项目中卸载 `@heroui/react` 和 `@heroui/styles`。对等依赖不会被卸载。 ```bash heroui uninstall [options] ``` **选项:** * `-p --packagePath` \[string] package.json 文件的路径 **输出:** ```bash HeroUI CLI ❗️ Packages slated for uninstallation: ╭──────────────────────────────────────────────────────────────────────────────────────╮ │ Package │ Version │ Status │ Docs │ │──────────────────────────────────────────────────────────────────────────────────────│ │ @heroui/react │ 3.0.0 │ stable │ https://heroui.com │ │ @heroui/styles │ 3.0.0 │ stable │ https://heroui.com │ ╰──────────────────────────────────────────────────────────────────────────────────────╯ ? Confirm uninstallation of these packages: › - Use arrow-keys. Return to submit. ❯ Yes No ✅ Successfully uninstalled: @heroui/react, @heroui/styles ``` ### list 列出已安装的 HeroUI 包(`@heroui/react`、`@heroui/styles`)。 ```bash heroui list [options] ``` **选项:** * `-p --packagePath` \[string] package.json 文件的路径 **输出:** ```bash HeroUI CLI Current installed packages: ╭──────────────────────────────────────────────────────────────────────────────────────╮ │ Package │ Version │ Status │ Docs │ │──────────────────────────────────────────────────────────────────────────────────────│ │ @heroui/react │ 3.0.0 🚀latest │ stable │ https://heroui.com │ │ @heroui/styles │ 3.0.0 🚀latest │ stable │ https://heroui.com │ ╰──────────────────────────────────────────────────────────────────────────────────────╯ ``` ### doctor 检查项目中存在的问题。 * 检查 `@heroui/react` 和 `@heroui/styles` 是否已安装 * 检查项目中是否安装了所需的 `对等依赖` 并满足最低版本要求 ```bash heroui doctor [options] ``` **选项:** * `-p --packagePath` \[string] package.json 文件的路径 **输出:** 如果项目中存在问题,`doctor` 命令将显示问题信息。 ```bash HeroUI CLI HeroUI CLI: ❌ Your project has 1 issue that require attention ❗️Issue 1: missingHeroUIPackages The following HeroUI packages are not installed: - @heroui/styles Run `heroui install` to install them. ``` 否则,`doctor` 命令将显示以下消息。 ```bash HeroUI CLI ✅ Your project has no detected issues. ``` ### env 显示本地环境的调试信息。 ```bash heroui env [options] ``` **选项:** * `-p --packagePath` \[string] package.json 文件的路径 **输出:** ```bash HeroUI CLI Current installed packages: ╭──────────────────────────────────────────────────────────────────────────────────────╮ │ Package │ Version │ Status │ Docs │ │──────────────────────────────────────────────────────────────────────────────────────│ │ @heroui/react │ 3.0.0 🚀latest │ stable │ https://heroui.com │ │ @heroui/styles │ 3.0.0 🚀latest │ stable │ https://heroui.com │ ╰──────────────────────────────────────────────────────────────────────────────────────╯ Environment Info: System: OS: darwin CPU: arm64 Binaries: Node: v25.8.1 ``` ### agents-md 下载用于 AI 编程助手(Claude、Cursor 等)的 HeroUI 文档。该命令会从 HeroUI 仓库克隆最新文档,并将一份精简索引注入到 `AGENTS.md` 或 `CLAUDE.md` 中,方便助手参考你项目中的 HeroUI 配置。 ```bash heroui agents-md [options] ``` **选项:** * `--react` \[boolean] 仅包含 React 文档(一次只能选择一个文档库) * `--native` \[boolean] 仅包含 Native 文档 * `--migration` \[boolean] 仅包含 HeroUI v2 到 v3 的迁移文档 * `--output ` \[string] 目标文件路径(例如 `AGENTS.md`、`CLAUDE.md`) * `--ssh` \[boolean] 使用 SSH 而非 HTTPS 进行 git clone **示例:** 不带任何标志运行以进入交互模式: ```bash heroui agents-md ``` 将 React 文档下载到指定文件: ```bash heroui agents-md --react --output AGENTS.md ``` 下载 Native 或迁移文档: ```bash heroui agents-md --native --output CLAUDE.md heroui agents-md --migration --output AGENTS.md ``` **工作原理:** 1. 使用 git sparse-checkout 从 `v3` 分支克隆文档 2. 生成文档和示例文件的精简索引 3. 将该索引注入到你的 markdown 文件中,置于标记之间(`` / ``,Native 和 Migration 也有类似的标记) 4. 将 `.heroui-docs/` 添加到 `.gitignore` `--react`、`--native` 和 `--migration` 一次只能选择其中一个。 更多详情请参阅 [AGENTS.md](/docs/react/getting-started/agents-md)。 `agents-md` 命令会收集匿名使用数据(所选项、输出文件名、耗时、成功或错误)。设置 `HEROUI_ANALYTICS_DISABLED=1` 可以选择不参与。 ## 问题反馈 如果你发现了 bug,请在 [heroui-cli Issues](https://github.com/heroui-inc/heroui-cli/issues) 中报告。 # 设计原则 **Category**: react **URL**: https://www.heroui.com/cn/docs/react/getting-started/design-principles **Source**: https://raw.githubusercontent.com/heroui-inc/heroui/refs/heads/v3/apps/docs/content/docs/cn/react/getting-started/(overview)/design-principles.mdx > 指导 HeroUI v3 设计和开发的核心原则 HeroUI v3 遵循 10 项核心原则,注重清晰度、无障碍、可定制性以及开发者体验。 ## 核心原则 ### 1. 语义意图优于视觉风格 使用语义命名(primary、secondary、tertiary),而非视觉描述(solid、flat、bordered)。灵感来自 [Uber 的 Base 设计系统](https://base.uber.com/6d2425e9f/p/756216-button),变体遵循清晰的层次结构: ```tsx // ✅ Semantic variants communicate hierarchy ``` | 变体 | 用途 | 使用方式 | | ------------- | ----------- | -------- | | **Primary** | 推进流程的主要操作 | 每种场景 1 个 | | **Secondary** | 备选操作 | 可使用多个 | | **Tertiary** | 次要操作(取消、跳过) | 谨慎使用 | | **Danger** | 破坏性操作 | 需要时使用 | ### 2. 无障碍是基础 基于 [React Aria Components](https://react-spectrum.adobe.com/react-aria/) 构建,符合 WCAG 2.1 AA 标准。内置自动 ARIA 属性、键盘导航与屏幕阅读器支持。 ```tsx import { Tabs, TabList, Tab, TabPanel } from '@heroui/react'; Profile Security Content Content ``` ### 3. 组合优于配置 复合组件允许你按需重新组合、自定义或省略其中的各个部分。可以使用点号语法、命名导出,或两者混合使用。 ```tsx // Compose parts to build exactly what you need import { Accordion, AccordionItem, AccordionHeading, AccordionTrigger, AccordionIndicator, AccordionPanel, AccordionBody } from '@heroui/react'; Question Text Answer content ``` ### 4. 渐进式呈现 从简单开始,仅在需要时才增加复杂度。组件只需最少的 props 即可工作,并能随需求增长而扩展。 ```tsx // Level 1: Minimal // Level 2: Enhanced // Level 3: Advanced ``` ### 5. 可预测的行为 所有组件遵循一致的模式:尺寸(`sm`、`md`、`lg`)、变体、`className` 支持以及 data 属性。相同的 API,相同的行为。 ```tsx // All components follow the same patterns ``` 或与 React 一同使用: ```tsx // Apply styles to any component import { buttonVariants } from '@heroui/styles'; Home ``` ### 8. 卓越的开发者体验 清晰的 API、富含信息的错误提示、IntelliSense、对 AI 友好的 Markdown 文档,以及用于可视化测试的 Storybook。 ### 9. 完全可定制 开箱即用的精美默认样式。使用 CSS 变量或 [BEM](https://getbem.com/) 类即可彻底改变整体外观。每一个插槽都可定制。 ```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. 开放且可扩展 可以包装、扩展或自定义组件以满足你的需求。可以使用变体函数、直接应用 BEM 类,或创建自定义的包装组件。 **使用变体函数应用样式:** ```tsx import { Link } from '@heroui/react'; import { linkVariants } from '@heroui/styles'; import NextLink from 'next/link'; // Use variant functions to style framework-specific components const slots = linkVariants({ underline: "hover" }); About Page ``` **直接应用 BEM 类:** ```tsx import Link from 'next/link'; // Apply HeroUI's BEM classes directly to any element Dashboard ``` **创建自定义包装组件:** ```tsx // Custom wrapper component const CTAButton = ({ intent = 'primary-cta', children, ref, ...props }: CTAButtonProps) => { const variantMap = { 'primary-cta': 'primary', 'secondary-cta': 'secondary', 'minimal': 'ghost' }; return ( ); }; ``` **使用 Tailwind Variants 扩展:** ```tsx import { Button } from '@heroui/react'; import { buttonVariants, tv } from '@heroui/styles'; // 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 ); } ``` 示例:`pages/index.tsx` ```tsx import {Button} from "@heroui/react"; export default function HomePage() { return (
); } ```
HeroUI v3 无需 Provider。安装并导入样式后,组件即可直接使用。 ### 3. 区域设置(可选) 为了与 Next.js 集成,请确保服务端的区域设置与客户端一致。 在根布局中,确定用户的首选语言,并在 `` 元素上设置 `lang` 和 `dir` 属性。 ```tsx // app/layout.tsx import {headers} from 'next/headers'; import {isRTL} from '@heroui/react'; import {ClientProviders} from './provider'; export default async function RootLayout({children}) { // Get the user's preferred language from the Accept-Language header. // You could also get this from a database, URL param, etc. const acceptLanguage = (await headers()).get('accept-language'); const lang = acceptLanguage?.split(/[,;]/)[0] || 'en-US'; return ( {children} ); } ``` 创建 `app/provider.tsx`,其中应渲染一个 `I18nProvider`,用于设置 React Aria 所使用的区域设置。 ```tsx // app/provider.tsx "use client"; import {I18nProvider} from '@heroui/react'; export function ClientProviders({lang, children}) { return ( {children} ); } ``` 如果你使用了带 nonce 的 [内容安全策略](https://developer.mozilla.org/en-US/docs/Web/HTTP/Guides/CSP)(CSP),请在文档的 head 中添加 `` 标签,并将其 content 属性设置为生成的 nonce 值。React Aria 会自动从该标签读取 nonce。 ## Vite ### 1. 创建 Vite 项目 ```bash npx heroui-cli@latest init ``` 当出现提示时,选择 **Vite** 模板。然后进入新创建的文件夹并安装依赖(例如 `pnpm install`)。 ### 2. 使用你的第一个 HeroUI 组件 示例:`src/App.tsx` ```tsx import {Button} from "@heroui/react"; function App() { return (
); } export default App; ``` HeroUI v3 无需 Provider。安装并导入样式后,组件即可直接使用。 ## 下一步 * [快速入门](/docs/react/getting-started/quick-start) — 最快上手的方式 * [主题](/docs/react/getting-started/theming) — 自定义颜色和设计令牌 * [组件](/docs/react/components) — 探索所有可用的组件
# 快速入门 **Category**: react **URL**: https://www.heroui.com/cn/docs/react/getting-started/quick-start **Source**: https://raw.githubusercontent.com/heroui-inc/heroui/refs/heads/v3/apps/docs/content/docs/cn/react/getting-started/(overview)/quick-start.mdx > 只需几分钟即可开始使用 HeroUI v3 ## 环境要求 * [React 19+](https://reactjs.org/) * [Tailwind CSS v4](https://tailwindcss.com/docs/installation/framework-guides) ## 快速安装 \` 作为最小冒烟测试,确认样式已正确生效。 完成后,请总结你做出的变更,并告诉我如何启动开发服务器。`} > **想让 AI 助手代劳?** 在你的编辑器中安装 [HeroUI MCP Server](/docs/react/getting-started/mcp-server),然后把上面的提示词粘贴给 AI 助手——它会分析你的项目并自动完成全部配置。 安装 HeroUI 及其所需依赖: ```bash npm i @heroui/styles @heroui/react ``` ```bash pnpm add @heroui/styles @heroui/react ``` ```bash yarn add @heroui/styles @heroui/react ``` ```bash bun add @heroui/styles @heroui/react ``` ## 导入样式 将以下内容添加到你的主 CSS 文件 `globals.css`: ```css @import "tailwindcss"; @import "@heroui/styles"; /* [!code highlight]*/ ``` 导入顺序很重要。请务必先导入 `tailwindcss`。 ## 使用组件 ```tsx import { Button } from '@heroui/react'; function App() { return ( ); } ``` ## 下一步 * [主题](/themes) — 创建并分享你自己的主题 * [浏览组件](/docs/react/components) — 查看所有可用的组件 * [学习样式](/docs/handbook/styling) — 使用 Tailwind CSS 进行自定义 * [探索组合模式](/docs/handbook/composition) — 掌握复合组件 # Agent Skills **Category**: react **URL**: https://www.heroui.com/cn/docs/react/getting-started/agent-skills **Source**: https://raw.githubusercontent.com/heroui-inc/heroui/refs/heads/v3/apps/docs/content/docs/cn/react/getting-started/(ui-for-agents)/agent-skills.mdx > 让 AI 助手能够使用 HeroUI v3 组件来构建 UI HeroUI Skills 为你的 AI 助手提供关于 HeroUI v3 组件、模式与最佳实践的全面知识。 ### 安装 ```bash curl -fsSL https://heroui.com/install | bash -s heroui-react ``` 或者使用 skills 包: ```bash npx skills add heroui-inc/heroui ``` 支持 Claude Code、Cursor、OpenCode 等。 ### 使用方法 Skills 会被你的 AI 助手 **自动发现**,你也可以通过 `/heroui-react` 命令直接调用。 只需让你的 AI 助手: * 使用 HeroUI v3 构建组件 * 使用 HeroUI 组件创建页面 * 自定义主题和样式 * 查阅组件文档 对于更复杂的使用场景,请使用 [MCP 服务器](/docs/react/getting-started/mcp-server),它提供对组件文档与源代码的实时访问。 ### 包含的内容 * HeroUI v3 安装指南 * 所有 HeroUI v3 组件,包含 props、示例与使用模式 * 主题与样式指南 * 设计原则与组合模式 ### 结构 ``` skills/heroui-react/ ├── SKILL.md # Main skill documentation ├── LICENSE.txt # Apache License 2.0 └── scripts/ # Utility scripts ├── list_components.mjs ├── get_component_docs.mjs ├── get_source.mjs ├── get_styles.mjs ├── get_theme.mjs └── get_docs.mjs ``` ### 相关文档 * [Agent Skills 规范](https://agentskills.io/home) — 了解 Agent Skills 的格式 * [Claude Agent Skills](https://platform.claude.com/docs/en/agents-and-tools/agent-skills/overview) — Claude 的 Skills 文档 * [Cursor Skills](https://cursor.com/docs/context/skills) — 在 Cursor 中使用 Skills * [OpenCode Skills](https://opencode.ai/docs/skills) — 在 OpenCode 中使用 Skills # AGENTS.md **Category**: react **URL**: https://www.heroui.com/cn/docs/react/getting-started/agents-md **Source**: https://raw.githubusercontent.com/heroui-inc/heroui/refs/heads/v3/apps/docs/content/docs/cn/react/getting-started/(ui-for-agents)/agents-md.mdx > 为 AI 编码代理下载 HeroUI v3 React 文档 将 HeroUI v3 React 文档直接下载到你的项目中,供 AI 助手参考。 **注意:** `agents-md` 命令专门用于 HeroUI React v3。其他 CLI 命令(如 `add`、`init`、`upgrade` 等)目前仍用于 HeroUI v2。 ### 用法 ```bash npx heroui-cli@latest agents-md --react ``` 或者指定输出文件: ```bash npx heroui-cli@latest agents-md --react --output AGENTS.md ``` ### 功能说明 * 将最新的 HeroUI v3 React 文档下载到 `.heroui-docs/react/` * 在 `AGENTS.md` 或 `CLAUDE.md` 中生成索引 * 包含用于代码示例的 demo 文件 * 自动将 `.heroui-docs/` 添加到 `.gitignore` ### 选项 * `--react` — 仅下载 React 文档 * `--output ` — 目标文件(例如 `AGENTS.md`,或 `AGENTS.md CLAUDE.md`) * `--ssh` — 使用 SSH 进行 git clone ### 环境要求 * Tailwind CSS >= v4 * React >= 19.0.0 * `@heroui/react >= 3.0.0` 或 `@latest` ### 相关文档 * [AGENTS.md](https://agents.md/) — 了解面向编码代理的 AGENTS.md 格式 * [CLAUDE.md](https://code.claude.com/docs/en/best-practices#write-an-effective-claude-md) — Claude 对应版本的 AGENTS.md * [AGENTS.md vs Skills](https://vercel.com/blog/agents-md-outperforms-skills-in-our-agent-evals) — AGENTS.md 的性能表现 # LLMs.txt **Category**: react **URL**: https://www.heroui.com/cn/docs/react/getting-started/llms-txt **Source**: https://raw.githubusercontent.com/heroui-inc/heroui/refs/heads/v3/apps/docs/content/docs/cn/react/getting-started/(ui-for-agents)/llms-txt.mdx > 让 Claude、Cursor、Windsurf 等 AI 助手理解 HeroUI v3 我们提供 [LLMs.txt](https://llmstxt.org/) 文件,让 AI 编码助手可以访问 HeroUI v3 文档。 ## 可用文件 **核心文档:** * [/react/llms.txt](/react/llms.txt) — React 文档的快速参考索引 * [/react/llms-full.txt](/react/llms-full.txt) — 完整的 HeroUI React 文档 **适用于上下文窗口有限的场景:** * [/react/llms-components.txt](/react/llms-components.txt) — 仅包含组件文档 * [/react/llms-patterns.txt](/react/llms-patterns.txt) — 常见模式与代码片段 **全平台:** * [/llms.txt](/llms.txt) — 快速参考索引(React + Native) * [/llms-full.txt](/llms-full.txt) — 完整文档(React + Native) * [/llms-components.txt](/llms-components.txt) — 全部组件文档 * [/llms-patterns.txt](/llms-patterns.txt) — 全部模式与代码片段 ## 集成 **Claude Code:** 让 Claude 参考文档: ``` Use HeroUI React documentation from https://heroui.com/react/llms.txt ``` 或者添加到你项目中的 `.claude` 文件以自动加载。 **Cursor:** 使用 `@Docs` 功能: ``` @Docs https://heroui.com/react/llms-full.txt ``` [了解更多](https://docs.cursor.com/context/@-symbols/@-docs) **Windsurf:** 添加到你的 `.windsurfrules` 文件: ``` #docs https://heroui.com/react/llms-full.txt ``` [了解更多](https://docs.codeium.com/windsurf/memories#memories-and-rules) **其他 AI 工具:** 大多数 AI 助手都可以通过 URL 引用文档。只需提供: ``` https://heroui.com/react/llms.txt ``` **针对特定组件的文档:** ``` https://heroui.com/react/llms-components.txt ``` **针对模式与最佳实践:** ``` https://heroui.com/react/llms-patterns.txt ``` ## 参与贡献 发现 AI 生成的代码有问题?欢迎在 [GitHub](https://github.com/heroui-inc/heroui) 上帮助我们改进 LLMs.txt 文件。 # MCP 服务器 **Category**: react **URL**: https://www.heroui.com/cn/docs/react/getting-started/mcp-server **Source**: https://raw.githubusercontent.com/heroui-inc/heroui/refs/heads/v3/apps/docs/content/docs/cn/react/getting-started/(ui-for-agents)/mcp-server.mdx > 直接在你的 AI 助手中访问 HeroUI v3 文档 HeroUI MCP 服务器让 AI 助手可以直接访问 HeroUI v3 组件文档,从而更轻松地在 AI 驱动的开发环境中使用 HeroUI 进行构建。 MCP 服务器目前仅支持 **@heroui/react v3**,并使用 [stdio 传输](https://modelcontextprotocol.io/specification/2025-06-18/basic/transports#stdio)。已在 npm 上以 `@heroui/react-mcp` 发布。源代码请查看 [GitHub](https://github.com/heroui-inc/heroui-mcp)。 随着我们向 HeroUI v3 添加更多组件,它们也将在 MCP 服务器中可用。 ## 快速设置 ### Cursor
Install in Cursor
或者手动添加到 **Cursor Settings** → **Tools** → **MCP Servers**: ```json title=".cursor/mcp.json" { "mcpServers": { "heroui-react": { "command": "npx", "args": ["-y", "@heroui/react-mcp@latest"] } } } ``` 或者,将以下内容添加到你的 `~/.cursor/mcp.json` 文件。更多信息请参阅 [Cursor 文档](https://cursor.com/docs/context/mcp)。 ### Claude Code 在终端中运行此命令: ```bash claude mcp add heroui-react -- npx -y @heroui/react-mcp@latest ``` 或者手动添加到你项目的 `.mcp.json` 文件: ```json title=".mcp.json" { "mcpServers": { "heroui-react": { "command": "npx", "args": ["-y", "@heroui/react-mcp@latest"] } } } ``` 添加配置后,重启 Claude Code 并运行 `/mcp`,即可在列表中看到 HeroUI MCP 服务器。如果你看到 **Connected**,就可以开始使用了。 更多详情请参阅 [Claude Code MCP 文档](https://docs.claude.com/en/docs/claude-code/mcp)。 ### Windsurf 将 HeroUI 服务器添加到你项目的 `.windsurf/mcp.json` 配置文件: ```json title=".windsurf/mcp.json" { "mcpServers": { "heroui-react": { "command": "npx", "args": ["-y", "@heroui/react-mcp@latest"] } } } ``` 添加配置后,重新启动 Windsurf 以激活 MCP 服务器。 更多详情请参阅 [Windsurf MCP 文档](https://docs.windsurf.com/windsurf/cascade/mcp)。 ### Zed 将 HeroUI 服务器添加到你的 `settings.json` 配置文件。通过命令面板打开设置(`zed: open settings`),或使用 `Cmd-,`(Mac)/ `Ctrl-,`(Linux): ```json title="settings.json" { "context_servers": { "heroui-react": { "command": "npx", "args": ["-y", "@heroui/react-mcp@latest"], "env": {} } } } ``` 添加配置后,重新启动 Zed 并打开 Agent Panel 设置视图。检查 heroui 服务器旁边的指示点是否为绿色,且 tooltip 显示为 "Server is active"。 更多详情请参阅 [Zed MCP 文档](https://zed.dev/docs/ai/mcp)。 ### VS Code 要在 VS Code 中通过 GitHub Copilot 配置 MCP,请将 HeroUI 服务器添加到项目的 `.vscode/mcp.json` 配置文件: ```json title=".vscode/mcp.json" { "servers": { "heroui-react": { "type": "stdio", "command": "npx", "args": ["-y", "@heroui/react-mcp@latest"] } } } ``` 添加配置后,打开 `.vscode/mcp.json`,然后点击 heroui-react 服务器旁边的 **Start**。 更多详情请参阅 [VS Code MCP 文档](https://code.visualstudio.com/docs/copilot/customization/mcp-servers)。 ### Codex 将 HeroUI 服务器添加到你的 `~/.codex/config.toml`(或项目级的 `.codex/config.toml`): ```toml title="config.toml" [mcp_servers.heroui-react] command = "npx" args = ["-y", "@heroui/react-mcp@latest"] ``` 添加配置后,重启 Codex 并在 TUI 中运行 `/mcp`,以验证服务器是否处于活动状态。 更多详情请参阅 [Codex MCP 文档](https://developers.openai.com/codex/mcp)。 ### OpenCode 将 HeroUI 服务器添加到你项目的 `opencode.json` 配置文件: ```json title="opencode.json" { "$schema": "https://opencode.ai/config.json", "mcp": { "heroui-react": { "type": "local", "command": ["npx", "-y", "@heroui/react-mcp@latest"] } } } ``` 添加配置后,重新启动 OpenCode 以激活 MCP 服务器。 更多详情请参阅 [OpenCode MCP 文档](https://open-code.ai/docs/en/mcp-servers)。 ## 用法 配置完成后,可以这样询问你的 AI 助手: * “帮我在 Next.js / Vite / Astro 应用中安装 HeroUI v3” * “显示所有 HeroUI 组件” * “Button 组件有哪些 props?” * “给我一个使用 Card 组件的示例” * “获取 Button 组件的源代码” * “显示 Card 组件的 CSS 样式” * “深色模式下有哪些主题变量?” ### 自动更新 MCP 服务器可以帮助你升级到最新的 HeroUI 版本: ```bash "Hey Cursor, update HeroUI to the latest version" ``` 你的 AI 助手会自动完成以下事项: * 将你当前的版本与最新发布的版本进行比较 * 查看变更日志,了解破坏性变更 * 将必要的代码更新应用到你的项目中 无论是更新到最新的稳定版还是预发布版,这一流程都适用于任何版本升级。 ## 可用工具 MCP 服务器为 AI 助手提供以下工具: | 工具 | 描述 | | ----------------------------- | ------------------------------------------------------------------------------------ | | `list_components` | 列出所有可用的 HeroUI v3 组件 | | `get_component_docs` | 获取一个或多个组件的完整文档,包括组件结构、props、示例和使用模式 | | `get_component_source_code` | 获取组件的 React/TypeScript 源代码(.tsx 文件) | | `get_component_source_styles` | 查看组件的 CSS 样式(.css 文件) | | `get_theme_variables` | 获取颜色、排版、间距相关的主题变量,支持浅色/深色模式 | | `get_docs` | 浏览完整的 HeroUI v3 文档,包括指南和设计原则(如需安装说明,请使用路径 `/docs/react/getting-started/quick-start`) | ## 故障排查 **环境要求:** Node.js 22 或更高版本。使用 `npx` 时会自动下载该包。 **需要帮助?** [GitHub Issues](https://github.com/heroui-inc/heroui-mcp/issues) | [Discord 社区](https://discord.gg/heroui) ## 链接 * [npm 包](https://www.npmjs.com/package/@heroui/react-mcp) * [GitHub 仓库](https://github.com/heroui-inc/heroui-mcp) * [贡献指南](https://github.com/heroui-inc/heroui-mcp/blob/main/CONTRIBUTING.md)