Quick Start

Project Bootstrap

Widgetbook v4 introduced a new init command in the CLI to help you set up your Widgetbook workspace quickly. Run the following command inside your app or design system package directory:

dart pub global activate widgetbook_cli 4.0.0-alpha.1
widgetbook init

Create your first Component

A Component is a representation of a Widget you want to showcase in Widgetbook. Each Component can have multiple stories. Let's start by cataloging a simple widget.

  1. Create a new widget in your app, e.g. lib/widgets/custom_button.dart:

    import 'package:flutter/material.dart';
    
    class CustomButton extends StatelessWidget {
      final String label;
      final VoidCallback onPressed;
    
      const CustomButton({
        super.key,
        required this.label,
        required this.onPressed,
      });
    
      @override
      Widget build(BuildContext context) {
        return ElevatedButton(
           onPressed: onPressed,
           child: Text(label),
         );
       }
     }
    
  2. Create a new file widgetbook/lib/custom_button.stories.dart:

    import 'package:widgetbook/widgetbook.dart';
    import 'package:your_app/widgets/custom_button.dart';
    
    part 'custom_button.stories.book.dart';
    
    const meta = Meta<CustomButton>();
    
  3. Run dart run build_runner build to generate the boilerplate code.

Create your first Story

A story is a variant of a Component. For example, if the component is a button, its stories can be "primary button", "secondary button", "disabled button", etc. Now you can start writing stories for the CustomButton component. A story must start with $.

import 'package:widgetbook/widgetbook.dart';
import 'package:your_app/widgets/custom_button.dart';

part 'custom_button.stories.book.dart';

const meta = Meta<CustomButton>();

final $Default = _Story();  

Create your first Scenario

A Scenario is like a golden test of your story with certain args and mode.

import 'package:widgetbook/widgetbook.dart';
import 'package:your_app/widgets/custom_button.dart';

part 'custom_button.stories.book.dart';

const meta = Meta<CustomButton>();

final $Default = _Story(
  scenarios: [
    _Scenario(
      name: 'Long Label',
      modes: [MaterialThemeMode('Light', ThemeData.light())],
      args: _Args.fixed(
        label: 'This is a very long label',
        onPressed: () {},
      ),
      run: (tester, args) async {
        // You can simulate interactions here
        // For example, tap the button
        // await tester.tap(find.text(args.label.value));

        // Or you can also expect certain behaviors
        // expect(...);
      },
    ),
  ],
);

To run these scenarios, you need to run flutter test then check your widgetbook/build/.widgetbook folder for the generated screenshots.

If you want to define global scenarios for all stories in you widgetbook, you can define them in your widgetbook.config.dart file:

final config = Config(
  // ...
  scenarios: [
    ScenarioDefinition(
      name: 'Dark',
      modes: [MaterialThemeMode('Dark', ThemeData.dark())],
    ),
    ScenarioDefinition(
      name: 'Light',
      modes: [MaterialThemeMode('Light', ThemeData.light())],
    ),
  ],
);