Flutter
Build beautiful mobile applications with Galaxy UI components for Flutter.
Overview
Galaxy UI for Flutter provides 37 production-ready components styled with Material Design 3. All components are fully typed with Dart and follow Flutter best practices with StatelessWidget patterns.
Prerequisites
Before you begin, make sure you have:
- Flutter 3.24+ (latest stable)
- Dart 3.5+
- Material Design 3 configured
- An existing Flutter 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 Flutter automatically
- ✅ Add required dependencies to
pubspec.yaml - ✅ Create
components.jsonconfiguration - ✅ Set up Material Design 3 theme
- ✅ Create utility functions
- ✅ Export
GalaxyButtonwidget with params: variant (6 options), size (4 options), onPressed, disabled, child
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": "flutter",
"language": "dart",
"styling": "material3",
"material": {
"version": "3",
"theme": "lib/theme/theme.dart"
},
"aliases": {
"components": "lib/components"
}
}Material Design 3 Setup
Make sure Material 3 is properly configured in your Flutter app:
pubspec.yaml
name: your_app
description: A beautiful Flutter application with Galaxy UI
dependencies:
flutter:
sdk: flutter
# Material Design 3 is included in Flutter SDK
# Additional dependencies added by Galaxy UI CLI:
intl: ^0.19.0
flutter:
uses-material-design: true
# Optional: Add custom fonts
fonts:
- family: Inter
fonts:
- asset: fonts/Inter-Regular.ttf
- asset: fonts/Inter-Medium.ttf
weight: 500
- asset: fonts/Inter-Bold.ttf
weight: 700lib/theme/theme.dart
import 'package:flutter/material.dart';
class AppTheme {
// Light Theme
static ThemeData lightTheme = ThemeData(
useMaterial3: true,
colorScheme: ColorScheme.fromSeed(
seedColor: const Color(0xFF6366F1), // Indigo
brightness: Brightness.light,
),
textTheme: const TextTheme(
displayLarge: TextStyle(
fontSize: 57,
fontWeight: FontWeight.bold,
),
titleLarge: TextStyle(
fontSize: 22,
fontWeight: FontWeight.w500,
),
bodyLarge: TextStyle(
fontSize: 16,
),
),
);
// Dark Theme
static ThemeData darkTheme = ThemeData(
useMaterial3: true,
colorScheme: ColorScheme.fromSeed(
seedColor: const Color(0xFF6366F1), // Indigo
brightness: Brightness.dark,
),
textTheme: const TextTheme(
displayLarge: TextStyle(
fontSize: 57,
fontWeight: FontWeight.bold,
),
titleLarge: TextStyle(
fontSize: 22,
fontWeight: FontWeight.w500,
),
bodyLarge: TextStyle(
fontSize: 16,
),
),
);
}lib/main.dart
import 'package:flutter/material.dart';
import 'package:your_app/theme/theme.dart';
void main() {
runApp(const MyApp());
}
class MyApp extends StatelessWidget {
const MyApp({super.key});
@override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Galaxy UI App',
theme: AppTheme.lightTheme,
darkTheme: AppTheme.darkTheme,
themeMode: ThemeMode.system,
home: const HomePage(),
);
}
}Usage Examples
Button Component
import 'package:flutter/material.dart';
import 'package:your_app/components/ui/button.dart';
class ButtonExample extends StatelessWidget {
const ButtonExample({super.key});
@override
Widget build(BuildContext context) {
return Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
// Default button
GalaxyButton(
variant: ButtonVariant.defaultVariant,
onPressed: () {
print('Button pressed!');
},
child: const Text('Default Button'),
),
const SizedBox(height: 16),
// Secondary button
GalaxyButton(
variant: ButtonVariant.secondary,
onPressed: () {},
child: const Text('Secondary Button'),
),
const SizedBox(height: 16),
// Outline button
GalaxyButton(
variant: ButtonVariant.outline,
onPressed: () {},
child: const Text('Outline Button'),
),
const SizedBox(height: 16),
// Disabled button
GalaxyButton(
variant: ButtonVariant.defaultVariant,
onPressed: null,
child: const Text('Disabled Button'),
),
],
);
}
}Input Component
import 'package:flutter/material.dart';
import 'package:your_app/components/ui/input.dart';
class LoginForm extends StatefulWidget {
const LoginForm({super.key});
@override
State<LoginForm> createState() => _LoginFormState();
}
class _LoginFormState extends State<LoginForm> {
final _emailController = TextEditingController();
final _passwordController = TextEditingController();
@override
void dispose() {
_emailController.dispose();
_passwordController.dispose();
super.dispose();
}
@override
Widget build(BuildContext context) {
return Padding(
padding: const EdgeInsets.all(16.0),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
// Email input
const Text(
'Email',
style: TextStyle(
fontSize: 14,
fontWeight: FontWeight.w500,
),
),
const SizedBox(height: 8),
GalaxyInput(
controller: _emailController,
hintText: 'Enter your email',
keyboardType: TextInputType.emailAddress,
),
const SizedBox(height: 16),
// Password input
const Text(
'Password',
style: TextStyle(
fontSize: 14,
fontWeight: FontWeight.w500,
),
),
const SizedBox(height: 8),
GalaxyInput(
controller: _passwordController,
hintText: 'Enter your password',
obscureText: true,
),
],
),
);
}
}Dialog Component
import 'package:flutter/material.dart';
import 'package:your_app/components/ui/dialog.dart';
import 'package:your_app/components/ui/button.dart';
class DialogExample extends StatelessWidget {
const DialogExample({super.key});
void _showDialog(BuildContext context) {
showDialog(
context: context,
builder: (BuildContext context) {
return GalaxyDialog(
title: 'Confirm Action',
content: const Text(
'Are you sure you want to continue? This action cannot be undone.',
),
actions: [
GalaxyButton(
variant: ButtonVariant.outline,
onPressed: () {
Navigator.of(context).pop();
},
child: const Text('Cancel'),
),
GalaxyButton(
variant: ButtonVariant.defaultVariant,
onPressed: () {
Navigator.of(context).pop();
// Handle confirmation
},
child: const Text('Confirm'),
),
],
);
},
);
}
@override
Widget build(BuildContext context) {
return GalaxyButton(
onPressed: () => _showDialog(context),
child: const Text('Open Dialog'),
);
}
}Available Components
Galaxy UI for Flutter includes 37 mobile-optimized components:
Form & Input
- Button
- Input
- Checkbox
- Radio Group
- Select (Dropdown)
- Slider
- Switch
- Textarea
- Label
Layout
- Separator (Divider)
- Accordion (ExpansionPanel)
- Collapsible
- Tabs (TabBar)
- Aspect Ratio
- Sheet (BottomSheet)
- Toolbar
Navigation
- Navigation Menu
- Pagination
Data Display
- Avatar
- Progress (LinearProgressIndicator)
- Badge
- Typography
- Empty State
- Skeleton (Shimmer)
Overlays
- Dialog
- Alert Dialog
- Popover (Menu)
- Tooltip
Date & Time
- Calendar (DatePicker)
- Calendar Range (DateRangePicker)
Interactive
- Toggle
- Toggle Group (SegmentedButton)
Dark Mode
Galaxy UI supports dark mode automatically with Flutter's ThemeMode:
import 'package:flutter/material.dart';
class MyApp extends StatefulWidget {
const MyApp({super.key});
@override
State<MyApp> createState() => _MyAppState();
}
class _MyAppState extends State<MyApp> {
ThemeMode _themeMode = ThemeMode.system;
void _toggleTheme() {
setState(() {
_themeMode = _themeMode == ThemeMode.light
? ThemeMode.dark
: ThemeMode.light;
});
}
@override
Widget build(BuildContext context) {
return MaterialApp(
theme: AppTheme.lightTheme,
darkTheme: AppTheme.darkTheme,
themeMode: _themeMode,
home: Scaffold(
appBar: AppBar(
actions: [
IconButton(
icon: Icon(
_themeMode == ThemeMode.light
? Icons.dark_mode
: Icons.light_mode,
),
onPressed: _toggleTheme,
),
],
),
body: const HomePage(),
),
);
}
}State Management
Galaxy UI components work with any Flutter state management solution:
Provider
import 'package:provider/provider.dart';
class CounterProvider extends ChangeNotifier {
int _count = 0;
int get count => _count;
void increment() {
_count++;
notifyListeners();
}
}
// Usage
GalaxyButton(
onPressed: () {
context.read<CounterProvider>().increment();
},
child: Text('Count: ${context.watch<CounterProvider>().count}'),
)Riverpod
import 'package:flutter_riverpod/flutter_riverpod.dart';
final counterProvider = StateProvider<int>((ref) => 0);
// Usage
Consumer(
builder: (context, ref, child) {
final count = ref.watch(counterProvider);
return GalaxyButton(
onPressed: () {
ref.read(counterProvider.notifier).state++;
},
child: Text('Count: $count'),
);
},
)Best Practices
1. Use const constructors
// ✅ Good - uses const
const GalaxyButton(
child: Text('Click Me'),
)
// ❌ Bad - no const
GalaxyButton(
child: Text('Click Me'),
)2. Extract widgets for reusability
class CustomCard extends StatelessWidget {
final String title;
final String subtitle;
const CustomCard({
super.key,
required this.title,
required this.subtitle,
});
@override
Widget build(BuildContext context) {
return Card(
child: Padding(
padding: const EdgeInsets.all(16.0),
child: Column(
children: [
Text(title, style: Theme.of(context).textTheme.titleLarge),
Text(subtitle),
],
),
),
);
}
}3. Use Theme.of(context)
Text(
'Hello World',
style: Theme.of(context).textTheme.headlineSmall,
)Performance Tips
- Use const constructors whenever possible
const Padding(
padding: EdgeInsets.all(8.0),
child: Text('Hello'),
)- Use ListView.builder for long lists
ListView.builder(
itemCount: items.length,
itemBuilder: (context, index) {
return ListTile(title: Text(items[index]));
},
)- Cache complex calculations
@override
Widget build(BuildContext context) {
final filteredItems = useMemoized(
() => items.where((item) => item.isActive).toList(),
[items],
);
return ListView(children: filteredItems.map(...));
}Troubleshooting
Material 3 colors not working
Make sure you have useMaterial3: true in your ThemeData:
ThemeData(
useMaterial3: true,
colorScheme: ColorScheme.fromSeed(seedColor: Colors.blue),
)Components not importing correctly
Check your import paths match the configuration in components.json:
import 'package:your_app/components/ui/button.dart';Hot reload not working
Try:
- Hot restart (
Rin terminal) - Stop and restart the app
- Run
flutter cleanthenflutter pub get
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
