Available annotations

The widgetbook_annotation package defines the annotations @WidgetbookApp, @WidgetbookUseCase, and @WidgetbookTheme. The annotations and their usage are explained below.

@WidgetbookApp

The annotation @WidgetbookApp has to be set only once and is mandatory for the code generation process. It is not important which element is annotated, but the location of the file in which @WidgetbookApp is used, defines the folder in which package:widgetbook_generator will create the file app.widgetbook.main. The app.widgetbook.main file contains all the code to run the Widgetbook.

Theme support

Since package:widgetbook supports Material and Cupertino themes as well as custom themes the annotation can be used with different constructors:

ConstructorThemeDescription
@WidgetbookApp.material(...)ThemeDataUse this if your app uses a Material theme (ThemeData)
@WidgetbookApp.cupertino(...)CupertinoThemeDataUse this if your app uses a Cupertino theme (CupertinoThemeData)
@WidgetbookApp(themeType: MyCustomTheme, ...)MyCustomThemeUse this if your app uses a custom theme (in this case MyCustomTheme). To declare the type of the theme to the generator, use the themeType property of the WidgetbookApp constructor.

Parameters

The annotation @WidgetbookApp (and its named constructors) has one required parameter name and multiple optional parameters.

ParameterTypeRequiredDescription
nameStringCreates the appInfo property.
devicesList<Device>Creates the devices property.
framesList<Frame>Creates the frames property.
textScaleFactorsList<double>Creates the textScaleFactors property.
themeTypeTypeUse only when you need custom theme support and can only be used with @WidgetbookApp and not with @WidgetbookApp.material or @WidgetbookApp.cupertino.

Example

For the following app structure

app
├─ lib
│  ├─ main.dart
│  ├─ app.dart
├─ test
│  ├─ app_test.dart
├─ pubspec.yaml

one might add @WidgetbookApp to the App Widget defined in app.dart.

@WidgetbookApp.material(
  name: 'Meal App',
  frames: const [
    WidgetbookFrame(
      name: 'Widgetbook',
      allowsDevices: true,
    ),
    WidgetbookFrame(
      name: 'None',
      allowsDevices: false,
    ),
  ],
  devices: [Apple.iPhone12],
  textScaleFactors: [
    1,
    2,
    3,
  ],
  foldersExpanded: true,
  widgetsExpanded: true,
)
class App extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp();
  }
}

package:widgetbook_generator will then create a new file app.widgetbook.dart next to the app.dart file. The resulting app structure will look like this:

app
├─ lib
│  ├─ main.dart
│  ├─ app.dart
│  ├─ app.widgetbook.dart
├─ test
│  ├─ app_test.dart
├─ pubspec.yaml

@WidgetbookUseCase

@WidgetbookUseCase allows developers to mark functions as a use case. The @WidgetbookUseCase must be applied to a function

Widget name(BuildContext context) {  
  return YourWidget()
}

or a lambda expression

Widget name(BuildContext context) => YourWidget();

Parameters

@WidgetbookUseCase requires the following parameters:

ParameterTypeRequiredDescription
nameStringSets the name of the WidgetbookUseCase
typeTypeGenerates a WidgetbookComponent based on the name of the provided Type. If multiple @WidgetbookUseCases reference the same type, Widgetbook will group all usecases under the same WidgetbookComponent.

Example

Lets assume that the file structure looks like this

app
├─ lib
│  ├─ main.dart
│  ├─ app.dart
│  ├─ tiles
│  │  ├─ awesome_tile.dart
│  ├─ app.widgetbook.dart
├─ test
│  ├─ app_test.dart
├─ pubspec.yaml

A use case for AwesomeTile located in /lib/tiles/awesome_tile.dart can be defined in that file by implementing the following

@WidgetbookUseCase(name: 'Default', type: AwesomeTile)
Widget awesomeTileUseCase(BuildContext context) {
  return AwesomeTile();
}

class AwesomeTile extends StatelessWidget {
  const AwesomeTile({Key? key}) : super(key: key);

  @override
  Widget build(BuildContext context) {
    return Container();
  }
}

It often happens that your widget is more complex. In such case, feel free to wrap the widget with whatever you need. This can also be a Provider, Bloc or other state management Widget.

After generating the code for the Widgetbook, you will find a navigation panel with the following content

use cases (WidgetbookCategory)
├─ tiles (WidgetbookFolder)
│  ├─ AwesomeTile (WidgetbookComponent)
│  │  ├─ Default (WidgetbookUseCase)

If you require multiple use cases for a Widget, feel free to define multiple @WidgetbookUseCases per Widget. The additional use cases will be located in the navigation panel similar to the showcased use case. For instance:

use cases (WidgetbookCategory)
├─ tiles (WidgetbookFolder)
│  ├─ AwesomeTile (WidgetbookComponent)
│  │  ├─ Default (WidgetbookUseCase)
│  │  ├─ Loaded (WidgetbookUseCase)

The generator skips the top root src folder from navigation panel.

@WidgetbookTheme

@WidgetbookTheme allows developers to annotated themes of their app. Similar to @WidgetbookUseCase, @WidgetbookTheme is used on methods returning a ThemeData object.

@WidgetbookTheme requires a name to identify different themes in the Widgetbook UI. You can also define isDefault to true if you want the theme to be the default on startup. If you set isDefault to true, it will also be the first theme shown in Widgetbook.

Example

@WidgetbookTheme(name: 'Dark', isDefault: true)
ThemeData getDarkTheme() => ThemeData(
      primarySwatch: Colors.blue,
    );

Localization annotations

Widgetbook allows developers to annotate locales and localization delegates supported by your app.

@WidgetbookLocales

Use @WidgetbookLocales to define the supported locales:

@WidgetbookLocales()
final locales = <Locale>[
  Locale('en'),
  Locale('de'),
  Locale('fr'),
];

@WidgetbookLocalizationDelegates

Use @WidgetbookLocalizationDelegates to define the supported localization delegates:

@WidgetbookLocalizationDelegates()
final delegates = [
  AppLocalizations.delegate,
  GlobalMaterialLocalizations.delegate,
  GlobalWidgetsLocalizations.delegate,
  GlobalCupertinoLocalizations.delegate,
];

Builder annotations

Widgetbook supports builder functions to customize how the use cases, themes and localization is build. Therefore, this package features annotations for all the builder functions available.

The annotations are:

  • @WidgetbookDeviceFrameBuilder
  • @WidgetbookLocalizationBuilder
  • @WidgetbookAppBuilder
  • @WidgetbookScaffoldBuilder
  • @WidgetbookThemeBuilder
  • @WidgetbookUseCaseBuilder

How to define an annotated builder function

Make sure to define a global function with the parameters of the builder function you'd like to define.

Example

@WidgetbookDeviceFrameBuilder()
DeviceFrameBuilderFunction frameBuilder = (
  BuildContext context,
  Device device,
  WidgetbookFrame frame,
  Orientation orientation,
  Widget child,
) { ... }