# Theme Addon

The Theme Addon lets you inject a theme widget into your tree, to make your use-cases 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/main.dart
import 'package:my_app/themes.dart'; // For AppThemes
import 'package:widgetbook/widgetbook.dart';

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

  @override
  Widget build(BuildContext context) {
    return Widgetbook.material(
      // ...
      addons: [
        MaterialThemeAddon( // [!code highlight]
          themes: [ // [!code highlight]
            WidgetbookTheme( // [!code highlight]
              name: 'Light', // [!code highlight]
              data: AppThemes.light(), // [!code highlight]
            ), // [!code highlight]
            WidgetbookTheme( // [!code highlight]
              name: 'Dark', // [!code highlight]
              data: AppThemes.dark(), // [!code highlight]
            ), // [!code highlight]
          ], // [!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/main.dart
import 'package:my_app/themes.dart'; // For AppThemes
import 'package:widgetbook/widgetbook.dart';

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

  @override
  Widget build(BuildContext context) {
    return Widgetbook.cupertino(
      // ...
      addons: [
        CupertinoThemeAddon( // [!code highlight]
          themes: [ // [!code highlight]
            WidgetbookTheme( // [!code highlight]
              name: 'Light', // [!code highlight]
              data: AppThemes.light(), // [!code highlight]
            ), // [!code highlight]
            WidgetbookTheme( // [!code highlight]
              name: 'Dark', // [!code highlight]
              data: AppThemes.dark(), // [!code highlight]
            ), // [!code highlight]
          ], // [!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/main.dart
import 'dart:ui';
import 'package:my_app/theme.dart'; // For AppTheme
import 'package:my_app/themes.dart'; // For AppThemes
import 'package:widgetbook/widgetbook.dart';

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

  @override
  Widget build(BuildContext context) {
    return Widgetbook(
      // ...
      addons: [
        ThemeAddon<AppThemeData>( // [!code highlight]
          themes: [ // [!code highlight]
            WidgetbookTheme( // [!code highlight]
              name: 'Light', // [!code highlight]
              data: AppThemes.light(), // [!code highlight]
            ), // [!code highlight]
            WidgetbookTheme( // [!code highlight]
              name: 'Dark', // [!code highlight]
              data: AppThemes.dark(), // [!code highlight]
            ), // [!code highlight]
          ], // [!code highlight]
          themeBuilder: (context, theme, child) { // [!code highlight]
            // Wrap use cases 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`
- `DeviceFrameAddon`

## Multi-snapshot Support

The `ThemeAddon`s are supported in the [Multi Snapshot Reviews](/cloud/snapshots/multi-snapshot) via the `ThemeAddonConfig`. Here's how to configure it:

```dart title=widgetbook/lib/main.dart
import 'package:widgetbook/widgetbook.dart';
import 'package:widgetbook_annotation/widgetbook_annotation.dart';

@App(
  cloudAddonsConfigs: {
    'Light': [
      ThemeAddonConfig('Light'), // [!code highlight]
    ],
    'Dark': [
      ThemeAddonConfig('Dark'), // [!code highlight]
    ],
  },
)
class WidgetbookApp extends StatelessWidget {
  const WidgetbookApp({super.key});

  @override
  Widget build(BuildContext context) {
    return Widgetbook(
      // ...
      addons: [
        // Your theme addon of choice here... // [!code highlight]
      ],
    );
  }
}
```
