apps/docs/content/docs/en/native/releases/rc-1.mdx
RC 1 marks the first Release Candidate for HeroUI Native, signaling that the library is approaching production readiness. This release introduces the Alert compound component with accessibility-first design and status variants, extracts Radio into a standalone component with dual-mode operation, and adds the animated Select.TriggerIndicator subcomponent. It also delivers a lightweight HeroUINativeProviderRaw for bundle optimization, a new disableFullWindowOverlay prop for iOS debugging, unified styles prop support across six components, and a theme refactor that replaces calculated surface colors with explicit theme-defined variables. Several critical bug fixes—including InputOTP in BottomSheet, toast text clipping, and element inspector compatibility—round out the release.
Update to the latest version:
<Tabs items={["npm", "pnpm", "yarn", "bun"]}> <Tab value="npm">
npm i heroui-native
This release introduces 1 new component:
The Alert component provides accessible alert messaging with built-in support for five status variants: default, accent, success, warning, and danger. It follows the compound component pattern with Alert.Indicator, Alert.Content, Alert.Title, and Alert.Description sub-components, giving developers full control over layout and customization. The primitive layer provides role="alert", aria-labelledby, and aria-describedby accessibility associations automatically.
<NativeVideoPlayerView target="component" slug="alert" srcLight="https://heroui-assets.nyc3.cdn.digitaloceanspaces.com/docs/native/components/videos/alert-docs-light.mp4" srcDark="https://heroui-assets.nyc3.cdn.digitaloceanspaces.com/docs/native/components/videos/alert-docs-dark.mp4" />
Features:
useStatusColor hookrole="alert", aria-labelledby, and aria-describedbyasChild slot support on all sub-componentsclassName prop support on all partsUsage:
import { Alert } from "heroui-native";
export function Example() {
return (
<Alert status="success">
<Alert.Indicator />
<Alert.Content>
<Alert.Title>Payment successful</Alert.Title>
<Alert.Description>
Your payment has been processed successfully.
</Alert.Description>
</Alert.Content>
</Alert>
);
}
For complete documentation and examples, see the Alert component page.
Related PR: #284
The Select component now includes a TriggerIndicator subcomponent that displays an animated chevron icon to visually indicate the open/close state. The indicator rotates smoothly when the select opens or closes, using React Native Reanimated spring physics.
Features:
animation prop with rotation values and spring configiconProps (size, color)Usage:
import { Select } from "heroui-native";
<Select>
<Select.Trigger>
<Select.Value placeholder="Select an option" />
<Select.TriggerIndicator />
</Select.Trigger>
<Select.Portal>
<Select.Content>
</Select.Content>
</Select.Portal>
</Select>
Related PR: #274
The Toast component styling has been refactored to replace the border-based padding approach with proper padding and vertical placeholder views, improving content visibility when toasts stack.
Improvements:
border-[16px] padding workaround with proper p-4 paddinguseVerticalPlaceholderStyles hook for placeholder view stylingshadow-overlay tokenThis refactor ensures content remains properly hidden when toasts of different heights stack together, while providing a more maintainable and predictable styling approach.
Related PR: #229
The Dialog component's popup animation timing has been fixed when closing via gesture. The progress value is now properly sequenced with delays to ensure the closing animation completes before resetting.
Improvements:
progress.set(2) call when isOpen becomes falseRelated PR: #277
The theme system has been refactored to replace calculated surface colors with explicit theme-defined variables, providing more control and consistency across themes.
Improvements:
surface-secondary and surface-tertiary (with foregrounds) are now defined explicitly in each theme (alpha, lavender, mint, sky, variables.css)var(--surface-secondary) and var(--surface-tertiary) instead of color-mix calculationson-surface, on-surface-secondary, and on-surface-tertiary palettes from theme.cssThis change gives theme authors direct control over surface color values rather than relying on color-mix calculations, resulting in more predictable and consistent surface styling across all themes.
Related PR: #281
styles Prop for Multiple ComponentsSix components now support the unified styles prop for slot-based styling, providing a consistent pattern for applying styles to component internals.
Supported components:
container and separator slotscontainer and text slotscontainer and text slotstext and asterisk slots (also fixed style prop handling)container and ripple slots (replaces containerStyle and rippleStyle)wrapper and content slotsNew Capability:
import { Accordion, Label } from "heroui-native";
// Apply styles to specific slots
<Label styles={{ text: { fontSize: 18 }, asterisk: { color: "red" } }} isRequired>
Username
</Label>
<Accordion
styles={{
container: { borderRadius: 12 },
separator: { backgroundColor: "gray" },
}}
>
</Accordion>
All changes maintain backward compatibility with existing style props and properly merge styles when both are provided.
Related PR: #271
disableFullWindowOverlay PropPortal-based components now support a disableFullWindowOverlay prop that enables React Native element inspector support on iOS during development.
Supported components:
BottomSheet.PortalDialog.PortalPopover.PortalSelect.PortalToastProviderNew Capability:
import { Dialog } from "heroui-native";
// Enable element inspector support on iOS
<Dialog>
<Dialog.Portal disableFullWindowOverlay>
<Dialog.Overlay />
<Dialog.Content>
</Dialog.Content>
</Dialog.Portal>
</Dialog>
On iOS, FullWindowOverlay uses a separate native window that blocks the React Native element inspector. Setting disableFullWindowOverlay to true renders content in the main window instead, enabling the inspector during development. The tradeoff is that overlays will no longer appear above native modals or the keyboard. This prop has no effect on Android.
For Toast, the prop is passed via config.toast when using HeroUINativeProvider.
Related PR: #283
A new lightweight provider variant, HeroUINativeProviderRaw, excludes ToastProvider and PortalHost to give consumers full control over which dependencies are bundled.
New Capability:
import { HeroUINativeProviderRaw } from "heroui-native/provider-raw";
// Lightweight provider without Toast and Portal dependencies
export function App() {
return (
<HeroUINativeProviderRaw>
</HeroUINativeProviderRaw>
);
}
This makes react-native-screens, @gorhom/bottom-sheet, and react-native-svg fully optional dependencies. The raw provider includes only SafeAreaListener, GlobalAnimationSettingsProvider, and TextComponentProvider. Consumers who need toast or portal features can compose them manually.
Related PR: #285
variant PropThe Select.Trigger component now supports a variant prop with "default" and "unstyled" options, enabling better composition with custom trigger components like Button.
New Capability:
import { Button, Select } from "heroui-native";
// Default variant (pre-styled trigger)
<Select>
<Select.Trigger variant="default">
<Select.Value placeholder="Choose..." />
<Select.TriggerIndicator />
</Select.Trigger>
</Select>
// Unstyled variant for custom compositions
<Select>
<Select.Trigger variant="unstyled">
<Button>
<Select.Value placeholder="Choose..." />
<Select.TriggerIndicator />
</Button>
</Select.Trigger>
</Select>
Related PR: #274
The ControlField component now supports a "radio" variant in ControlField.Indicator, rendering a standalone Radio component alongside the existing "switch" and "checkbox" variants.
New Capability:
import { ControlField } from "heroui-native";
<ControlField>
<ControlField.Indicator variant="radio" />
<ControlField.Label>Radio option</ControlField.Label>
</ControlField>
Related PR: #286
styles PropThe PressableFeedback Ripple component's individual style props (containerStyle and rippleStyle) have been replaced with a unified styles prop.
Migration:
Update all instances of individual style props to the unified styles prop:
// Before
<PressableFeedback.Ripple
containerStyle={{ borderRadius: 8 }}
rippleStyle={{ backgroundColor: "blue" }}
/>
// After
<PressableFeedback.Ripple
styles={{
container: { borderRadius: 8 },
ripple: { backgroundColor: "blue" },
}}
/>
Related PR: #271
Select.Trigger now defaults to variant="default", which applies default container styles (flex-row items-center justify-between h-12 px-4 rounded-2xl bg-surface shadow-surface). Users with custom styled triggers need to add variant="unstyled" to prevent default styles from being applied.
Migration:
// Before (custom styled trigger)
<Select.Trigger className="custom-trigger-styles">
</Select.Trigger>
// After (add variant="unstyled" to preserve custom styling)
<Select.Trigger variant="unstyled" className="custom-trigger-styles">
</Select.Trigger>
Related PR: #274
The on-surface, on-surface-secondary, and on-surface-tertiary CSS variables and their hover/focus variants have been removed from the base theme. Surface secondary and tertiary colors are now defined explicitly in each theme file.
Migration:
If you reference on-surface, on-surface-secondary, or on-surface-tertiary variables in custom styles, replace them with the appropriate surface foreground variables defined in your theme.
/* Before */
color: var(--on-surface);
color: var(--on-surface-secondary);
/* After */
color: var(--surface-foreground);
color: var(--surface-secondary-foreground);
Related PR: #281
RadioGroup.Indicator and RadioGroup.IndicatorThumb have been removed in favor of the new standalone Radio component. The related types RadioGroupIndicatorProps, RadioGroupIndicatorThumbProps, and RadioGroupIndicatorThumbAnimation are also removed from exports.
Migration:
Replace all RadioGroup.Indicator and RadioGroup.IndicatorThumb usages with the Radio component:
// Before
import { RadioGroup } from "heroui-native";
<RadioGroup>
<RadioGroup.Item value="option1">
<RadioGroup.Indicator>
<RadioGroup.IndicatorThumb />
</RadioGroup.Indicator>
<RadioGroup.Label>Option 1</RadioGroup.Label>
</RadioGroup.Item>
</RadioGroup>
// After
import { Radio, RadioGroup } from "heroui-native";
<RadioGroup>
<RadioGroup.Item value="option1">
<Radio>
<Radio.Indicator>
<Radio.IndicatorThumb />
</Radio.Indicator>
</Radio>
<RadioGroup.Label>Option 1</RadioGroup.Label>
</RadioGroup.Item>
</RadioGroup>
Related PR: #286
This release includes fixes for the following issues:
Issue #229: Fixed InputOTP not working inside BottomSheet. The InputOTP component now functions correctly when rendered within a BottomSheet overlay, resolving input focus and interaction issues that previously prevented OTP entry in bottom sheet contexts.
Issue #265: Fixed the first letter of Toast description text being clipped. The toast styling refactor replaces the border-based padding approach with proper padding and placeholder views, ensuring all text content is fully visible regardless of toast stacking configuration.
Issue #272: Fixed FullWindowOverlay blocking the React Native element inspector on iOS. The new disableFullWindowOverlay prop on portal components allows developers to render overlay content in the main window during development, restoring element inspector functionality.
Related PRs:
The following documentation pages have been updated to reflect the changes in this release:
Thanks to everyone who contributed to this release!