LogoWidgetbook

Custom Theme in widgetbook

Widgetbook provides comprehensive support for custom themes. This document will guide you through creating a custom theme for your Flutter widgets and integrating it into Widgetbook. Let's delve into how you can define and use custom themes to enhance your development and testing experience.

Creating a Custom Theme#

To create a custom theme, you must first define a class for your theme data. For instance, consider the AppThemeData class:

class AppThemeData {
  AppThemeData({
    required this.color,
  });

  final Color color;
}

In this example, the AppThemeData class holds one property, color. You can extend this class to include additional properties like typography, icon themes, or anything else you need for your theme.

Using the Custom Theme in Widgets#

Widgets can consume this theme data using an InheritedWidget. The InheritedWidget holds the theme data and exposes it through a static of method. Here's an example of an InheritedWidget for our custom theme:

class AppTheme extends InheritedWidget {
  const AppTheme({
    required this.data,
    required Widget child,
    super.key,
  }) : super(
          child: child,
        );

  final AppThemeData data;

  static AppThemeData of(BuildContext context) {
    final widget = context.dependOnInheritedWidgetOfExactType<AppTheme>();
    return widget!.data;
  }

  @override
  bool updateShouldNotify(covariant AppTheme oldWidget) {
    return data != oldWidget.data;
  }
}

Your widgets can use the custom theme through this InheritedWidget. For instance, the AwesomeWidget below uses the theme data to define its color:

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

  @override
  Widget build(BuildContext context) {
    return ColoredBox(
      color: AppTheme.of(context).color,
      child: Center(
        child: Text(
          '$AwesomeWidget',
          style: TextStyle(
            color: AppTheme.of(context).color.computeLuminance() > 0.5
                ? Colors.black
                : Colors.white,
          ),
        ),
      ),
    );
  }
}

Integrating Custom Themes with Widgetbook#

Widgetbook offers full support for custom themes. To add your custom themes to Widgetbook, use the ThemeAddon in your Widgetbook definition:

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

  @override
  Widget build(BuildContext context) {
    return Widgetbook(
      addons: [
        ThemeAddon<AppThemeData>(
          themes: [
            WidgetbookTheme(
              name: 'Blue',
              data: AppThemeData(
                color: Colors.blue,
              ),
            ),
            WidgetbookTheme(
              name: 'Yellow',
              data: AppThemeData(
                color: Colors.yellow,
              ),
            ),
          ],
          themeBuilder: (context, theme, child) {
            // Wrap use cases with the custom theme's InheritedWidget
            return AppTheme(
              data: theme,
              child: child,
            );
          },
        ),
      ],
      directories: [
        WidgetbookComponent(
          name: 'Awesome Widget',
          useCases: [
            WidgetbookUseCase(
              name: 'Default',
              builder: (context) => const AwesomeWidget(),
            )
          ],
        )
      ],
    );
  }
}

In this ThemeAddon, we defined two themes: 'Blue' and 'Yellow.' Each theme is represented by an instance of WidgetbookTheme, which requires a name and data.

The data should be an instance of your custom theme data class. The themeBuilder argument takes a function that wraps the widget displayed with the InheritedWidget that exposes the theme data.

By integrating your custom themes into Widgetbook, you can conveniently switch between themes in the Widgetbook UI. This facilitates testing your widgets under different themes, ultimately aiding the development and debugging process.

That's it! You have successfully created and integrated a custom theme in Widgetbook. With custom themes, you can ensure that your widgets look and behave as expected under different theme conditions.