Skip to main content

@hikari/ui-native

Shared React Native component library for mobile apps in the monorepo. Built on gluestack-ui v3 with NativeWind for Tailwind CSS styling on native platforms.

Storybook: ui-native-storybook-web.pages.dev

Installation

Already available to all workspace apps. Add the dependency:

{
"dependencies": {
"@hikari/ui-native": "workspace:*"
}
}

Wrap your app with the provider:

import { GluestackUIProvider } from "@hikari/ui-native/provider";

export default function App() {
return (
<GluestackUIProvider mode="light">{/* your app */}</GluestackUIProvider>
);
}

Usage

import {
Button,
ButtonText,
Card,
Heading,
Text,
VStack,
} from "@hikari/ui-native";

function MyScreen() {
return (
<Card className="gap-2 p-4">
<Heading size="md">Dashboard</Heading>
<Text>Everything is running smoothly.</Text>
<Button action="primary" variant="solid" size="md">
<ButtonText>View Details</ButtonText>
</Button>
</Card>
);
}

Deep imports

import { Button, ButtonText } from "@hikari/ui-native/components/ui/button";

Components (52)

CategoryComponents
LayoutBox, Center, Grid, GridItem, HStack, VStack, View, Divider, SafeAreaView, KeyboardAvoidingView, ScrollView, Portal
TypographyHeading, Text, Link, LinkText
FormsButton, Checkbox, FormControl, Input, InputField, Radio, Select, Slider, Switch, Textarea
Data DisplayAccordion, Avatar, Badge, Card, Icon, Image, ImageBackground, Progress, Skeleton, Spinner, Table
FeedbackAlert, Toast, FAB
OverlaysActionsheet, AlertDialog, BottomSheet, Drawer, Menu, Modal, Popover, Tooltip
ListsFlatList, SectionList, VirtualizedList
PlatformInputAccessoryView, StatusBar, RefreshControl, Pressable

Variant system

Components use gluestack-ui's tva() (Tailwind Variant Authority) for variant props. Common patterns:

PropValuesUsed by
actionprimary, secondary, positive, negative, error, warning, success, info, mutedButton, Badge, Alert, Toast
variantsolid, outline, link, filled, unfilled, ghost, elevatedButton, Badge, Alert, Card, Accordion
sizexs, sm, md, lg, xl, 2xlButton, Input, Badge, Avatar, Modal, Heading, Text
spacexs, sm, md, lg, xl, 2xl, 3xl, 4xlHStack, VStack
orientationhorizontal, verticalDivider, Slider, Progress

Per-app theming

The default color palette is defined in src/components/ui/gluestack-ui-provider/config.ts using NativeWind's vars() function. Each color scale (primary, secondary, error, success, etc.) has shades from 0–950 as RGB triplets.

Overriding colors

To customize the theme in your app, create a custom config and pass it as a style to the provider's root View:

import { vars } from "nativewind";
import { UiNativeProvider } from "@hikari/ui-native/provider";

const appTheme = {
light: vars({
// Override primary to teal
"--color-primary-500": "13 148 136",
"--color-primary-600": "15 118 110",
"--color-primary-700": "19 78 74",
// ... only override the shades you need
}),
dark: vars({
"--color-primary-500": "45 212 191",
"--color-primary-600": "94 234 212",
"--color-primary-700": "153 246 228",
}),
};

export default function App() {
const mode = "light"; // or "dark" or "system"
return (
<UiNativeProvider
mode={mode}
style={appTheme[mode === "system" ? "light" : mode]}
>
{/* your app */}
</UiNativeProvider>
);
}

NativeWind vars() values cascade through the React Native view tree, so vars set on a parent override those set higher up (like the default provider config).

Available color scales

ScaleCSS variable patternUsage
primary--color-primary-{0-950}Primary buttons, active states
secondary--color-secondary-{0-950}Secondary surfaces, muted elements
tertiary--color-tertiary-{0-950}Tertiary accents
error--color-error-{0-950}Error states, destructive actions
success--color-success-{0-950}Success feedback
warning--color-warning-{0-950}Warning states
info--color-info-{0-950}Informational highlights
typography--color-typography-{0-950}Text colors
outline--color-outline-{0-950}Borders and outlines
background--color-background-{0-950}Surface backgrounds

Special background tokens: --color-background-error, --color-background-warning, --color-background-success, --color-background-muted, --color-background-info.

Focus ring indicators: --color-indicator-primary, --color-indicator-info, --color-indicator-error.

Design system documentation

Each app with significant native UI should have a DESIGN-SYSTEM.md at its root documenting the color palette, typography, spacing, and component patterns used. This serves as the source of truth for the app's visual language.

Adding or upgrading components

# Add a new gluestack component
pnpm --filter @hikari/ui-native ui:add

# Upgrade existing components
pnpm --filter @hikari/ui-native ui:upgrade

# Run postprocessing (code transforms for NativeWind compat)
pnpm --filter @hikari/ui-native ui:postprocess

Tech stack

  • UI Framework: gluestack-ui v3
  • Styling: NativeWind (Tailwind CSS for React Native), Tailwind v3
  • Animations: @legendapp/motion (framer-motion equivalent for RN)
  • Bottom Sheet: @gorhom/bottom-sheet
  • Icons: Lucide React Native
  • Gestures: react-native-gesture-handler, react-native-reanimated

Storybook

The component library is documented and tested via two Storybook setups:

Web preview (primary)

  • App: apps/ui-native-storybook-web
  • Framework: @storybook/react-native-web-vite (renders native components via react-native-web)
  • URL: ui-native-storybook-web.pages.dev
  • Coverage: 52 story files, 125 stories covering all variants and sizes
  • Tests: Vitest coverage tests (component-to-story mapping) + Playwright e2e (all stories render without errors)
  • Key config: jsxImportSource: "nativewind" for CSS interop, esbuild plugin to stub InputAccessoryView, ESM alias for @legendapp/motion

On-device preview

  • App: apps/ui-native-playground (Expo with on-device Storybook via @storybook/react-native)
  • Purpose: Verify components on actual iOS/Android devices with native gestures and animations

A coverage test in apps/ui-native-storybook-web/test/storybook-coverage.test.ts ensures both storybook setups stay in sync with the package's component exports.