Skip to main content

Annotation

@Design

The main annotation is @Design(...) or @design if you are not passing any additional parameters. It should be placed on a Widget class as such:

tip

Don't forget to add the part '*.design.dart'; statement as it enables the part file builder.

@Design(
title: 'MyWidget',
subtitle: 'A very awesome widget',
description: 'A long long time ago ...(100 words)...',
designLink: 'https://www.figma.com/',
showApiDocs: false,
)
class MyWidget extends StatelessWidget {
//...
}

Here are the list of parameters you can customize:

  • title (String?)
    • override the title of the page (also in the explorer tree).
    • if null, defaults to the name of the widget.
  • subtitle (String?)
    • override the subtitle of the page (placed under the title).
    • if null, will not be shown.
  • description (String?)
    • override the description of the page (place under the section links).
    • if null, will not be shown.
  • designLink (String?)
    • if set, the user can see the link button on the widget designer.
    • if null, will not be shown.
  • showApiDocs (bool = true)
    • if true, the API docs section will be generated. It describes the fields in the widget constructor.
    • if false, will not be shown.

@DesignField

Another useful annotation is @DesignField which allows you to initialize the Data builder of a given field in your widget's constructor at runtime via the field parameter.

The designer will use the first data builder in the provided list which matches the same parameter type.

tip

For concrete examples on how to use the various out-of-the-box data builders, checkout the documentation on Default data builders.

Some of the data builder takes a parameter or an "initial value" of the field. This is especially useful for required fields that has no default value on the constructor. If both the parameter and the default value is specified, the parameter will be used.

It can be configured in the 2 following places, in the order of priority if overlapped:

  1. Constructor parameter: placed on the parameter of a constructor/factory constructor of the widget, this will the first place the designer looks when constructing the widget initially.
  factory ToggleButton.special({
@DesignField(parameter: DesignParamStringLorem())
required String title,
//...
Key? key,
}) : super(key: key);

  1. Class field: placed on the class field, this will be the secondary place the designer looks at if no annotation is provided at the target constructor.
class ToggleButton extends StatelessWidget {
@DesignField(parameter: DesignParamStringLorem())
final String title;

// ...
}

@DesignExamples

In many situations, you would want to provide examples of different setups on a constructor. With the @DesignExamples, you can provide a list of DesignExample on the target constructor, each would be rendered into a widget designer subsection that contains a title, an optional description and a builder. The builder is a aggregated model of the design fields, generated by the @design/@Design() annotation. It uses the following naming convention: _${NAME_OF_CONSTRUCTOR_IN_PASCAL_CASE}ParamBuilder.

Here is an example using the annotation:

@design
class ResponsiveSizedBox extends StatelessWidget {
@DesignExamples(examples: [
DesignExample(
title: 'Example red',
description: 'Example case with red infinite placeholder as child',
builder: _$ResponsiveSizedBoxParamBuilder(
child: DesignParamWidgetPlaceholder(
color: Colors.red,
size: Size.infinite,
),
),
),
DesignExample(
title: 'Example blue',
description: 'Example case with blue infinite placeholder as child',
builder: _$ResponsiveSizedBoxParamBuilder(
child: DesignParamWidgetPlaceholder(
color: Colors.blue,
size: Size.infinite,
),
widthWhenConstrained: 500.0,
),
),
])
const ResponsiveSizedBox({
required this.child,
this.widthWhenConstrained = 400.0,
this.paddingWhenConstrained = const EdgeInsets.all(20),
this.centeredWhenConstrained = true,
this.breakpoint = 420,
Key? key,
}) : super(key: key);
}

caution

Note that the _${NAME_OF_CONSTRUCTOR_IN_PASCAL_CASE}ParamBuilder class will have to be generated first to be used. Hence you would need to run the build_runner for a first time on the @design/@Design() annotated class both at the beginning and when you change the ctor.

Otherwise you might run into "Chicken & egg" problem.

For a more complete example, please checkout the example project on Github.