# Theme Addon

The Theme Addon lets you inject a theme widget into your tree, to make your stories styled and try them out with different themes.
There are 3 different variants of the Theme Addon, which depend on the theme data and widget you use in your application:

| Addon                 | Theme Data           | Inherited Widget |
| --------------------- | -------------------- | ---------------- |
| `MaterialThemeAddon`  | `ThemeData`          | `Theme`          |
| `CupertinoThemeAddon` | `CupertinoThemeData` | `CupertinoTheme` |
| `ThemeAddon`          | Custom               | Custom           |

<Tabs
  values={[
    { label: "Dark Theme", value: "dark" },
    { label: "Light Theme", value: "light" },
  ]}
>
  <TabItem value="dark">
    <iframe
      src="https://demo.widgetbook.io/#/?path=features/basket/basketscreen/default&device={name:None}&locale={name:en}&theme={name:Dark}&preview"
      width="100%"
      height="720px"
    />
  </TabItem>
  <TabItem value="light">
    <iframe
      src="https://demo.widgetbook.io/#/?path=features/basket/basketscreen/default&device={name:None}&locale={name:en}&theme={name:Light}&preview"
      width="100%"
      height="720px"
    />
  </TabItem>
</Tabs>

## Usage

### Material Theme

If your app is built using `MaterialApp`, then you are probably using `ThemeData` to define your themes. Then `MaterialThemeAddon` is the right choice for you.

```dart title=widgetbook/lib/widgetbook.config.dart
import 'package:my_app/themes.dart'; // For AppThemes

final config = Config(
  // ...
  addons: [
    MaterialThemeAddon({ // [!code highlight]
      'Light': AppThemes.light(), // [!code highlight]
      'Dark': AppThemes.dark(), // [!code highlight]
    }), // [!code highlight]
  ],
);
```

### Cupertino Theme

If your app is built using `CupertinoApp`, then you are probably using `CupertinoThemeData` to define your themes. Then `CupertinoThemeAddon` is the right choice for you.

```dart title=widgetbook/lib/widgetbook.config.dart
import 'package:my_app/themes.dart'; // For AppThemes

final config = Config(
  // ...
  addons: [
    CupertinoThemeAddon({ // [!code highlight]
      'Light': AppThemes.light(), // [!code highlight]
      'Dark': AppThemes.dark(), // [!code highlight]
    }), // [!code highlight]
  ],
);
```

### Custom Theme

If you have a custom theme data and widget or you have a custom logic to build your theme, then `ThemeAddon` is the right choice for you.

<Accordion title="App Custom Theme">

```dart title='lib/theme.dart'
// Custom theme data
class AppThemeData {
  AppThemeData(this.color);

  final Color color;
}

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

  final AppThemeData data;

  // To 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;
  }
}
```

</Accordion>

```dart title=widgetbook/lib/widgetbook.config.dart
import 'dart:ui';
import 'package:my_app/theme.dart'; // For AppTheme
import 'package:my_app/themes.dart'; // For AppThemes

final config = Config(
  // ...
  addons: [
    ThemeAddon<AppThemeData>( // [!code highlight]
      { // [!code highlight]
        'Light': AppThemes.light(), // [!code highlight]
        'Dark': AppThemes.dark(), // [!code highlight]
      }, // [!code highlight]
      (context, theme, child) { // [!code highlight]
        // Wrap stories with the custom theme's InheritedWidget // [!code highlight]
        return AppTheme( // [!code highlight]
          data: theme, // [!code highlight]
          child: child, // [!code highlight]
        ); // [!code highlight]
      }, // [!code highlight]
    ), // [!code highlight]
  ],
);
```

## Order

Since the [order of addons](/addons/overview#order-of-addons) matters, here are some guidelines to follow when using the `ThemeAddon`:

Addons that should come before the `ThemeAddon`:

- `ViewportAddon`

## Mode

Each addon has a corresponding [Mode](/addons/modes) to lock its value in scenarios. For this addon, use the theme mode matching your addon variant:

```dart
final $Default = _Story(
  scenarios: [
    _Scenario(
      name: 'Dark Theme',
      modes: [
        // Use one of the following based on your addon
        MaterialThemeMode('Dark', ThemeData.dark()), // [!code highlight]
        CupertinoThemeMode('Dark', CupertinoThemeData(brightness: Brightness.dark)), // [!code highlight]
        ThemeMode('Dark', myAppTheme, myAppThemeBuilder), // [!code highlight]
      ]
    ),
  ],
)
```
