best_theme 2.0.0 copy "best_theme: ^2.0.0" to clipboard
best_theme: ^2.0.0 copied to clipboard

Theme management package for Flutter with light and dark mode support.

Best Theme #


Best Theme is a powerful Flutter package designed to simplify theme management within your applications. It provides an intuitive way to define and switch between light and dark modes while allowing you to add your own custom colors with seamless context-based access — powered by Flutter's native ThemeExtension system.

Table of Contents #

Features #

  • ThemeExtension-based: Fully integrated with Flutter's native ThemeData.extensions system.
  • No object needed: Use MyThemeMaterial directly as your app root — no manual instantiation.
  • Custom Color Support: Define light and dark variants for each color in one place.
  • Customizable ThemeData: Override buildLightTheme / buildDarkTheme to set fonts, color schemes, and more.
  • Context-based Access: Access colors and theme controls directly via BuildContext extensions.
  • Custom extension name: Name your context getter via extensionName in the annotation.
  • GoRouter / declarative routing: Works seamlessly with any routing solution.

Installation #

flutter pub add best_theme
flutter pub add best_theme_annotation
flutter pub add dev:best_theme_generator
dart pub add dev:build_runner

Usage #

1. Create Theme File with Colors and Class Definition #

Create a theme file (e.g., my_theme.dart) and define your colors along with the theme class:

import 'package:best_theme/best_theme.dart';
import 'package:best_theme_annotation/best_theme_annotation.dart';
import 'package:flutter/material.dart';

part 'my_theme.g.dart';

// Define your colors — one entry per color with light and dark variants
List<BestColor> dataColor = [
  const BestColor(name: 'primary', light: Colors.blue,      dark: Colors.indigo),
  const BestColor(name: 'text',    light: Colors.black87,   dark: Colors.white70),
  const BestColor(name: 'card',    light: Color(0xffFCFCFC),dark: Color(0xff1E1E2A)),
];

// extensionName controls the BuildContext getter: context.appColors
@BestTheme(
  vars: ['primary', 'text', 'card'],
  extensionName: 'appColors',
)
class MyTheme extends _$MyTheme {
  MyTheme() : super(myColors: dataColor);
}

Run code generation:

dart run build_runner build -d

Or watch for changes:

dart run build_runner watch -d

2. Wrap Your App with MyThemeMaterial #

No object creation needed — just use the generated widget directly:

void main() {
  runApp(
    MyThemeMaterial(
      initialMode: ThemeMode.system,
      builder: (context, mode, lightTheme, darkTheme) => MaterialApp(
        title: 'My App',
        themeMode: mode,
        theme: lightTheme,
        darkTheme: darkTheme,
        home: const HomePage(),
      ),
    ),
  );
}

3. Using Custom Colors #

Access your colors anywhere through the context using the extensionName you set:

Container(
  decoration: BoxDecoration(
    color: context.appColors.card,
    border: Border.all(color: context.appColors.primary),
  ),
  child: Text(
    'Hello!',
    style: TextStyle(color: context.appColors.text),
  ),
);

4. Customize ThemeData (fonts, colors, etc.) #

Override buildLightTheme and/or buildDarkTheme in your class. The base parameter already has the color extension injected — just copyWith what you need:

@BestTheme(vars: ['primary', 'text', 'card'], extensionName: 'appColors')
class MyTheme extends _$MyTheme {
  MyTheme() : super(myColors: dataColor);

  @override
  ThemeData buildLightTheme(ThemeData base) => base.copyWith(
    fontFamily: 'Roboto',
    primaryColor: Colors.blue,
    appBarTheme: const AppBarTheme(elevation: 0, centerTitle: true),
    colorScheme: ColorScheme.light(primary: Colors.blue),
  );

  @override
  ThemeData buildDarkTheme(ThemeData base) => base.copyWith(
    fontFamily: 'Roboto',
    scaffoldBackgroundColor: const Color(0xFF0A1628),
    colorScheme: ColorScheme.dark(primary: Colors.indigo),
  );
}

5. Theme Control #

Use context extensions to toggle and set the theme from anywhere in the widget tree:

// Toggle between light and dark
context.toggleTheme();

// Set a specific mode
context.setThemeMode(ThemeMode.dark);
context.toDark();
context.toLight();

// Check current state
bool isDarkMode = context.isDark;

// Access Flutter ThemeData helpers
Color bg   = context.scaffoldBackgroundColor;
Color pri  = context.primary;
Color pri2 = context.primaryScheme;

