Beta 13

TextArea component, Button outline variant, Tabs improvements, form component decomposition, popup animation refactor, style class exports, and critical bug fixes

February 3, 2026

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.

Installation

Update to the latest version:

npm i heroui-native@beta
pnpm add heroui-native@beta
yarn add heroui-native@beta
bun add heroui-native@beta

Using AI assistants? Simply prompt "Hey Cursor, update HeroUI Native to the latest version" and your AI assistant will automatically compare versions and apply the necessary changes. Learn more about the HeroUI Native MCP Server.

Try It Out

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.

Prerequisites

Make sure you have the latest version of Expo Go installed on your mobile device.

How to Access

Option 1: Scan the QR Code

Use your device's camera or Expo Go app to scan:

Expo Go QR Code

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

📱 Open Demo App in Expo Go

This will automatically open the app in Expo Go if it's installed on your device.

What's New

New Components

This release introduces 3 new essential components:

  • TextArea: Multiline text input component with styled border and background for collecting longer user input.
  • Input: Single-line text input component with styled border and background, now available as a standalone component separate from TextField.
  • CloseButton: Reusable button component for closing dialogs, modals, or dismissing content with consistent styling across overlay components.

TextArea

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.

Features:

  • Multiline text input with customizable rows
  • Seamless integration with TextField component
  • Validation state support with visual feedback
  • Primary and secondary variants for different contexts
  • Disabled and read-only states
  • Customizable styling via className and styles props
  • Complete accessibility support

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

Input

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.

Features:

  • Single-line text input with styled border and background
  • Standalone usage or integration with form components
  • Validation state support with visual feedback
  • Primary and secondary variants for different contexts
  • Disabled and read-only states
  • Customizable styling via className and styles props
  • Complete accessibility support

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

CloseButton

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.

Features:

  • Consistent close button styling across overlay components
  • Customizable icon size and color
  • Support for custom children to replace default icon
  • Disabled state support
  • Seamless integration with Dialog, Popover, Select, and Bottom Sheet
  • Default styling optimized for overlay contexts

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

New Subcomponents

Tabs.Separator

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:

  • Animated visibility transitions based on active tab
  • Configurable visibility via betweenValues prop
  • Customizable animation timing and opacity
  • Always visible option for static separators

Usage:

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

Component Improvements

Button Outline Variant

The Button component now includes an outline variant that provides a bordered style with transparent background, offering more visual variety for button designs.

Improvements:

  • New outline variant for bordered button style
  • Consistent styling with other Button variants
  • Proper hover and focus states for outline variant
  • Seamless integration with existing Button API

Usage:

import { Button } from "heroui-native";

<Button variant="outline">Outline Button</Button>

Related PR: #235

Tabs Indicator Animation Refactor

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:

  • Migrated indicator animation to translateX transforms
  • Improved animation performance and smoothness
  • Better visual consistency during tab transitions
  • Reduced layout recalculations during animations

Related PR: #227

Popover Arrow Sizing and Visual Connection

The Popover component has been improved with better arrow sizing and visual connection to the popover content, creating a more cohesive visual appearance.

Improvements:

  • Improved arrow sizing relative to popover content
  • Enhanced visual connection between arrow and popover
  • Better alignment and spacing
  • More polished overall appearance

Related PR: #243

Form Components Decomposition

Form components have been decomposed into standalone primitives, providing developers with more flexibility and better control over component composition.

Improvements:

  • Decomposed form components into standalone primitives
  • Improved component reusability and composition
  • Better separation of concerns
  • Enhanced flexibility for custom form layouts

Related PR: #247

Input Android Shadow Fix

The Input component now includes platform-specific shadow styling for Android, ensuring consistent visual appearance across platforms.

Improvements:

  • Added platform-specific shadow for Android
  • Improved visual consistency across iOS and Android
  • Better elevation appearance on Android devices
  • Enhanced component appearance on Android platform

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:

  • Standardized entering/exiting animations using FadeInDown/FadeOutDown for dialog presentations
  • Refactored overlay animation hooks to support both progress-based and entering/exiting animations
  • Improved overlay composition using Dialog.Overlay and Popover.Overlay components instead of Pressable wrappers
  • Fixed Android pointer events issue affecting popup interactions
  • Made presentation prop explicit in examples (popover, dialog, bottom-sheet)
  • Simplified animation API for better maintainability and consistency

Related PR: #263

API Enhancements

Granular Exports for Bundle Optimization

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 component
  • heroui-native/[component-name] - Individual components
  • heroui-native/portal - Portal 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.

