Theme Addon

The Theme Addon lets you preview your use-cases in different themes. This ensures that your components maintain their look and feel, consistent with the design language of your application.

ThemeAddon<AppThemeData>(
  themes: [
    WidgetbookTheme(
      name: 'Light',
      data: yourCustomLightTheme,
    ),
    WidgetbookTheme(
      name: 'Dark',
      data: yourCustomDarkTheme,
    ),
  ],
  themeBuilder: (context, theme, child) {
    return AppTheme(
      data: theme,
      child: child,
    );
  },
)

ThemeAddon comes with two variants (MaterialThemeAddon and CupertinoThemeAddon), that can be used as follows:

Material Theme Addon

The Material Theme Addon lets you apply your Material themes, based on the ThemeData class, to the components you're previewing. The MaterialThemeAddon class requires a themes property, which lists the available themes.

An optional property initialTheme can be defined to specify which theme should be active when the application starts. Here's an example of how you can use the Material Theme Addon.

Here's an example of how you can use the Material Theme Addon:

MaterialThemeAddon(
  themes: [
    WidgetbookTheme(
      name: 'Light',
      data: yourMaterialLightTheme,
    ),
    WidgetbookTheme(
      name: 'Dark',
      data: yourMaterialDarkTheme,
    ),
  ],
  initialTheme: WidgetbookTheme(
    name: 'Light',
    data: yourMaterialLightTheme,
  ),
),

In this example, we have defined two themes: 'Light' and 'Dark'. The name property is a user-friendly name that will be displayed in the Widgetbook user interface. The data property corresponds to the actual ThemeData for each theme. The 'Light' theme is the initial theme when the application starts.

Once you've set up your themes in this way, Widgetbook will provide an interface to switch between these themes, allowing you to preview how your components will look under different themes quickly.

Cupertino Theme Addon

The Cupertino Theme Addon enables you to implement your Cupertino themes based on the CupertinoThemeData class.

The CupertinoThemeAddon class necessitates a themes property to enumerate the available themes. Additionally, an initialTheme can be specified to set which theme should be active at the application's start.

Here's an example:

Example: CupertinoThemeAddon
CupertinoThemeAddon(
  themes: [
    WidgetbookTheme(
      name: 'Light',
      data: yourCupertinoLightTheme,
    ),
    WidgetbookTheme(
      name: 'Dark',
      data: yourCupertinoDarkTheme,
    ),
  ],
  initialTheme: WidgetbookTheme(
    name: 'Light',
    data: yourCupertinoLightTheme,
  ),
),

In this scenario, two themes: 'Light' and 'Dark', are defined. The name property is a human-readable name displayed in the Widgetbook user interface.

The data property corresponds to the actual CupertinoThemeData for each theme. 'Light' is selected as the initial theme when the application launches.

Custom Theme Addon

Widgetbook also supports defining entirely custom themes in addition to Material and Cupertino themes.

Assume you have defined a very simple custom theme AppThemeData that includes just a single color.

The AppThemeData class can be compared with the ThemeData class for the Material design system or the CupertinoThemeData class for the Cupertino design system.

Example: AppThemeData
class AppThemeData {
  final Color color;

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

This AppThemeData object must now be injected into the Widget tree, which is typically accomplished using an InheritedWidget. For instance, you could define an AppTheme InheritedWidget to inject your custom theme into the Widget tree.

The AppTheme widget can be compared with the Theme Widget for the Material design system or the CupertinoTheme Widget for the Cupertino design system.

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

  final AppThemeData data;

  // Access the theme's data using AppTheme.of(context)
  static AppThemeData of(BuildContext context) {
    final widget = context.dependOnInheritedWidgetOfExactType<AppTheme>();
    return widget!.data;
  }

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

Moreover, we define two custom theme instances:

Example: Custom themes
final blueTheme = AppThemeData(
  color: Colors.blue,
);

final yellowTheme = AppThemeData(
  color: Colors.yellow,
);

The ThemeAddon requires two properties. The themes property defines which themes are available while the initialTheme property defines which theme is active and selected.

Example: ThemeAddon
ThemeAddon<AppThemeData>(
  initialTheme: blueTheme,
  themes: [
    blueTheme,
    yellowTheme,
  ],
  themeBuilder: (context, theme, child) {
    return AppTheme(
      data: theme,
      child: child,
    );
   }
);