6. Theme Toggle Switch Example #

Switch(
  value: context.isDark,
  onChanged: (_) => context.toggleTheme(),
);

7. Complete Example #

class HomePage extends StatelessWidget {
  const HomePage({super.key});

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        backgroundColor: context.appColors.primary,
        title: const Text('Best Theme Demo'),
        actions: [
          Switch(
            value: context.isDark,
            onChanged: (_) => context.toggleTheme(),
          ),
        ],
      ),
      body: Padding(
        padding: const EdgeInsets.all(16),
        child: Column(
          children: [
            Container(
              padding: const EdgeInsets.all(16),
              decoration: BoxDecoration(
                color: context.appColors.card,
                borderRadius: BorderRadius.circular(8),
                border: Border.all(color: context.appColors.primary),
              ),
              child: Text(
                'This adapts to your theme!',
                style: TextStyle(color: context.appColors.text),
              ),
            ),
            const SizedBox(height: 16),
            ElevatedButton(
              style: ElevatedButton.styleFrom(
                backgroundColor: context.appColors.primary,
              ),
              onPressed: () => context.setThemeMode(ThemeMode.light),
              child: const Text('Switch to Light'),
            ),
          ],
        ),
      ),
    );
  }
}

8. GoRouter Support #

Works with any router — just pass MaterialApp.router to the builder:

final _router = GoRouter(routes: [
  GoRoute(path: '/', builder: (_, __) => const HomePage()),
]);

void main() {
  runApp(
    MyThemeMaterial(
      initialMode: ThemeMode.system,
      builder: (context, mode, lightTheme, darkTheme) => MaterialApp.router(
        routerConfig: _router,
        themeMode: mode,
        theme: lightTheme,
        darkTheme: darkTheme,
      ),
    ),
  );
}

API Reference #

Context Extensions #

Extension Description
context.{extensionName}.{colorName} Access any defined custom color
context.isDark true when current brightness is dark
context.toggleTheme() Toggle between light and dark
context.setThemeMode(ThemeMode) Set a specific theme mode
context.toDark() Switch to dark mode
context.toLight() Switch to light mode
context.scaffoldBackgroundColor Current scaffold background color
context.primary Current Theme.primaryColor
context.primaryScheme Current colorScheme.primary

_$ClassName Overridable Hooks #

Method Description
buildLightTheme(ThemeData base) Override to customize light ThemeData
buildDarkTheme(ThemeData base) Override to customize dark ThemeData

Migration from 1.x (old version) #

For the old 1.0.2 documentation using the singleton approach, see the 1.0.2 README.

App setup #

Old (1.x):

// Needed a context wrapper method
class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return context.BestTheme(
      materialApp: MaterialApp(...),
    );
  }
}

New (2.0):

// Standalone widget — no StatelessWidget wrapper needed
void main() {
  runApp(
    MyThemeMaterial(
      builder: (context, mode, light, dark) => MaterialApp(
        themeMode: mode,
        theme: light,
        darkTheme: dark,
        home: const HomePage(),
      ),
    ),
  );
}

Color access #

Old (1.x):

context.myColors.color1

New (2.0):

context.appColors.color1  // uses your extensionName

Theme class definition #

Old (1.x):

class MyTheme extends _$MyTheme {
  MyTheme() : super(myColors: dataColor, mode: ThemeMode.system);
}

New (2.0):

class MyTheme extends _$MyTheme {
  MyTheme() : super(myColors: dataColor);

  @override
  ThemeData buildLightTheme(ThemeData base) => base.copyWith(fontFamily: 'Roboto');
}

Theme toggling #

Old (1.x):

context.toDarkTheme();
context.toLightTheme();
context.advanceToggle(ThemeMode.dark);

New (2.0):

context.toDark();
context.toLight();
context.setThemeMode(ThemeMode.dark);

Contributing #

We welcome contributions to the Best Theme package!

  1. Report Issues: Found a bug? Open an issue
  2. Request Features: Have an idea? Share it with us!

About the Developer #

This package was developed by Dosty Pshtiwan, a passionate Flutter developer dedicated to creating tools that make Flutter development easier and more enjoyable.

Connect with Dosty #

5
likes
160
points
64
downloads

Publisher

verified publisherdostypshtiwan.com

Weekly Downloads

Theme management package for Flutter with light and dark mode support.

Repository (GitHub)
View/report issues

Documentation

API reference

License

MIT (license)

Dependencies

flutter

More

Packages that depend on best_theme