lycn_theme_engine 1.0.0
lycn_theme_engine: ^1.0.0 copied to clipboard
A reusable Flutter theme engine with configurable color tokens, custom statuses, runtime theme editing, persistence, and JSON import/export.
LYCN Theme Engine #
A reusable Flutter theme engine for managing configurable light, dark, and system themes with custom color tokens, dynamic statuses, runtime theme editing, persistence, JSON import/export, and bundled theme configuration.
Features #
- Light, dark, and system theme modes
- Built-in default theme configuration
- Custom color tokens
- Separate light and dark colors for tokens
- Dynamic status definitions and status colors
- Runtime theme customization
- Persistent runtime configuration
- JSON import and export
- Theme reset and seed reset
- Bundled theme configuration through
assets/theme_seed.json - Material 3
ThemeDatageneration - Built-in Theme Manager UI
- Reusable themed widgets
- Theme mode controls
- Customizable status labels
- Custom storage implementations
- Android, iOS, Windows, macOS, and Linux support
Installation #
Add lycn_theme_engine to your pubspec.yaml:
dependencies:
lycn_theme_engine: ^1.0.0
Then install the package:
flutter pub get
Quick Start #
Create a ThemeManager, initialize it, and provide it to LycnThemeApp:
import 'package:flutter/material.dart';
import 'package:lycn_theme_engine/lycn_theme_engine.dart';
Future<void> main() async {
WidgetsFlutterBinding.ensureInitialized();
final themeManager = ThemeManager();
await themeManager.initialize();
runApp(
LycnThemeApp(
manager: themeManager,
home: const HomePage(),
),
);
}
class HomePage extends StatelessWidget {
const HomePage({super.key});
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: const Text('LYCN Theme Engine'),
),
body: Center(
child: Text(
'Theme Engine Example',
style: TextStyle(
color: Theme.of(context).colorScheme.primary,
),
),
),
);
}
}
ThemeManager generates the light and dark ThemeData instances and controls the active Flutter theme mode.
Theme Modes #
LYCN Theme Engine supports three theme modes:
ThemeModeType.lightThemeModeType.darkThemeModeType.system
Set the theme mode at runtime:
await themeManager.setMode(ThemeModeType.dark);
For system-controlled theme mode:
await themeManager.setMode(ThemeModeType.system);
The Flutter ThemeMode can also be accessed through:
themeManager.flutterThemeMode
Built-in Theme Tokens #
The package includes a set of built-in color tokens for common application UI elements.
Examples include:
primary
secondary
tertiary
bg.scaffold
bg.surface
btn.confirm
btn.reject
btn.other
text.title
text.subtitle
text.description
text.other
border.enabled
border.disabled
border.other
status.default
Access commonly used colors directly from ThemeManager:
final primary = themeManager.primary;
final secondary = themeManager.secondary;
final scaffoldBackground = themeManager.bgScaffold;
final surfaceBackground = themeManager.bgSurface;
final titleColor = themeManager.textTitle;
final subtitleColor = themeManager.textSubtitle;
final confirmColor = themeManager.buttonConfirm;
final rejectColor = themeManager.buttonReject;
You can also resolve any token by its key:
final color = themeManager.color('primary');
Custom Color Tokens #
Applications can define their own color tokens in addition to the built-in tokens.
For example:
await themeManager.addOrUpdateToken(
TokenDef(
key: 'brand.accent',
label: 'Brand Accent',
),
lightColor: Colors.blue,
darkColor: Colors.lightBlue,
);
Resolve the custom token:
final accentColor = themeManager.color('brand.accent');
Custom tokens support separate light and dark colors.
Check Whether a Token Exists #
if (themeManager.hasToken('brand.accent')) {
final color = themeManager.color('brand.accent');
}
Get Token Definitions #
final tokens = themeManager.tokenDefs;
for (final token in tokens) {
print(token.key);
}
Remove a Custom Token #
await themeManager.removeToken('brand.accent');
Built-in locked tokens cannot be removed.
Dynamic Statuses #
LYCN Theme Engine supports dynamic application statuses.
A status contains:
- Actual value
- Display label
- Light-mode color
- Dark-mode color
Example:
await themeManager.addOrUpdateStatus(
StatusDef(
actualValue: 'SUCCESS',
displayLabel: 'Success',
lightColor: Colors.green,
darkColor: Colors.lightGreen,
),
);
Resolve a Status Color #
final color = themeManager.statusColor('SUCCESS');
Resolve a Status Label #
final label = themeManager.statusLabel('SUCCESS');
Check Whether a Status Exists #
if (themeManager.hasStatus('SUCCESS')) {
final color = themeManager.statusColor('SUCCESS');
}
Remove a Status #
await themeManager.removeStatus('SUCCESS');
Status colors are also exposed through automatically generated status.<ACTUAL_VALUE> tokens.
For example:
status.SUCCESS
status.PENDING
status.FAILED
Bundled Theme Configuration #
Applications can provide a theme configuration that is bundled into the consuming application's build.
Create:
assets/theme_seed.json
Then add the asset to the application's pubspec.yaml:
flutter:
assets:
- assets/theme_seed.json
A seed can contain the application's initial theme configuration, including:
- Theme mode
- Color token definitions
- Status definitions
- Light palette
- Dark palette
Initialize the manager using the seed:
final themeManager = ThemeManager();
await themeManager.initialize(
seed: const ThemeSeed(),
);
The default seed path is:
assets/theme_seed.json
A custom asset path can also be supplied:
await themeManager.initialize(
seed: const ThemeSeed(
assetPath: 'assets/my_theme.json',
),
);
Configuration Precedence #
Theme configuration is resolved in the following order:
Built-in defaults
↓
Bundled theme seed
↓
Saved runtime configuration
↓
Final active configuration
This means an application can ship a predefined theme while allowing users to customize it at runtime.
Saved runtime configuration takes precedence over the bundled seed.
Theme Reset #
Reset the theme to the built-in defaults:
await themeManager.reset();
Reset to the bundled seed configuration:
await themeManager.resetToSeed();
Clear saved runtime configuration and return to the bundled configuration:
await themeManager.clearSavedConfiguration();
Persistence #
Runtime theme configuration is persisted using SharedPreferences by default.
The default storage implementation is:
SharedPreferencesThemeStorage
The package also provides:
ThemeStorage
MemoryThemeStorage
Using Custom Storage #
Applications can implement ThemeStorage when a different persistence mechanism is required:
class MyThemeStorage implements ThemeStorage {
@override
Future<void> save(ThemeConfig config) async {
// Save configuration.
}
@override
Future<ThemeConfig?> load() async {
// Load configuration.
return null;
}
@override
Future<void> clear() async {
// Clear configuration.
}
}
Then provide the storage implementation to ThemeManager:
final themeManager = ThemeManager(
storage: MyThemeStorage(),
);
JSON Import and Export #
Theme configurations can be exported to JSON.
Export #
final json = themeManager.exportJson();
For compact JSON:
final json = themeManager.exportJson(
pretty: false,
);
Import #
final success = await themeManager.importJson(json);
if (success) {
print('Theme imported successfully');
}
Invalid JSON does not replace the current configuration.
The package also exposes ThemeJson for direct encoding and decoding of ThemeConfig objects.
Theme Manager UI #
The package includes a built-in Theme Manager screen for runtime theme configuration.
Open it using:
Navigator.of(context).push(
MaterialPageRoute(
builder: (_) => ThemeManagerScreen(
manager: themeManager,
),
),
);
The Theme Manager UI provides:
- Light and dark palette editing
- Theme mode selection
- Built-in token display
- Custom token creation
- Token color editing
- Token deletion for unlocked tokens
- Dynamic status creation
- Status editing
- Status color editing
- Status deletion
- Theme reset
- Reset to bundled seed
- Clear saved configuration
- JSON import
- JSON export
- Live theme preview
The UI adapts to different screen sizes.
Reusable Theme Widgets #
LYCN Theme Engine provides convenience widgets that resolve colors and statuses through the active ThemeManager.
Text #
TText.title('Page Title');
TText.subtitle('Subtitle');
TText.description('Description');
TText.other('Additional text');
Buttons #
TButton.confirm(
label: 'Save',
onPressed: () {},
);
TButton.reject(
label: 'Cancel',
onPressed: () {},
);
TButton.other(
label: 'Other Action',
onPressed: () {},
);
Custom token buttons are also supported:
TButton.token(
tokenKey: 'brand.accent',
label: 'Custom Action',
onPressed: () {},
);
Status Chips #
TChip.status('SUCCESS');
The status chip automatically resolves:
- Status color
- Status display label
from the active theme configuration.
Cards #
TCard(
child: Text('Content'),
);
Dividers #
TDivider();
Theme Mode Controls #
The package includes reusable theme mode controls.
Toggle #
ThemeModeToggle(
manager: themeManager,
);
The toggle cycles through:
Light → System → Dark → Light
Light/Dark Switch #
ThemeModeSwitch(
manager: themeManager,
);
Segmented Control #
ThemeModeSegmented(
manager: themeManager,
);
The segmented control provides:
Light | System | Dark
Using ThemeResolver #
For applications that need direct token and status resolution, the package provides ThemeResolver.
final resolver = ThemeResolver(themeManager.config);
final color = resolver.color('primary');
final statusColor = resolver.statusColor('SUCCESS');
final statusLabel = resolver.statusLabel('SUCCESS');
The resolver can also resolve colors for a specific theme mode:
final lightColor = resolver.color(
'primary',
mode: ThemeModeType.light,
);
final darkColor = resolver.color(
'primary',
mode: ThemeModeType.dark,
);
Theme Configuration Model #
A complete theme configuration consists of:
ThemeConfig
├── mode
├── token definitions
├── status definitions
├── light palette
└── dark palette
Example:
final config = ThemeConfig(
mode: ThemeModeType.system,
tokenDefs: const [
TokenDef(
key: 'brand.accent',
label: 'Brand Accent',
),
],
statuses: const [
StatusDef(
actualValue: 'SUCCESS',
displayLabel: 'Success',
lightColor: Color(0xFF16A34A),
darkColor: Color(0xFF4ADE80),
),
],
light: const {
'brand.accent': Color(0xFF2563EB),
},
dark: const {
'brand.accent': Color(0xFF60A5FA),
},
);
Application Integration #
A typical application structure can look like:
my_app/
├── assets/
│ └── theme_seed.json
├── lib/
│ ├── main.dart
│ └── ...
└── pubspec.yaml
pubspec.yaml:
dependencies:
flutter:
sdk: flutter
lycn_theme_engine: ^1.0.0
flutter:
assets:
- assets/theme_seed.json
main.dart:
import 'package:flutter/material.dart';
import 'package:lycn_theme_engine/lycn_theme_engine.dart';
Future<void> main() async {
WidgetsFlutterBinding.ensureInitialized();
final manager = ThemeManager();
await manager.initialize(
seed: const ThemeSeed(),
);
runApp(
LycnThemeApp(
manager: manager,
home: const HomePage(),
),
);
}
Supported Platforms #
LYCN Theme Engine is designed for:
- Android
- iOS
- Windows
- macOS
- Linux
Web is not currently a supported target.
Example Application #
The package repository contains an example Flutter application demonstrating the theme engine.
The example demonstrates:
- Theme initialization
- Bundled theme seed configuration
- Light/dark/system modes
- Custom tokens
- Dynamic statuses
- Runtime theme editing
- Theme Manager UI
- Reusable theme widgets
Testing #
The package includes unit and widget tests covering the core functionality.
Run the package tests:
flutter test
Run static analysis:
flutter analyze
For deterministic test execution in environments where test concurrency can cause runner issues:
flutter test --concurrency=1
Package Structure #
The main public API is available through:
import 'package:lycn_theme_engine/lycn_theme_engine.dart';
The package contains the following major components:
ThemeManager
ThemeResolver
ThemeConfig
TokenDef
StatusDef
ThemeSeed
ThemeStorage
ThemeJson
ThemeDataBuilder
LycnThemeApp
ThemeInitializer
ThemeManagerScreen
TText
TButton
TChip
TCard
TDivider
ThemeModeToggle
ThemeModeSwitch
ThemeModeSegmented
Version #
Current version:
1.0.0
Repository #
Source code, examples, tests, and issue tracking are available on GitHub:
https://github.com/LycnAlpha/lycn_theme_engine
License #
LYCN Theme Engine is released under the MIT License.
See the LICENSE file for the complete license text.