React Native
Build beautiful mobile applications with Galaxy UI components for React Native.
Overview
Galaxy UI for React Native provides 37 production-ready components styled with NativeWind v4 (Tailwind CSS for React Native). All components are fully typed with TypeScript and follow React Native best practices.
Prerequisites
Before you begin, make sure you have:
- React Native 0.74+ (with New Architecture support)
- Node.js 18+ or Bun 1.0+
- NativeWind v4 configured
- Expo 51+ or bare React Native project
Installation
Step 1: Initialize Galaxy UI
# Using npx
npx @galaxy-stack/nebula-cli@latest init
# Using bunx
bunx @galaxy-stack/nebula-cli@latest initThe CLI will:
- ✅ Detect React Native automatically
- ✅ Install NativeWind v4 dependencies
- ✅ Create
components.jsonconfiguration - ✅ Set up utility functions
- ✅ Configure Tailwind CSS
- ✅ Export
Buttoncomponent with props: variant (6 options), size (4 options), onPress, disabled, children, className
Step 2: Add Components
# Add a single component
npx @galaxy-stack/nebula-cli@latest add button
# Add multiple components
npx @galaxy-stack/nebula-cli@latest add button input dialogConfiguration
Galaxy UI creates a components.json file in your project root:
{
"$schema": "https://galaxy-nebula.vercel.app/schema.json",
"framework": "react-native",
"typescript": true,
"styling": "nativewind",
"nativewind": {
"version": "v4",
"config": "tailwind.config.js"
},
"aliases": {
"components": "@/components",
"utils": "@/lib/utils"
}
}NativeWind v4 Setup
Make sure NativeWind v4 is properly configured:
babel.config.js
module.exports = function (api) {
api.cache(true);
return {
presets: ["babel-preset-expo"],
plugins: [
"nativewind/babel",
"react-native-reanimated/plugin",
],
};
};tailwind.config.js
/** @type {import('tailwindcss').Config} */
module.exports = {
content: [
"./App.{js,jsx,ts,tsx}",
"./app/**/*.{js,jsx,ts,tsx}",
"./components/**/*.{js,jsx,ts,tsx}",
],
presets: [require("nativewind/preset")],
theme: {
extend: {
colors: {
border: "hsl(var(--border))",
input: "hsl(var(--input))",
ring: "hsl(var(--ring))",
background: "hsl(var(--background))",
foreground: "hsl(var(--foreground))",
primary: {
DEFAULT: "hsl(var(--primary))",
foreground: "hsl(var(--primary-foreground))",
},
// ... more colors
},
},
},
plugins: [],
};global.css
@tailwind base;
@tailwind components;
@tailwind utilities;
:root {
--background: 0 0% 100%;
--foreground: 222.2 84% 4.9%;
--primary: 222.2 47.4% 11.2%;
--primary-foreground: 210 40% 98%;
/* ... more variables */
}
.dark {
--background: 222.2 84% 4.9%;
--foreground: 210 40% 98%;
--primary: 210 40% 98%;
--primary-foreground: 222.2 47.4% 11.2%;
/* ... more variables */
}Usage Examples
Button Component
import { Button } from '@/components/ui/button';
import { View } from 'react-native';
export default function App() {
return (
<View className="flex-1 items-center justify-center gap-4 p-4">
{/* Default button */}
<Button variant="default">Default Button</Button>
{/* Secondary button */}
<Button variant="secondary">Secondary Button</Button>
{/* Outline button */}
<Button variant="outline">Outline Button</Button>
{/* With custom handler */}
<Button onPress={() => console.log('Pressed!')}>Click Me</Button>
</View>
);
}Input Component
import { Input } from '@/components/ui/input';
import { View, Text } from 'react-native';
import { useState } from 'react';
export default function LoginForm() {
const [email, setEmail] = useState('');
const [password, setPassword] = useState('');
return (
<View className="flex-1 p-4 gap-4">
<View className="gap-2">
<Text className="text-sm font-medium">Email</Text>
<Input
placeholder="Enter your email"
value={email}
onChangeText={setEmail}
keyboardType="email-address"
autoCapitalize="none"
/>
</View>
<View className="gap-2">
<Text className="text-sm font-medium">Password</Text>
<Input
placeholder="Enter your password"
value={password}
onChangeText={setPassword}
secureTextEntry
/>
</View>
</View>
);
}Dialog Component
import {
Dialog,
DialogTrigger,
DialogContent,
DialogHeader,
DialogTitle,
DialogDescription,
DialogFooter,
DialogClose,
} from '@/components/ui/dialog';
import { Button } from '@/components/ui/button';
export default function DialogExample() {
return (
<Dialog>
<DialogTrigger asChild>
<Button>Open Dialog</Button>
</DialogTrigger>
<DialogContent>
<DialogHeader>
<DialogTitle>Confirm Action</DialogTitle>
<DialogDescription>
Are you sure you want to continue? This action cannot be undone.
</DialogDescription>
</DialogHeader>
<DialogFooter>
<DialogClose asChild>
<Button variant="outline">Cancel</Button>
</DialogClose>
<DialogClose asChild>
<Button variant="default">Confirm</Button>
</DialogClose>
</DialogFooter>
</DialogContent>
</Dialog>
);
}Available Components
Galaxy UI for React Native includes 37 mobile-optimized components:
Form & Input
- Button
- Input
- Checkbox
- Radio Group
- Select
- Slider
- Switch
- Textarea
- Label
Layout
- Separator
- Accordion
- Collapsible
- Tabs
- Aspect Ratio
- Sheet
- Toolbar
Navigation
- Navigation Menu
- Pagination
Data Display
- Avatar
- Progress
- Badge
- Typography
- Empty
- Skeleton
Overlays
- Dialog
- Alert Dialog
- Popover
- Tooltip
Date & Time
- Calendar
- Calendar Range
Interactive
- Toggle
- Toggle Group
Dark Mode
Galaxy UI supports dark mode out of the box with NativeWind v4:
import { useColorScheme } from 'react-native';
import { StatusBar } from 'expo-status-bar';
export default function App() {
const colorScheme = useColorScheme();
return (
<>
<StatusBar style={colorScheme === 'dark' ? 'light' : 'dark'} />
{/* Your app content */}
</>
);
}TypeScript Support
All components are fully typed with TypeScript:
import type { ButtonProps } from '@/components/ui/button';
const CustomButton: React.FC<ButtonProps> = ({ children, ...props }) => {
return (
<Button {...props}>
{children}
</Button>
);
};Best Practices
1. Use Composition
import { Button } from '@/components/ui/button';
import { Spinner } from '@/components/ui/spinner';
function LoadingButton({ loading, children, ...props }) {
return (
<Button disabled={loading} {...props}>
{loading && <Spinner size="sm" className="mr-2" />}
{children}
</Button>
);
}2. Customize with Tailwind
<Button className="bg-purple-600 active:bg-purple-700">
Custom Button
</Button>3. Handle Platform Differences
import { Platform } from 'react-native';
<Button
className={Platform.select({
ios: 'rounded-full',
android: 'rounded-md',
})}
>
Platform Button
</Button>Performance Tips
- Use
useMemofor complex calculations
const filteredData = useMemo(() =>
data.filter(item => item.active),
[data]
);- Use
React.memofor expensive components
const MemoizedComponent = React.memo(MyComponent);- Avoid inline functions in render
// ❌ Bad
<Button onPress={() => handlePress(id)}>
// ✅ Good
const handleButtonPress = useCallback(() => {
handlePress(id);
}, [id]);
<Button onPress={handleButtonPress}>Troubleshooting
NativeWind not working
Make sure you have:
- Installed NativeWind v4:
npm install nativewind@^4.0.0 - Added
nativewind/babeltobabel.config.js - Imported
global.cssin your App entry file
Components not styled correctly
Check that your tailwind.config.js includes the correct content paths:
content: [
"./app/**/*.{js,jsx,ts,tsx}",
"./components/**/*.{js,jsx,ts,tsx}",
],Next Steps
- Components Overview - Browse all available components
- CLI Usage - Learn more about the CLI
- Theming - Customize your theme
Resources
Support
Having issues? Check our GitHub Issues or contact kevinbui210191@gmail.com
