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.
See source code