apps/docs/content/docs/native/releases/beta-13.mdx
Beta 13 introduces the TextArea component for multiline text input, adds Button outline variant, and exports style class names for all components. This release also includes significant improvements to Tabs with better animations and clearer variant naming, decomposes form components into standalone primitives for better flexibility, refactors popup animation system for improved consistency and Android compatibility, and fixes critical issues including Chinese character input handling, theme color calculations, Uniwind Pro compatibility, BottomSheet opening issues, and tree-shaking support. These updates enhance developer experience and component reliability across the library.
Update to the latest version:
<Tabs items={["npm", "pnpm", "yarn", "bun"]}> <Tab value="npm">
npm i heroui-native@beta
Experience all the Beta 13 improvements in action with our preview app! You can explore the new TextArea and CloseButton components, along with Button outline variant, Tabs improvements, granular exports, and all the bug fixes directly on your device.
Make sure you have the latest version of Expo Go installed on your mobile device.
Option 1: Scan the QR Code
Use your device's camera or Expo Go app to scan:
<div className="flex justify-center my-6"> </div>Note for Android users: If scanning the QR code with your device's camera or other scanner apps redirects to a browser and shows a 404 error, open Expo Go first and use its built-in QR scanner instead.
Option 2: Click the Link
This will automatically open the app in Expo Go if it's installed on your device.
This release introduces 3 new essential components:
The TextArea component provides a complete solution for multiline text input scenarios, such as comments, messages, descriptions, and longer form fields. It features seamless integration with TextField for complete form structure, validation state support, and customizable variants for different visual contexts.
<NativeVideoPlayerView srcLight="https://heroui-assets.nyc3.cdn.digitaloceanspaces.com/docs/native/components/videos/text-area-docs-light.mp4" srcDark="https://heroui-assets.nyc3.cdn.digitaloceanspaces.com/docs/native/components/videos/text-area-docs-dark.mp4" />
Features:
Usage:
import { Description, Label, TextArea, TextField } from "heroui-native";
export function Example() {
return (
<TextField>
<Label>Message</Label>
<TextArea placeholder="Enter your message here..." />
<Description>Please provide as much detail as possible.</Description>
</TextField>
);
}
For complete documentation and examples, see the TextArea component page.
Related PR: #254
The Input component is now available as a standalone component, providing single-line text input functionality with styled border and background. Previously available only as TextField.Input, Input can now be used independently or integrated with form components like TextField and ControlField.
<NativeVideoPlayerView srcLight="https://heroui-assets.nyc3.cdn.digitaloceanspaces.com/docs/native/components/videos/input-docs-light.mp4" srcDark="https://heroui-assets.nyc3.cdn.digitaloceanspaces.com/docs/native/components/videos/input-docs-dark.mp4" />
Features:
Usage:
import { Description, Input, Label, TextField } from "heroui-native";
export function Example() {
return (
<TextField>
<Label>Email</Label>
<Input placeholder="Enter your email..." />
<Description>We'll never share your email.</Description>
</TextField>
);
}
For complete documentation and examples, see the Input component page.
Related PR: #247
The CloseButton component provides a reusable solution for closing dialogs, modals, popovers, and other overlay components. It features consistent styling across all overlay components, customizable icon properties, and seamless integration with Dialog, Popover, Select, and Bottom Sheet components.
<NativeVideoPlayerView srcLight="https://heroui-assets.nyc3.cdn.digitaloceanspaces.com/docs/native/components/videos/close-button-docs-light.mp4" srcDark="https://heroui-assets.nyc3.cdn.digitaloceanspaces.com/docs/native/components/videos/close-button-docs-dark.mp4" />
Features:
Usage:
import { CloseButton } from "heroui-native";
// Standalone usage
<CloseButton onPress={handleClose} />
// As part of Dialog, Popover, Select, Bottom Sheet
<Dialog>
<Dialog.Close />
</Dialog>
For complete documentation and examples, see the CloseButton component page.
Related PR: #237
The Tabs component now includes a new Separator subcomponent that provides animated visibility control between tab triggers. This allows developers to create visual separators that automatically show or hide based on the active tab state.
Features:
betweenValues propUsage:
import { Tabs } from "heroui-native";
<Tabs value={activeTab} onValueChange={setActiveTab}>
<Tabs.List>
<Tabs.ScrollView>
<Tabs.Indicator />
<Tabs.Trigger value="general">
<Tabs.Label>General</Tabs.Label>
</Tabs.Trigger>
<Tabs.Separator betweenValues={["general", "notifications"]} />
<Tabs.Trigger value="notifications">
<Tabs.Label>Notifications</Tabs.Label>
</Tabs.Trigger>
</Tabs.ScrollView>
</Tabs.List>
</Tabs>
Related PR: #228
The Button component now includes an outline variant that provides a bordered style with transparent background, offering more visual variety for button designs.
Improvements:
outline variant for bordered button styleUsage:
import { Button } from "heroui-native";
<Button variant="outline">Outline Button</Button>
Related PR: #235
The Tabs component's indicator animation has been refactored to use translateX transforms instead of width/height animations, resulting in smoother and more performant tab indicator transitions.
Improvements:
translateX transformsRelated PR: #227
The Popover component has been improved with better arrow sizing and visual connection to the popover content, creating a more cohesive visual appearance.
Improvements:
Related PR: #243
Form components have been decomposed into standalone primitives, providing developers with more flexibility and better control over component composition.
Improvements:
Related PR: #247
The Input component now includes platform-specific shadow styling for Android, ensuring consistent visual appearance across platforms.
Improvements:
Related PR: #248
The animation system for popup components (Popover, Select, Dialog, BottomSheet) has been refactored to improve entering/exiting animation logic, overlay composition, and content animation handling. This change standardizes animation behavior across all popup components and fixes Android pointer events issues.
Improvements:
Related PR: #263
The library now provides granular exports for each component, allowing developers to reduce bundle size by importing only the components they need.
New Capability:
// 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 componentheroui-native/[component-name] - Individual componentsheroui-native/portal - Portal utilitiesheroui-native/utils - Utility functionsheroui-native/hooks - Custom hooksRelated PR: #233
All components now export their style class names, enabling developers to reference component styles programmatically and create custom styling solutions.
New Capability:
import { buttonClassNames } from "heroui-native";
// Access component class names programmatically
const customStyles = {
base: buttonClassNames.base,
variant: buttonClassNames.variant,
};
This enhancement provides developers with programmatic access to component class names, enabling advanced styling scenarios and custom theme implementations.
Related PR: #252
Related PR: #246
The Tabs component's variant prop has been renamed from pill/line to primary/secondary for better clarity and consistency with other components.
Migration:
Update all instances of Tabs variant prop:
// Before
<Tabs variant="pill">
</Tabs>
<Tabs variant="line">
</Tabs>
// After
<Tabs variant="primary">
</Tabs>
<Tabs variant="secondary">
</Tabs>
Available options:
"primary" - Primary variant (previously "pill")"secondary" - Secondary variant (previously "line")Related PR: #236
The Tabs component's indicator animation has been refactored to use translateX transforms instead of left positioning for GPU-accelerated performance. This change improves animation performance but requires updates to custom animation configurations.
Migration:
If you have customized the Tabs indicator animation, update your animation configuration:
// Before
<Tabs
indicatorAnimation={{
left: {
type: "spring",
config: { damping: 20, stiffness: 300 }
}
}}
>
</Tabs>
// After
<Tabs
indicatorAnimation={{
translateX: {
type: "spring",
config: { damping: 20, stiffness: 300 }
}
}}
>
</Tabs>
What Changed:
left to translateX in TabsIndicatorAnimation configurationtranslateX transform for GPU-accelerated animationsleft-0 base class to indicator styles to maintain initial positioningRelated PR: #227
The Divider component has been renamed to Separator for better consistency with naming conventions and to avoid confusion with other divider implementations.
Migration:
Update all imports and usages:
// Before
import { Divider } from "heroui-native";
<Divider />
// After
import { Separator } from "heroui-native";
<Separator />
Related PR: #238
The quaternary variant has been removed from Surface and Card components to simplify the design system and improve consistency.
Migration:
Update any components using the quaternary variant:
// Before
<Surface variant="quaternary">
</Surface>
<Card variant="quaternary">
</Card>
// After
// Use default, secondary, or tertiary variants, or apply custom styling
<Surface variant="secondary">
</Surface>
<Card variant="secondary">
</Card>
// Or use custom styling for specific needs
<Surface className="bg-custom-quaternary">
</Surface>
Available variants:
"default" - Default surface styling"secondary" - Secondary surface styling"tertiary" - Tertiary surface stylingRelated PR: #246
As part of the form component decomposition, several components have been renamed and restructured to provide better flexibility and composition patterns.
Component Renames:
FormField has been renamed to ControlFieldErrorView has been renamed to FieldErrorMigration:
Update all imports and usages:
// Before
import { FormField, ErrorView, TextField } from "heroui-native";
<FormField>
<TextField.Input />
<ErrorView>Error message</ErrorView>
</FormField>
// After
import { ControlField, FieldError, Input, TextField } from "heroui-native";
<ControlField>
<Input />
<FieldError>Error message</FieldError>
</ControlField>
TextField.Input Removal:
The TextField.Input subcomponent has been removed. Use the standalone Input component instead:
// Before
import { TextField } from "heroui-native";
<TextField>
<TextField.Input placeholder="Enter text..." />
</TextField>
// After
import { Input, TextField } from "heroui-native";
<TextField>
<Input placeholder="Enter text..." />
</TextField>
Component Composition Changes:
RadioGroup, TextField, and ControlField now use Label, Description, and FieldError components directly, providing more flexible composition:
import { ControlField, Description, FieldError, Input, Label, RadioGroup, TextField } from "heroui-native";
// TextField with Label, Description, and FieldError
<TextField>
<Label>Email</Label>
<Input placeholder="Enter email..." />
<Description>We'll never share your email.</Description>
<FieldError>Invalid email address</FieldError>
</TextField>
// RadioGroup with Label, Description, and FieldError
<RadioGroup>
<Label>Select option</Label>
<RadioGroup.Item value="option1">
<RadioGroup.Label>Option 1</RadioGroup.Label>
</RadioGroup.Item>
<Description>Choose one option</Description>
<FieldError>Please select an option</FieldError>
</RadioGroup>
// ControlField with Label, Description, and FieldError
<ControlField>
<Label>Custom Field</Label>
<Input placeholder="Enter value..." />
<Description>Additional information</Description>
<FieldError>Validation error</FieldError>
</ControlField>
Related PR: #247
A new reusable CloseButton component has been introduced, and all close button implementations across Dialog, Popover, Select, and BottomSheet components have been refactored to use this shared component. The asChild prop has been removed from all Close components.
Migration:
Update any usage of asChild prop on Close components:
// Before
import { Button, Dialog } from "heroui-native";
<Dialog>
<Dialog.Close asChild>
<Button>Cancel</Button>
</Dialog.Close>
</Dialog>
// After
import { Button, Dialog } from "heroui-native";
const [isOpen, setIsOpen] = useState(false);
<Dialog open={isOpen} onOpenChange={setIsOpen}>
<Button onPress={() => setIsOpen(false)}>Cancel</Button>
</Dialog>
What Changed:
CloseButton component added with default variant="tertiary", size="sm", and isIconOnly={true}Dialog.Close, Popover.Close, Select.Close, and BottomSheet.Close now extend CloseButton internallyasChild prop has been removed from all Close componentsvariant, size, iconProps, and custom childrenRelated PR: #237
The animation system for popup components has been refactored, resulting in several API changes that require code updates.
Migration:
closeDelay and isDismissKeyboardOnClose props from Dialog.Rootentering/exiting animation configs from Dialog.Root animation prop (now only supports disable flags). Custom animations should be configured using Keyframe animations directly on Dialog.Content componentisAnimatedStyleActive and onLayout props from Dialog.ContentisDismissKeyboardOnClose prop from BottomSheet.RootBottomSheet.Overlay animation prop to remove entering/exiting properties (no longer supported)presentation prop explicit on all Popover.Content and Select.Content components (changed from optional to required)useBottomSheetAnimation() no longer returns bottomSheetState, useDialogAnimation() no longer returns dialogStateWhat Changed:
Dialog.Root: Removed closeDelay and isDismissKeyboardOnClose propsDialog.Root: Animation prop type changed from DialogRootAnimation (supported custom entering/exiting) to AnimationRootDisableAll (disable flags only)Dialog.Content: Removed isAnimatedStyleActive and onLayout propsBottomSheet.Root: Removed isDismissKeyboardOnClose propBottomSheet.Overlay: Animation prop no longer supports entering/exiting propertiesPopover.Content: presentation prop is now required (was optional, defaulted to "popover")Select.Content: presentation prop is now required (was optional, defaulted to "popover")useBottomSheetAnimation() no longer returns bottomSheetState, useDialogAnimation() no longer returns dialogStateRelated PR: #263
This release includes fixes for the following issues:
Issue #181: Fixed TextField error when inputting Chinese characters. The TextField component now properly handles multibyte characters and international input, ensuring smooth text entry for all languages including Chinese, Japanese, and Korean.
Issue #219: Fixed Button childrenToString() returning "[object Object]" for multiple children. The function now properly handles React elements and complex children structures, preventing stringification issues when rendering button content.
Issue #232: Fixed HeroUINativeProvider breaking with the recently released Uniwind Pro. The provider now properly handles Uniwind Pro compatibility, ensuring smooth integration with the latest Uniwind version.
Issue #259: Fixed BottomSheet issue where opening quickly and starting a meeting would prevent it from opening again. The refactored animation system resolves this issue by improving the entering/exiting animation logic.
Issue #261: Fixed @gorhom/bottom-sheet not being tree-shaken. The library now properly supports tree-shaking for unused dependencies.
Additional Fixes:
childrenToString function to prevent React elements from being stringified incorrectlyRelated PRs:
Thanks to everyone who contributed to this release!