# 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)
# 动画 **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)