Styling
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
classNamein 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:
import { Button } from 'heroui-native';
<Button className="bg-accent px-6 py-3 rounded-lg">
<Button.Label>Custom Button</Button.Label>
</Button>Using style: Components also accept inline styles via the style prop:
import { Button } from 'heroui-native';
<Button style={{ backgroundColor: '#8B5CF6', paddingHorizontal: 24 }}>
<Button.Label>Styled Button</Button.Label>
</Button>Render Props
Use a render function to access component state and customize content dynamically:
import { RadioGroup, cn } from 'heroui-native';
<RadioGroup value={value} onValueChange={setValue}>
<RadioGroup.Item value="option1">
{({ isSelected, isInvalid, isDisabled }) => (
<>
<RadioGroup.Label
className={cn(
"text-foreground",
isSelected && "text-accent font-semibold"
)}
>
Option 1
</RadioGroup.Label>
<RadioGroup.Indicator
className={cn(
"border-2 rounded-full",
isSelected && "border-accent bg-accent"
)}
>
{isSelected && <CustomIcon />}
</RadioGroup.Indicator>
</>
)}
</RadioGroup.Item>
</RadioGroup>Creating Wrapper Components
Create reusable custom components using tailwind-variants—a Tailwind CSS first-class variant API:
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 text-white',
secondary: 'bg-gray-200',
danger: 'bg-red-500 text-white',
},
},
defaultVariants: {
intent: 'primary',
},
});
type CustomButtonVariants = VariantProps<typeof customButtonVariants>;
interface CustomButtonProps
extends Omit<ButtonRootProps, 'className' | 'variant'>,
CustomButtonVariants {
className?: string;
}
export function CustomButton({
intent,
className,
children,
...props
}: CustomButtonProps) {
return (
<Button
className={customButtonVariants({ intent, className })}
{...props}
>
<Button.Label>{children}</Button.Label>
</Button>
);
}Responsive Design
HeroUI Native supports Tailwind's responsive breakpoint system via Uniwind. 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
import { Button } from 'heroui-native';
import { View, Text } from 'react-native';
<View className="px-4 sm:px-6 lg:px-8 py-6 sm:py-8">
<Text className="text-2xl sm:text-3xl lg:text-4xl font-bold mb-4 sm:mb-6">
Responsive Heading
</Text>
<Button className="px-3 sm:px-4 lg:px-6">
<Button.Label className="text-sm sm:text-base lg:text-lg">
Responsive Button
</Button.Label>
</Button>
</View>Responsive Layouts
import { View, Text } from 'react-native';
<View className="flex-row flex-wrap">
{/* Mobile: 1 column, Tablet: 2 columns, Desktop: 3 columns */}
<View className="w-full sm:w-1/2 lg:w-1/3 p-2">
<View className="bg-accent p-4 rounded-lg">
<Text className="text-accent-foreground">Item 1</Text>
</View>
</View>
</View>Default breakpoints:
sm: 640pxmd: 768pxlg: 1024pxxl: 1280px2xl: 1536px
For custom breakpoints and more details, see the Uniwind breakpoints documentation.
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:
import { cn } from 'heroui-native';
import { View } from 'react-native';
function MyComponent({ className, isActive }) {
return (
<View
className={cn(
'bg-background p-4 rounded-lg',
'border border-divider',
isActive && 'bg-accent',
className
)}
/>
);
}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:
// 'bg-accent' overrides 'bg-background'
cn('bg-background p-4', 'bg-accent');
// Result: 'p-4 bg-accent'useThemeColor Hook
Quick access to theme colors in hex format for use with the style prop:
import { useThemeColor } from 'heroui-native';
import { View, Text } from 'react-native';
function MyComponent() {
const accentColor = useThemeColor('accent');
const dangerColor = useThemeColor('danger');
return (
<View style={{ borderColor: accentColor }}>
<Text style={{ color: dangerColor }}>Error message</Text>
</View>
);
}Type signature:
useThemeColor(themeColor: ThemeColor): stringAvailable theme colors include: background, foreground, surface, accent, default, success, warning, danger, and all their variants (hover, soft, etc.).