# 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 {{ versions.cli }}
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`:

   ```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),
        );
      }
    }
   ```

1. Create a new file `widgetbook/lib/custom_button.stories.dart`:

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

   part 'custom_button.stories.g.dart';

   const meta = Meta(CustomButton.new);
   ```

1. 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 `$`.

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

part 'custom_button.stories.g.dart';

const meta = Meta(CustomButton.new);

final $Default = _Story(
  args: _Args(  // [!code highlight]
    label: StringArg('Button'),  // [!code highlight]
    onPressed: Arg.fixed(() {}),  // [!code highlight]
  ),  // [!code highlight]
);
```

The generated `_Args` class holds one entry per widget parameter. Any parameter
without a usable default — like `CustomButton`'s required `onPressed` callback —
must be supplied through `args`, so a bare `_Story()` will not compile for this
widget. Wrap a value in an [Arg](/args/overview) type such as `StringArg` to expose
it as an adjustable knob in Widgetbook's UI, or in `Arg.fixed(...)` to pin it
(handy for callbacks). Widgets whose parameters are all optional or have defaults
can still use `_Story()` with no `args`.

## Create your first Scenario

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

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

part 'custom_button.stories.g.dart';

const meta = Meta(CustomButton.new);

final $Default = _Story(
  args: _Args(  // [!code highlight]
    label: StringArg('Button'),  // [!code highlight]
    onPressed: Arg.fixed(() {}),  // [!code highlight]
  ),  // [!code highlight]
  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));

        // 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:

```dart
final config = Config(
  // ...
  scenarioConfig: ScenarioConfig(
    definitions: [
      ScenarioDefinition(
        name: 'Dark',
        modes: [MaterialThemeMode('Dark', ThemeData.dark())],
      ),
      ScenarioDefinition(
        name: 'Light',
        modes: [MaterialThemeMode('Light', ThemeData.light())],
      ),
    ],
  ),
);
```
