Skip to main content

lycn_theme_engine 1.0.0 copy "lycn_theme_engine: ^1.0.0" to clipboard
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 ThemeData generation
  • 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.light
  • ThemeModeType.dark
  • ThemeModeType.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.

1
likes
160
points
343
downloads

Documentation

API reference

Publisher

unverified uploader

Weekly Downloads

A reusable Flutter theme engine with configurable color tokens, custom statuses, runtime theme editing, persistence, and JSON import/export.

Homepage
Repository (GitHub)
View/report issues

License

MIT (license)

Dependencies

flutter, shared_preferences

More

Packages that depend on lycn_theme_engine