# 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
$450Living 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 (
);
}
```
## 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 (
);
}
```
## 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')}
/>
InformationAdditional 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 ContentMain 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 (
);
}
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';
ProfileSecurityContentContent
```
### 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
SuccessJD
```
### 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 StartedLearn 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 StartedLearn 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:**