smart_lib_theme 1.0.4
smart_lib_theme: ^1.0.4 copied to clipboard
A Flutter theme management library for dynamic theme switching with BLoC and ThemeExtension.
π¨ SmartLib Theme - Effortless Flutter Theme Management #
A zero-boilerplate, BLoC-powered Flutter theme management library that makes it incredibly simple to create, switch, and customize themesβlight, dark, or any style you dream of!
π Why Use This Library? #
- β One-time setup: Initialize once, then forget about theme plumbing.
- β Custom themes made simple: Create themes with your brand colors in seconds.
- β Dynamic switching: Switch themes anywhere in your app with a single line of code.
- β Persistent themes: Themes stay saved across app restarts.
- β Scalable: Supports dozens of themes without performance issues.
Theming your Flutter project as Master #
Based on a Medium article by Karo Hovhannisyan β one of the most skilled mobile architects in the industry β this library is perfect for apps that need flexible theming with zero complexity.
π¦ Built With #
- Flutter (v3.7.2+)
- BLoC for state management
- SharedPreferences for persistence
- ThemeExtension for custom design tokens
π Quick Start Guide #
0. TL;DR #
Key Methods:
await AppThemeManager.init(themes: [])
- Wrap
MaterialApp
withAppThemeBuilder(theme: theme)
AppThemeManager.changeTheme(context: context, themeKey: 'key')
AppThemeManager.getCurrentTheme(context: context)
// Always returns the updated theme
1. Install the Package #
Add to pubspec.yaml
:
dependencies:
smart_lib_theme: ^0.1.0 # Replace with latest version
Then run:
flutter pub get
2. Initialize the Theme Manager #
In your main.dart
, define supported themes:
import 'package:flutter/material.dart';
import 'package:smart_lib_theme/core/theme/default/themes.dart';
import 'package:smart_lib_theme/features/theme/presentation/app_theme_manager.dart';
import 'package:smart_lib_theme/features/theme/presentation/widgets/app_theme_builder.dart';
Future<void> main() async {
await AppThemeManager.init(themes: [
AppTheme(key: 'light', themeData: AppDefaultThemesData().light),
AppTheme(key: 'dark', themeData: AppDefaultThemesData().dark),
]);
runApp(const MyApp());
}
β Replace
AppDefaultThemesData()
with your custom theme class (see below).
3. Wrap Your App with AppThemeBuilder
#
Ensures dynamic theme updates across the entire UI:
class MyApp extends StatelessWidget {
const MyApp({super.key});
@override
Widget build(BuildContext context) {
return AppThemeBuilder(
builder: (theme) {
return MaterialApp(
title: 'Themed App',
theme: theme, // <-- Dynamic theme applied here
home: const HomePage(),
);
},
);
}
}
π§ One-time setup: Done once, works forever.
4. Switch Themes Dynamically #
From any widget, change themes by passing the theme key:
GestureDetector(
onTap: () {
AppThemeManager.changeTheme(context: context, themeKey: 'dark');
},
child: Text('Switch to Dark Mode'),
)
π The UI updates instantly thanks to BLoC and
ThemeExtension
.
β οΈ If thethemeKey
doesnβt exist,ThemeExceptionConstants.notFoundKey
is thrown.
5. Access Theme Colors & Styles #
Use BuildContext
extensions for colors and text styles:
Text(
'Styled Text',
style: context.textTheme().titleLarge?.copyWith(
color: context.appColors().onPrimary,
),
),
Container(
color: context.appColors().surface,
child: Text('Surface Background'),
),
π¨ All tokens (colors, shapes, text styles) are available via
context.appColors()
andcontext.textTheme()
.
π¨ Create Custom Themes #
1. Define Your Own Colors #
Extend AppThemeExtension
to define your brand palette:
class MyCustomThemeExtension extends AppThemeExtension {
MyCustomThemeExtension()
: super(
primary: Colors.purple,
onPrimary: Colors.white,
secondary: Colors.tealAccent,
onSecondary: Colors.black,
// Override other tokens as needed
);
}
2. Use Custom Themes in Initialization #
Replace defaults with your custom themes:
await AppThemeManager.init(themes: [
AppTheme(key: 'custom', themeData: ThemeData(
extensions: [MyCustomThemeExtension()],
colorScheme: ColorScheme.fromSeed(seedColor: Colors.purple),
)),
]);
π― Now use
AppThemeManager.changeTheme(context, themeKey: 'custom')
to switch to your theme!
π§ͺ Example: Theme Switcher UI #
class HomePage extends StatelessWidget {
const HomePage({super.key});
@override
Widget build(BuildContext context) {
return Scaffold(
backgroundColor: context.appColors().surface,
body: Column(
children: [
const SizedBox(height: 300),
Center(
child: GestureDetector(
onTap: () => AppThemeManager.changeTheme(context: context, themeKey: 'light'),
child: Text('Light Theme'),
),
),
const SizedBox(height: 100),
Center(
child: GestureDetector(
onTap: () => AppThemeManager.changeTheme(context: context, themeKey: 'dark'),
child: Text('Dark Theme', style: context.textTheme().bodyMedium),
),
),
],
),
);
}
}
π¦ Folder Structure (Clean Architecture) #
lib/
βββ core/ # Shared utilities (ThemeExtension, default themes)
β βββ theme/
β βββ default/ # Default light/dark themes
β βββ extensions/ # ThemeExtension definitions
β βββ data/ # Component-specific styling (buttons, text, etc.)
βββ features/
β βββ theme/
β βββ domain/ # Entities, use cases
β βββ data/ # Repository + SharedPreferences impl
β βββ presentation/ # BLoC, widgets, manager
βββ di/ # Dependency injection
π License #
MIT License β see LICENSE for details.
π€ Contributing #
Feel free to open issues or PRs! See CONTRIBUTING.md for guidelines.
π¬ Feedback #
Have questions or suggestions? Reach out on GitHub or email me at dallakyanvanik@gmail.com. #
β¨ Maintained by Vanik Dallakyan #
Made with β€οΈ for Flutter developers everywhere.