A modern Flutter UI framework with reusable widgets, design system components, and beautiful developer-friendly APIs.
- NovaButton — filled, outlined, text variants · loading state · icon support · disabled state
- NovaTextField — label · validation · password toggle · multiline · theme-aware borders
- NovaContainer — tappable · elevation shorthand · gradient · clip support
- NovaCard — zero-config card with shadow and rounded corners
- NovaLoader — circular, linear, dots loading indicators
- NovaDialog — info/success/warning/danger alert and confirm dialogs
- NovaBadge — status labels · notification counts · dot indicators · overlay badges
- NovaShimmer — animated skeleton loading placeholders
- NovaAvatar — network/asset/initials/icon avatar with online indicator
- NovaChip — filter/tag chips with group support
- NovaToast — animated overlay notifications with auto-dismiss
- NovaBottomSheet — styled modal bottom sheet with actions support
- NovaTheme — one-line light/dark theme setup
- NovaColors — semantic theme-aware colors + raw swatches
- NovaSpacing — spacing scale + gap widgets + EdgeInsets helpers
- NovaRadius — border radius tokens + directional helpers
- Null safety · Material 3 · Dark mode · All platforms
dependencies:
nova_ui: ^1.0.4flutter pub getimport'package:nova_ui/nova_ui.dart';
// 1. Setup themeMaterialApp(
theme:NovaTheme.light(),
darkTheme:NovaTheme.dark(),
themeMode:ThemeMode.system,
)
// 2. Use widgetsNovaButton(
text:'Login',
onPressed: () {},
)
NovaTextField(
label:'Email',
hintText:'you@example.com',
validator: (v) => v!.isEmpty ?'Required':null,
)
NovaCard(
onTap: () {},
child:Text('Hello Nova UI'),
)// Filled (default)NovaButton(text:'Submit', onPressed: () {})
// OutlinedNovaButton(
text:'Cancel',
variant:NovaButtonVariant.outlined,
onPressed: () {},
)
// LoadingNovaButton(text:'Saving...', loading:true, onPressed: () {})
// DisabledNovaButton(text:'Unavailable', onPressed:null)
// With iconNovaButton(
text:'Upload',
icon:Icon(Icons.upload),
onPressed: () {},
)// BasicNovaTextField(label:'Name', hintText:'Enter your name')
// Password — auto visibility toggleNovaTextField(
label:'Password',
obscureText:true,
)
// With validation (inside Form widget)NovaTextField(
label:'Email',
validator: (v) => v!.contains('@') ?null:'Invalid email',
)
// MultilineNovaTextField(label:'Bio', maxLines:4)// TappableNovaContainer(
onTap: () {},
elevation:4,
borderRadius:NovaRadius.lg,
child:Text('Tap me'),
)
// GradientNovaContainer(
height:120,
borderRadius:NovaRadius.xl,
gradient:LinearGradient(colors: [Colors.purple, Colors.blue]),
child:Center(child:Text('Gradient')),
)// Zero configNovaCard(child:Text('Simple card'))
// TappableNovaCard(
onTap: () {},
child:ListTile(title:Text('Tap to open')),
)// Circular (default)constNovaLoader()
// Linear progress barNovaLoader(type:NovaLoaderType.linear)
// Dots animationNovaLoader(type:NovaLoaderType.dots, size:32)
// Custom colorNovaLoader(color:Colors.white)// Simple alertNovaDialog.show(
context: context,
title:'Done!',
message:'Your profile has been saved.',
type:NovaDialogType.success,
)
// Confirm dialogNovaDialog.show(
context: context,
title:'Delete Account?',
message:'This action cannot be undone.',
type:NovaDialogType.danger,
confirmText:'Delete',
cancelText:'Cancel',
onConfirm: () =>_deleteAccount(),
)// Status labelNovaBadge(label:'Active', color:NovaBadgeColor.success)
// Dot indicatorNovaBadge(isDot:true, color:NovaBadgeColor.danger)
// CountNovaBadge(count:5)
// Overlay on iconNovaBadge(count:12, child:Icon(Icons.notifications))// Rectangle placeholderconstNovaShimmer(width:200, height:16)
// Circle — avatar placeholderconstNovaShimmer.circle(size:48)
// Card skeletonNovaShimmer.card()
// List skeletonNovaShimmer.list(itemCount:5)
// Real world usage
isLoading
?NovaShimmer.list(itemCount:4)
:ListView.builder(...)// Initials — auto color from nameNovaAvatar(name:'John Doe') // → 'JD'// Network image with fallbackNovaAvatar(
imageUrl:'https://example.com/photo.jpg',
name:'John Doe',
)
// Online indicatorNovaAvatar(
name:'John',
showOnlineIndicator:true,
isOnline:true,
)
// SizesNovaAvatar(name:'JD', size:NovaAvatarSize.xs) // 28pxNovaAvatar(name:'JD', size:NovaAvatarSize.lg) // 64px// Simple tagNovaChip(label:'Flutter')
// VariantsNovaChip(label:'Soft', variant:NovaChipVariant.soft)
NovaChip(label:'Outlined', variant:NovaChipVariant.outlined)
// DeletableNovaChip(
label:'Remove',
onDeleted: () =>_removeTag(),
)
// Single select groupNovaChipGroup(
chips: ['All', 'Active', 'Completed'],
selectedIndex: _tab,
onChanged: (i) =>setState(() => _tab = i),
)
// Multi select groupNovaChipGroup.multi(
chips: ['Flutter', 'Dart', 'Firebase'],
selectedIndexes: _filters,
onMultiChanged: (i) =>setState(() => _filters = i),
)// Simple infoNovaToast.show(
context: context,
message:'Changes saved.',
)
// SuccessNovaToast.show(
context: context,
message:'Profile updated!',
type:NovaToastType.success,
)
// Error — top positionNovaToast.show(
context: context,
message:'Something went wrong.',
type:NovaToastType.error,
position:NovaToastPosition.top,
)// Custom contentNovaBottomSheet.show(
context: context,
title:'Edit Profile',
child:Column(
children: [
NovaTextField(label:'Name'),
NovaSpacing.gapMd,
NovaButton(text:'Save', onPressed: () {}),
],
),
)
// Actions listNovaBottomSheet.showActions(
context: context,
title:'Options',
actions: [
NovaSheetAction(
label:'Share',
icon:Icons.share_rounded,
onTap: () {},
),
NovaSheetAction(
label:'Delete',
icon:Icons.delete_outline_rounded,
isDestructive:true,
onTap: () {},
),
],
)MaterialApp(
theme:NovaTheme.light(),
darkTheme:NovaTheme.dark(),
themeMode:ThemeMode.system,
)
// Custom brand colorMaterialApp(
theme:NovaTheme.light(seedColor:Colors.teal),
darkTheme:NovaTheme.dark(seedColor:Colors.teal),
)// Semantic — theme-aware (dark mode automatic)
color:NovaColors.primary(context)
color:NovaColors.surface(context)
color:NovaColors.textSecondary(context)
color:NovaColors.success(context)
// Raw swatches
color:NovaColors.indigo[500]
color:NovaColors.slate[200]// Raw valuesSizedBox(height:NovaSpacing.md) // 16pxSizedBox(width:NovaSpacing.sm) // 8px// Gap widgets (vertical)NovaSpacing.gapSm // 8pxNovaSpacing.gapMd // 16pxNovaSpacing.gapLg // 24px// EdgeInsets helpers
padding:NovaSpacing.paddingMd // all sides 16px
padding:NovaSpacing.paddingPage // h:24 v:16
padding:NovaSpacing.paddingH(20) // horizontal onlyborderRadius:NovaRadius.sm // 8px
borderRadius:NovaRadius.md // 12px
borderRadius:NovaRadius.lg // 16px
borderRadius:NovaRadius.full // pill shapecontext.isDark // bool
context.novaPrimary // Color
context.novaSurface // Color
context.novaTextPrimary // Color
context.novaTextSecondary // Color
context.novaScheme // ColorScheme| Version | Widgets | Status |
|---|---|---|
| 1.0.0 | NovaButton, NovaTextField, NovaContainer | ✅ Released |
| 1.0.1 | NovaCard, NovaTheme, Dark mode | ✅ Released |
| 1.0.2 | README, LICENSE, Pub score 160/160 | ✅ Released |
| 1.0.3 | NovaLoader, NovaDialog, NovaBadge | ✅ Released |
| 1.0.4 | NovaShimmer, NovaAvatar, NovaChip | ✅ Released |
| 1.0.5 | NovaToast, NovaBottomSheet | ✅ Released |
| 1.0.6 | NovaDropdown, NovaCheckbox, NovaSwitch | 🔜 Coming Soon |
Contributions are welcome! Please open an issue first to discuss changes.
MIT © 2026 flutterbysunny

