v1.0.0
LinkButton component, sub-menu conflict resolution, optional @gorhom/bottom-sheet, ThemeColorValue branded type
🎉 HeroUI Native reaches v1.0.0 — the first stable release, marking the library's graduation from beta and release candidate stages into a production-ready foundation for React Native apps. Alongside this milestone, the release includes the new LinkButton component, sub-menu conflict resolution, an optional @gorhom/bottom-sheet peer dependency, and improved type safety for useThemeColor.
Installation
Update to the latest version:
npm i heroui-nativepnpm add heroui-nativeyarn add heroui-nativebun add heroui-nativeUsing 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 v1.0.0 improvements in action with our preview app! You can explore the new LinkButton component, improved sub-menu behavior, and all the 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:

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.
What's New
LinkButton Component
The new LinkButton compound component renders a ghost-variant button with no highlight feedback, designed for inline link-style interactions such as "Terms of Service" or "Privacy Policy" links. It delegates entirely to the existing Button infrastructure while enforcing ghost variant and disabled highlight internally.
Features:
- Compound sub-component:
LinkButton.Labelfor styled text content - Ghost variant enforced internally — no
variantprop exposed - Highlight feedback disabled by default via
resolveAnimationObject h-auto p-0base class removes default button height and padding for inline use- Consumer animation config merged while preserving
highlight: false
Usage:
import { LinkButton } from "heroui-native";
export function TermsLink() {
return (
<LinkButton onPress={() => openURL("https://example.com/terms")}>
<LinkButton.Label>Terms of Service</LinkButton.Label>
</LinkButton>
);
}Related PR: #341
Component Improvements
Sub-Menu Single-Open Enforcement and Backdrop Close
The Menu sub-menu system has been refactored to track the active sub-menu by ID instead of a simple boolean, enforcing single-open behavior across sibling sub-menus. A backdrop pressable overlay now renders over the menu content area when a sub-menu is open, allowing users to dismiss it by tapping outside.
Improvements:
openSubMenuIdreplaces the boolean flag — only one sub-menu can be active at a time; opening a new one automatically closes the previous- A
Pressableoverlay renders over the menu content when a sub-menu is open, allowing tap-to-dismiss - Non-active sub-menu triggers receive
opacity-40andpointer-events-nonevia the newisOtherSubMenuOpenstyle variant - Open sub-menu content uses
z-50; closed usesz-40to avoid stacking issues - New "Two Sub Menus" example added to the demo app showcasing multiple sub-menus in a single menu
Related PR: #343
Button Label Ref Type Fix
The ButtonLabel ref type has been corrected from View to TextRef, and an unused View import has been removed from button.tsx. This fix aligns the ref type with the actual rendered element.
Related PR: #341
API Enhancements
ThemeColorValue Branded Type for useThemeColor
The useThemeColor hook now returns a ThemeColorValue branded type for single-color calls, making misuse of array destructuring immediately visible as a never type in the IDE. The non-null assertion operator (!) has also been replaced with a safe nullish coalescing fallback.
New behavior:
import { useThemeColor } from "heroui-native";
// Correct — direct assignment
const mutedColor = useThemeColor("muted");
// Incorrect — IDE immediately surfaces `never` type
const [color] = useThemeColor("muted"); // color: neverThemeColorValue extends string, so it is assignable everywhere a string is expected. Existing call sites are unaffected at runtime. The _colorValueBrand symbol is declared with declare const so it has zero runtime footprint.
Related PR: #337
useBottomSheetAwareHandlers Public Hook
The useBottomSheetAwareHandlers hook is now exported as a public API, giving consumers explicit control over keyboard avoidance wiring inside bottom sheets. This replaces the implicit isBottomSheetAware prop that was previously available on Input and InputOTP.
Usage:
import { useBottomSheetAwareHandlers, Input } from "heroui-native";
export function BottomSheetInput() {
const { onFocus, onBlur } = useBottomSheetAwareHandlers();
return <Input onFocus={onFocus} onBlur={onBlur} placeholder="Type here..." />;
}Related PR: #347
⚠️ Breaking Changes
Input and InputOTP Inside Bottom Sheet
The isBottomSheetAware prop has been removed from Input and InputOTP. Previously, keyboard avoidance inside bottom sheets was handled automatically under the hood. Now you must explicitly use the useBottomSheetAwareHandlers hook and pass the handlers yourself. This change keeps the Input component lighter by removing the implicit @gorhom/bottom-sheet import, allowing the package to be an optional peer dependency for projects that don't use bottom sheet features.
Migration:
// Before
<Input isBottomSheetAware placeholder="Type here..." />
// After
import { useBottomSheetAwareHandlers } from "heroui-native";
const { onFocus, onBlur } = useBottomSheetAwareHandlers();
<Input onFocus={onFocus} onBlur={onBlur} placeholder="Type here..." />This applies to any Input or InputOTP rendered inside a BottomSheet. Components used outside of bottom sheets are unaffected.
Related PR: #347
Bug Fixes
This release includes fixes for the following issues:
-
Issue #330: Resolved
Inputunconditionally importing@gorhom/bottom-sheetat the module level even whenisBottomSheetAwarewasfalse. The package is now loaded lazily via an optionaltry/catchwrapper, so projects that don't use bottom sheet features no longer need it installed. -
Issue #340: Fixed sub-menu content appearing behind sibling sub-menu triggers. The sub-menu system now tracks the active sub-menu by ID, enforces single-open behavior, and applies correct z-index layering (
z-50for open,z-40for closed).
Related PRs:
Updated Documentation
The following documentation pages have been updated to reflect the changes in this release:
- LinkButton - LinkButton compound component documentation with anatomy, usage examples, and API reference
- Menu - Updated sub-menu documentation with single-open enforcement and backdrop close behavior
- Input - Updated bottom sheet usage examples with
useBottomSheetAwareHandlershook pattern - InputOTP - Updated bottom sheet usage examples with
useBottomSheetAwareHandlershook pattern
Links
Contributors
Thanks to everyone who contributed to this release!