bolt_ui_kit 1.2.0
bolt_ui_kit: ^1.2.0 copied to clipboard
A comprehensive Flutter UI kit with pre-built components, themes, and utilities for rapid application development. Includes customizable buttons, forms, cards, and more.
Flutter Kit #
A comprehensive and modular Flutter UI kit that offers reusable widgets, themes, and utilities for rapid app development.
Features #
- Responsive Design: Built with
flutter_screenutil
for fully responsive UI across all devices - Dynamic Theming: Easily customize themes with your brand colors
- Modular Widgets: Pre-built, customizable UI components
- API Integration: Simplified API handling with error management
- Toast Notifications: Beautiful toast messages for user feedback
- Layouts: Flexible layout options for different UI needs
- Input Controls: Form components with validation support
- State Management: Built with GetX for efficient state management
- Storage Solutions: Persistent storage with easy-to-use interface
Installation #
Add Flutter Kit to your project by including it in your pubspec.yaml
:
dependencies:
bolt_ui_kit:
git:
url: https://github.com/DevMaan707/bolt_ui_kit.git
ref: main
Getting Started #
Initialize the Kit #
Before using any components, initialize the Flutter Kit with your app's colors and preferences:
void main() async {
WidgetsFlutterBinding.ensureInitialized();
await BoltKit.initialize(
primaryColor: Color(0xFF1976D2), // Your primary brand color
accentColor: Color(0xFF64B5F6), // Your accent/secondary color
fontFamily: 'Poppins', // Optional: Default font family
);
runApp(MyApp());
}
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return FlutterKit.builder(
builder: () => GetMaterialApp(
title: 'My App',
theme: AppTheme.lightTheme(),
darkTheme: AppTheme.darkTheme(),
themeMode: ThemeMode.system,
home: HomeScreen(),
),
);
}
}
Components Usage #
Buttons #
// Primary Button
Button(
text: 'Sign In',
type: ButtonType.primary,
onPressed: () => handleSignIn(),
)
// Secondary Button
Button(
text: 'Cancel',
type: ButtonType.secondary,
onPressed: () => Navigator.pop(context),
)
// Outlined Button
Button(
text: 'View Details',
type: ButtonType.outlined,
onPressed: () => viewDetails(),
)
// Button with icon
Button(
text: 'Add to Cart',
type: ButtonType.primary,
icon: Icons.shopping_cart,
onPressed: () => addToCart(),
)
// Loading Button
Button(
text: 'Processing...',
type: ButtonType.primary,
isLoading: true,
onPressed: null,
)
Cards #
// Standard Card
AppCard(
child: Text('This is a standard card'),
)
// Elevated Card
AppCard(
type: CardType.elevated,
child: Text('This is an elevated card with more shadow'),
)
// Outlined Card
AppCard(
type: CardType.outlined,
child: Text('This is an outlined card without shadow'),
)
// Interactive Card
AppCard(
onTap: () => handleCardTap(),
child: Text('Tap this card'),
)
// Custom Card
AppCard(
backgroundColor: Colors.blue.shade50,
borderRadius: BorderRadius.circular(16),
padding: EdgeInsets.all(24),
child: Text('Custom styled card'),
)
Toast Notifications #
// Success Toast
Toast.show(
message: 'Profile updated successfully!',
type: ToastType.success,
)
// Error Toast
Toast.show(
message: 'Failed to connect to server',
type: ToastType.error,
)
// Info Toast
Toast.show(
message: 'New message received',
type: ToastType.info,
)
// Warning Toast
Toast.show(
message: 'Your subscription will expire soon',
type: ToastType.warning,
)
// Custom Toast
Toast.show(
message: 'Custom notification',
type: ToastType.info,
title: 'Important Update',
duration: Duration(seconds: 5),
position: Alignment.topCenter,
dismissible: false,
)
Pickers & Selectors #
Flutter Kit includes beautiful, customizable pickers that follow your app's theme for consistent UI:
Date & Time Pickers #
// Date picker with theme-consistent styling
final date = await DatePickerUtil.showCustomDatePicker(
initialDate: DateTime.now(),
firstDate: DateTime(2000),
lastDate: DateTime(2100),
helpText: 'Select Date',
confirmText: 'Choose',
cancelText: 'Cancel',
);
// Date range picker
final dateRange = await DatePickerUtil.showCustomDateRangePicker(
initialDateRange: DateTimeRange(
start: DateTime.now(),
end: DateTime.now().add(Duration(days: 7)),
),
helpText: 'Select Date Range',
);
// Time picker with themed UI
final time = await TimePickerUtil.showCustomTimePicker(
initialTime: TimeOfDay.now(),
helpText: 'Select Time',
use24HourFormat: false,
);
// Duration picker
final duration = await TimePickerUtil.showDurationPicker(
initialDuration: Duration(minutes: 30),
showHours: true,
showMinutes: true,
showSeconds: true,
);
Calendar Picker #
// Single date selection
final result = await CalendarPickerUtil.showCalendarPicker(
mode: CalendarPickerMode.single,
primaryColor: AppColors.primary,
selectedColor: AppColors.accent,
title: 'Select Date',
);
// Multiple dates selection
final result = await CalendarPickerUtil.showCalendarPicker(
mode: CalendarPickerMode.multi,
initialSelectedDates: [DateTime.now()],
title: 'Select Multiple Dates',
);
// Date range selection
final result = await CalendarPickerUtil.showCalendarPicker(
mode: CalendarPickerMode.range,
title: 'Select Date Range',
);
File & Media Pickers #
// Image picker with beautiful UI
final image = await ImagePickerUtil().showCustomImagePicker(
enableCrop: true,
cropSettings: CropSettings.square(
primaryColor: AppColors.primary,
),
);
// File picker with custom UI
final file = await FilePickerUtil().showCustomFilePicker(
context: context,
title: 'Select File',
primaryColor: AppColors.primary,
);
// QR Scanner with animated UI
final result = await QRScannerUtil().scanQR(
title: 'Scan QR Code',
scanInstructions: 'Position the QR code within the frame',
primaryColor: AppColors.primary,
);
Simplified Access #
// Quick access through the AppPickers utility class
final date = await AppPickers.pickDate();
final time = await AppPickers.pickTime();
final image = await AppPickers.pickImageWithDialog();
final qrCode = await AppPickers.scanQR();
final dateRange = await AppPickers.pickDateRange();
final dates = await AppPickers.pickMultipleDates();
Input Forms #
// Text Input
AppInput(
label: 'Username',
hint: 'Enter your username',
prefixIcon: Icons.person,
onChanged: (value) => updateUsername(value),
)
// Password Input
AppInput(
label: 'Password',
hint: 'Enter your password',
prefixIcon: Icons.lock,
type: InputType.password,
onChanged: (value) => updatePassword(value),
)
// Email Input with validation
AppInput(
label: 'Email',
hint: 'Enter your email address',
type: InputType.email,
validator: (value) {
if (value == null || value.isEmpty) {
return 'Email is required';
}
if (!value.contains('@')) {
return 'Enter a valid email address';
}
return null;
},
)
// Multiline Input
AppInput(
label: 'Notes',
hint: 'Enter additional notes',
type: InputType.multiline,
maxLines: 5,
)
Complete Form #
AppForm(
formKey: _formKey,
onSubmit: () => handleFormSubmit(),
submitLabel: 'Create Account',
children: [
AppInput(
label: 'Full Name',
hint: 'Enter your full name',
prefixIcon: Icons.person,
validator: (value) => value!.isEmpty ? 'Name is required' : null,
),
AppInput(
label: 'Email',
hint: 'Enter your email',
type: InputType.email,
prefixIcon: Icons.email,
validator: (value) => !value!.contains('@') ? 'Invalid email' : null,
),
AppInput(
label: 'Password',
hint: 'Create a password',
type: InputType.password,
prefixIcon: Icons.lock,
validator: (value) => value!.length < 6
? 'Password must be at least 6 characters'
: null,
),
],
)
Layouts #
// Standard Layout
AppLayout(
type: AppLayoutType.standard,
padding: EdgeInsets.all(16),
child: Center(child: Text('Standard Layout')),
)
// Scrollable Layout
AppLayout(
type: AppLayoutType.scroll,
padding: EdgeInsets.all(16),
child: Column(
children: [
// Long content here
],
),
)
// Safe Area Layout
AppLayout(
type: AppLayoutType.safeArea,
padding: EdgeInsets.all(16),
child: Text('Protected from notches and system UI'),
)
// Constrained Width Layout (good for tablets/web)
AppLayout(
type: AppLayoutType.constrained,
padding: EdgeInsets.all(16),
child: Text('Width constrained layout'),
)
API Service #
// Initialize API Service
final apiService = ApiService('https://api.example.com');
// GET Request
Future<void> fetchUsers() async {
try {
final response = await apiService.get(
endpoint: '/users',
queryParams: {'page': '1', 'limit': '10'},
);
// Process response data
final users = response as List<dynamic>;
print('Fetched ${users.length} users');
} catch (e) {
print('Error fetching users: $e');
}
}
// POST Request
Future<void> createUser() async {
try {
final response = await apiService.post(
endpoint: '/users',
body: {
'name': 'John Doe',
'email': 'john@example.com',
},
);
print('User created with ID: ${response['id']}');
} catch (e) {
print('Error creating user: $e');
}
}
// Safe Request (with automatic error handling)
Future<void> safeGetUsers() async {
final users = await apiService.safeRequest<List<dynamic>>(
request: () => apiService.get(endpoint: '/users'),
defaultValue: [],
);
print('Safely fetched ${users?.length ?? 0} users');
}
Using AppNavbar #
Scaffold(
appBar: Navbar(
title: 'Dashboard',
style: NavbarStyle.standard,
actions: [
IconButton(
icon: Icon(Icons.notifications),
onPressed: () => showNotifications(),
),
],
),
body: AppLayout(
// Content here
),
)
// Transparent Navigation Bar
Navbar(
title: 'Product Details',
style: NavbarStyle.transparent,
iconColor: Colors.white,
titleColor: Colors.white,
)
// Elevated Navigation Bar
Navbar(
title: 'Settings',
style: NavbarStyle.elevated,
centerTitle: false,
)
Using Theme Colors and Typography #
Container(
color: AppColors.primary,
child: Text(
'Primary Color Background',
style: AppTextThemes.heading5(color: Colors.white),
),
)
Text(
'This is a body text',
style: AppTextThemes.bodyMedium(),
)
Text(
'Error message',
style: AppTextThemes.bodySmall(color: AppColors.error),
)
Working with Storage Service #
// Initialize is handled automatically by FlutterKit.initialize()
final storage = Get.find<StorageService>();
// Store a value
await storage.write('user_id', '12345');
// Read a value
String? userId = storage.read<String>('user_id');
// Store a complex object
await storage.writeObject('user_profile', userProfile);
// Read a complex object
UserProfile? profile = storage.readObject<UserProfile>(
'user_profile',
(json) => UserProfile.fromJson(json),
);
Advanced Customization #
Custom Colors #
You can access and override the default colors after initialization:
// Override colors after initialization
AppColors.success = Colors.green.shade800;
AppColors.error = Colors.red.shade900;
Custom Text Styles #
// Create a custom text style based on the app's theme
final customStyle = AppTextThemes.bodyLarge(
color: AppColors.primary,
fontWeight: FontWeight.w700,
);
Text('Custom styled text', style: customStyle);
Navigation #
// Basic navigation
NavigationService.push(DetailsScreen());
// Named route navigation
NavigationService.pushNamed('/details', arguments: {'id': '123'});
// Replace current screen
NavigationService.pushReplacement(NewScreen());
// Clear stack and navigate
NavigationService.pushAndRemoveUntil(HomeScreen());
// Go back
NavigationService.pop();
API Service #
The ApiService
class provides a robust HTTP client implementation using Dio with built-in logging, error handling, and retry logic.
Usage #
// Initialize the API service
final apiService = ApiService('https://api.example.com');
// Make GET request
final response = await apiService.get(
endpoint: '/users',
queryParams: {'page': 1},
headers: {'Authorization': 'Bearer token'},
);
// Make POST request
final response = await apiService.post(
endpoint: '/users',
body: {'name': 'John Doe'},
);
// Make PUT request
final response = await apiService.put(
endpoint: '/users/1',
body: {'name': 'John Doe Updated'},
);
// Make DELETE request
final response = await apiService.delete(
endpoint: '/users/1',
);
// Safe request with error handling
final result = await apiService.safeRequest<User>(
request: () => apiService.get(endpoint: '/users/1'),
defaultValue: null,
);
Features #
- Automatic error handling and logging
- Request/response interceptors
- Timeout handling
- Pretty printing of requests/responses
- Toast notifications for errors
- Type-safe responses
- Customizable base URL and timeout settings
New Widgets #
PDF Viewer #
The BoltPDFViewer
widget provides a feature-rich PDF viewer with navigation controls and customization options.
// Show PDF from file
BoltPDFViewer.showPdfDialog(
context: context,
filePath: 'assets/document.pdf',
title: 'Document Viewer',
);
// Show PDF from URL
BoltPDFViewer.openPdf(
context: context,
url: 'https://example.com/document.pdf',
enableNavigation: true,
);
Features:
- File, network and asset source support
- Navigation controls
- Page counter
- Full-screen mode
- Custom toolbar actions
- Error handling
- Loading states
- Dark mode support
Slides Viewer #
The BoltSlidesViewer
widget allows viewing presentations in various formats with a rich set of controls.
// Show Google Slides
BoltSlidesViewer.showSlidesDialog(
context: context,
googleSlidesId: 'presentation_id',
title: 'Presentation',
);
// Open PowerPoint file
BoltSlidesViewer.openSlidesViewer(
context: context,
filePath: 'presentation.pptx',
sourceType: SlidesSourceType.pptx,
);
Features:
- Support for multiple formats (PDF, PPTX, Google Slides)
- Navigation controls
- Slide counter
- Full-screen presentation mode
- Auto-conversion to PDF
- Network file support
- Custom toolbar actions
- Error handling
- Loading states
- Dark mode support
Input Components #
PinInput
// Basic PIN input
BoltPinInput(
length: 6,
onCompleted: (pin) => print('PIN: $pin'),
);
// Custom styled PIN dialog
showPinInputDialog(
context: context,
title: 'Enter PIN',
length: 4,
theme: PinInputTheme.outlined,
);
Features:
- Multiple visual themes
- Customizable styling
- Error handling
- Secure input mode
- Dialog helper
- Validation support
- Custom keyboard types
The library also includes other components like:
- File picker with preview
- Image picker with cropping
- Date/time pickers
- Calendar picker
- QR code scanner
All components are designed to be customizable, responsive and support both light and dark themes.
Best Practices #
-
Initialize Early: Call
FlutterKit.initialize()
as early as possible in your app lifecycle. -
Consistent Typography: Use the provided text themes for consistent typography throughout your app.
-
Responsive Design: Always use screenutil's responsive units (
.w
,.h
,.sp
) for dimensions. -
Error Handling: Use the API service's
safeRequest
method to simplify error handling. -
Form Validation: Leverage the built-in form validation capabilities of
AppInput
andAppForm
. -
Theme Extensions: Extend the theme as needed by creating your own theme extension classes.
Requirements #
- Flutter SDK: >=2.17.0
- Dart SDK: >=2.17.0
Dependencies #
- flutter_screenutil: ^5.7.0
- get: ^4.6.5
- get_storage: ^2.1.1
- google_fonts: ^5.1.0
- dio: ^5.3.2
- intl: ^0.18.1
License #
This project is licensed under the MIT License - see the LICENSE file for details.
For more detailed information and examples, check out the documentation.