Related PR: #233

Style Class Names Export

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

Style Fixes

Style Optimizations

  • Quaternary Variant Removal: Removed quaternary variant and polished component styles for better consistency
  • Component Style Polish: Enhanced styling across multiple components for improved visual consistency
  • Shadow and Border Radius Updates: Improved shadow and border radius consistency across components
  • Theme Variable Cleanup: Simplified theme variables and removed redundant color-mix calculations

Related PR: #246

⚠️ Breaking Changes

Tabs Variant Prop Rename

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">
  {/* content */}
</Tabs>

<Tabs variant="line">
  {/* content */}
</Tabs>

// After
<Tabs variant="primary">
  {/* content */}
</Tabs>

<Tabs variant="secondary">
  {/* content */}
</Tabs>

Available options:

  • "primary" - Primary variant (previously "pill")
  • "secondary" - Secondary variant (previously "line")

Related PR: #236

Tabs Indicator Animation Refactor

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 }
    }
  }}
>
  {/* content */}
</Tabs>

// After
<Tabs
  indicatorAnimation={{
    translateX: {
      type: "spring",
      config: { damping: 20, stiffness: 300 }
    }
  }}
>
  {/* content */}
</Tabs>

What Changed:

  • Animation API changed from left to translateX in TabsIndicatorAnimation configuration
  • Indicator positioning now uses translateX transform for GPU-accelerated animations
  • Added left-0 base class to indicator styles to maintain initial positioning
  • Visual behavior remains identical, only the underlying implementation has changed

Related PR: #227

Divider Component Rename

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

Quaternary Variant Removal

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">
  {/* content */}
</Surface>

<Card variant="quaternary">
  {/* content */}
</Card>

// After
// Use default, secondary, or tertiary variants, or apply custom styling
<Surface variant="secondary">
  {/* content */}
</Surface>

<Card variant="secondary">
  {/* content */}
</Card>

// Or use custom styling for specific needs
<Surface className="bg-custom-quaternary">
  {/* content */}
</Surface>

Available variants:

  • "default" - Default surface styling
  • "secondary" - Secondary surface styling
  • "tertiary" - Tertiary surface styling

Related PR: #246

Form Component Decomposition

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 ControlField
  • ErrorView has been renamed to FieldError

Migration:

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

CloseButton Component and asChild Removal

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:

  • New CloseButton component added with default variant="tertiary", size="sm", and isIconOnly={true}
  • Dialog.Close, Popover.Close, Select.Close, and BottomSheet.Close now extend CloseButton internally
  • The asChild prop has been removed from all Close components
  • Close components still support all Button props including variant, size, iconProps, and custom children
  • You must now handle close logic manually when using custom buttons instead of Close components

Related PR: #237

The animation system for popup components has been refactored, resulting in several API changes that require code updates.

Migration:

  • Remove closeDelay and isDismissKeyboardOnClose props from Dialog.Root
  • Remove custom entering/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 component
  • Remove isAnimatedStyleActive and onLayout props from Dialog.Content
  • Remove isDismissKeyboardOnClose prop from BottomSheet.Root
  • Update BottomSheet.Overlay animation prop to remove entering/exiting properties (no longer supported)
  • Make presentation prop explicit on all Popover.Content and Select.Content components (changed from optional to required)
  • Update animation hooks usage: useBottomSheetAnimation() no longer returns bottomSheetState, useDialogAnimation() no longer returns dialogState

What Changed:

  • Dialog.Root: Removed closeDelay and isDismissKeyboardOnClose props
  • Dialog.Root: Animation prop type changed from DialogRootAnimation (supported custom entering/exiting) to AnimationRootDisableAll (disable flags only)
  • Dialog.Content: Removed isAnimatedStyleActive and onLayout props
  • BottomSheet.Root: Removed isDismissKeyboardOnClose prop
  • BottomSheet.Overlay: Animation prop no longer supports entering/exiting properties
  • Popover.Content: presentation prop is now required (was optional, defaulted to "popover")
  • Select.Content: presentation prop is now required (was optional, defaulted to "popover")
  • Animation hooks: useBottomSheetAnimation() no longer returns bottomSheetState, useDialogAnimation() no longer returns dialogState

Related PR: #263

Bug Fixes

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:

  • Fixed theme calculated colors issue that was causing incorrect color values in certain scenarios
  • Fixed childrenToString function to prevent React elements from being stringified incorrectly

Related PRs:

Contributors

Thanks to everyone who contributed to this release!

On this page