[コラム]Widgetbook について

1.Widgetbook とは

Widgetbook/Guides/Quick Start(URL: https://docs.widgetbook.io/guides/quick-start)

widgetbook は、Flutter アプリケーションのウィジェットを整理してプレビューできるツールです。これはデザインシステムやウィジェットカタログを作成する際に特に有効で、開発者やデザイナーがアプリの各コンポーネントを独立して確認しやすくします。

主な特徴
ウィジェットのカスタマイズ:
Widgetbook では、異なるプロパティと状態でウィジェットを設定し、これらの異なる構成を容易に切り替えて確認できます。

ホットリロード対応:
Flutter のホットリロードを利用して、リアルタイムでウィジェットの変更をプレビューできます。

階層的な構造:
ウィジェットをカテゴリやサブカテゴリに整理できるため、大規模なプロジェクトでも管理がしやすくなります。

レスポンシブデザインのサポート:
異なるスクリーンサイズでのウィジェットの見え方を確認できるため、レスポンシブデザインの実装をサポートします。

チームでのコラボレーション:
デザイナーや他の開発者と連携して、アプリのデザインと機能を共有しやすくします。

このツールは、Flutter プロジェクトの効率を向上させ、UI の一貫性と品質を保つのに役立ちます。pub.dev で Widgetbook のパッケージを探すことで、より詳しい情報やインストール方法を確認できます。あなたがフロントエンドのエンジニアリングに焦点を当てていることを考えると、このツールはあなたの開発プロセスを大いに支援する可能性があります。

2.Widgetbook の使い方

前提

(1)(Flutter)動作環境がある。

(2)対象アプリ(動作確認済Flutterアプリ)のPJフォルダがある。

以下では対象アプリとして(”flutter create counter” コマンド実行により作成される(デフォルトの))カウンタアプリを例にして、(Widgetbookを)適用する説明にしてあるます。

2-1.対象アプリのPJフォルダに移動

(1)まだ対象アプリが無い方は(ここでは、次のコマンドで)新規作成します。(動作確認もしておきます)

> flutter create counter

(1)対象アプリが無い方は(ここでは、以下のコマンドで)新規作成する。
C:\app\flutter\tool> flutter create counter
//・・・(省略)・・・対象アプリ新規作成完了。

(2)対象アプリPJフォルダに移動します。

> cd counter

(2)対象アプリPJフォルダに移動する。
C:\app\flutter\tool> cd counter
C:\app\flutter\tool\counter>

(初期フォルダ構成と対象(カウンター)アプリの内容(例))

すると(一応)初期フォルダ構成と対象(カウンター)アプリは、こんな内容になっていますよね。

(main.dart)言わずと知れた(デフォルト作成される)カウンターアプリです:
import 'package:flutter/material.dart';

void main() {
  runApp(const MyApp());
}

class MyApp extends StatelessWidget {
  const MyApp({super.key});

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Flutter Demo',
      theme: ThemeData(
        colorScheme: ColorScheme.fromSeed(seedColor: Colors.deepPurple),
        useMaterial3: true,
      ),
      home: const MyHomePage(title: 'Flutter Demo Home Page'),
    );
  }
}

class MyHomePage extends StatefulWidget {
  const MyHomePage({super.key, required this.title});

  final String title;

  @override
  State<MyHomePage> createState() => _MyHomePageState();
}

class _MyHomePageState extends State<MyHomePage> {
  int _counter = 0;

  void _incrementCounter() {
    setState(() {
      _counter++;
    });
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        backgroundColor: Theme.of(context).colorScheme.inversePrimary,
        title: Text(widget.title),
      ),
      body: Center(
        child: Column(
          mainAxisAlignment: MainAxisAlignment.center,
          children: <Widget>[
            const Text(
              'You have pushed the button this many times:',
            ),
            Text(
              '$_counter',
              style: Theme.of(context).textTheme.headlineMedium,
            ),
          ],
        ),
      ),
      
      //↓ (ちなみに)今回、カタログ化したい対象ウィジェットはこれです ↓
      floatingActionButton: FloatingActionButton(
        onPressed: _incrementCounter,
        tooltip: 'Increment',
        child: const Icon(Icons.add),
      ),
      //↑ ↑ ↑ ↑ ↑ ↑ ↑ ↑ ↑ ↑ ↑ ↑ ↑ ↑ ↑ ↑ ↑ ↑ ↑ ↑ ↑ ↑ ↑ ↑ ↑ ↑ ↑ ↑ ↑
    );
  }
}

2-2.必要なパッケージ依存関係の登録(対象アプリPJフォルダ直下)

(1)対象アプリPJフォルダ直下で次のコマンドを実行して下さい。:
tool> cd counter
counter>

flutter pub add widgetbook
flutter pub add widgetbook_annotation
flutter pub add dev:widgetbook_generator
flutter pub add dev:build_runner

2-3.widgetbook(Flutter)プロジェクトの新規作成

(1)次のコマンドで、対象アプリPJフォルダ直下に、widgetbook という(Flutter)プロジェクトを(シンプル構成( –empty を付ける)で)新規作成しします。

※今回私の場合は、このwidgetbookで扱いたいwidgetとして、web版とwindows版だけで充分でしたので、更に、–platforms オプションにより(プラットフォームを)限定しました。

> flutter create widgetbook –empty –platforms=web,windows

(1)次のコマンドで、対象アプリPJフォルダ直下に、widgetbook という(Flutter)プロジェクトを(シンプル構成( –empty を付ける)で)新規作成して下さい。
C:\app\flutter\tool> cd counter
C:\app\flutter\tool\counter>
 flutter create widgetbook --empty --platforms=web, windows
//・・・(省略)・・・widgetbookPJ新規作成完了。

補足)flutter create –empty コマンドを使用すると、Flutterプロジェクトが作成されますが、特にシンプルな構造で生成されます。具体的には、–empty オプションを付けることで、プロジェクトには最小限のファイルのみが含まれ、カウンターアプリのようなサンプルコードは含まれません。通常の flutter create コマンドで生成される例示的なアプリケーションコードやテストファイルなどが省略され、プロジェクト構成をシンプルに保つことができます。

このオプションは、特定の用途や設定から始めたい開発者にとって便利です。プロジェクトの基盤を自分で一から構築したい場合や、特定のフレームワークのみを利用したい場合などに使用できます。

(フォルダ構成(例))

すると(一応)こんなフォルダ構成になっていますよね。

(b)widgetフォルダ
(c)widgetフォルダ直下
(d)widget \ lib フォルダ直下

2-4.widgetbookプロジェクト \ pubspec.yaml 修正

widgetbook フォルダ直下にある pubspec.yaml を、次の様に修正します。

(widgetbook\pubspec.yaml)修正前:
name: widgetbook //修正前
description: "A new Flutter project."
publish_to: 'none'
version: 0.1.0
(widgetbook\pubspec.yaml)修正後:
name: widgetbook_workspace //修正後
description: "A new Flutter project."
publish_to: 'none'
version: 0.1.0

補足)widgetbookという名前のパッケージとプロジェクト名が衝突しないようにするためのものです。FlutterやDartのプロジェクトでは、pubspec.yaml ファイル内で定義されるプロジェクト名が、他のパッケージ名と衝突してしまうと、依存関係の解決などで問題が生じることがあります。特に、widgetbookという名前はWidgetbook自体のパッケージ名でもあるため、これをプロジェクト名として使用すると問題が発生する可能性があります。

このため、widgetbook/pubspec.yaml ファイル内でプロジェクト名を widgetbook_workspace に変更することを推奨しています。これ故にここでは、pubspec.yaml ファイル内の name 属性を widgetbook から widgetbook_workspace に変更することを示しています。

2-5.必要なパッケージ依存関係の登録

(1)widgetbookフォルダ直下で次のコマンドを実行して、必要なパッケージの依存関係を登録します。

(1)widgetbookフォルダ直下で次のコマンドを実行して下さい。:
counter> cd widgetbook
counter\widgetbook>

flutter pub add widgetbook
flutter pub add widgetbook_annotation
flutter pub add dev:widgetbook_generator
flutter pub add dev:build_runner

(2)一応、 widgetbook\pubspec.yaml に、上記パッケージ依存関係が登録されていることを確認します。

(widgetbook\pubspec.yaml) 上記パッケージ依存関係が登録されていることを確認して下さい。
name: widgetbook_workspace
description: "A new Flutter project."
publish_to: 'none'
version: 0.1.0

environment:
  sdk: ^3.5.0

dependencies:
  flutter:
    sdk: flutter
  widgetbook: ^3.8.1
  widgetbook_annotation: ^3.1.0

dev_dependencies:
  flutter_test:
    sdk: flutter
  flutter_lints: ^4.0.0
  widgetbook_generator: ^3.8.0
  build_runner: ^2.4.12

flutter:
  uses-material-design: true

2-6.widgetbook \ pubspec.yaml に対象アプリ情報を登録

(1)まず対象アプリ名(以下の①)を(対象アプリPJフォルダ直下のpubspec.yamlname 内容により)確認します。

(対象アプリPJフォルダ直下のpubspec.yaml)
name: counter //⓵対象アプリ名
description: "A new Flutter project."


publish_to: 'none'



version: 1.0.0+1

environment:
  sdk: ^3.5.0

(2)widgetbook \ pubspec.yaml に、次の様に、対象アプリ情報(①対象アプリ名、及び①への相対パス)を登録します。

(widgetbook\pubspec.yaml)修正前:
name: widgetbook_workspace
description: "A new Flutter project."
publish_to: 'none'
version: 0.1.0

environment:
  sdk: ^3.5.0

dependencies:
  flutter:
    sdk: flutter
  widgetbook: ^3.8.1
  widgetbook_annotation: ^3.1.0
//この位置に、右側の設定を追加する
//⓵対象アプリ名:
//  path: ../
dev_dependencies:
  flutter_test:
    sdk: flutter
  flutter_lints: ^4.0.0
  widgetbook_generator: ^3.8.0
  build_runner: ^2.4.12
(widgetbook\pubspec.yaml)修正後:
name: widgetbook_workspace
description: "A new Flutter project."
publish_to: 'none'
version: 0.1.0

environment:
  sdk: ^3.5.0

dependencies:
  flutter:
    sdk: flutter
  widgetbook: ^3.8.1
  widgetbook_annotation: ^3.1.0
  counter:
    path: ../

dev_dependencies:
  flutter_test:
    sdk: flutter
  flutter_lints: ^4.0.0
  widgetbook_generator: ^3.8.0
  build_runner: ^2.4.12

(フォルダ構成(例))

すると(一応)こんなフォルダ構成になっていますよね。

(b)widgetフォルダ
※上記2では、
このwidgetbookPJ
を新規作成しましたよね。
(c)widgetフォルダ直下
※上記5(2)では、
ここのpubspec.yaml
を修正しましたよね。
(d)widget \ lib フォルダ直下

(widgetbook PJフォルダ直下の pubspec.yaml(例))

そして、widgetbook(PJフォルダ直下の)pubspec.yamlは、こんな内容になっていますよね。

(widgetbook PJフォルダ直下の pubspec.yaml)
name: widgetbook_workspace
description: "A new Flutter project."
publish_to: 'none'
version: 0.1.0

environment:
  sdk: ^3.5.0

dependencies:
  flutter:
    sdk: flutter
  widgetbook: ^3.8.1
  widgetbook_annotation: ^3.1.0
  counter:
    path: ../

dev_dependencies:
  flutter_test:
    sdk: flutter
  flutter_lints: ^4.0.0
  widgetbook_generator: ^3.8.0
  build_runner: ^2.4.12

flutter:
  uses-material-design: true

2-7.対象ウィジェットのユースケース定義ファイル作成

(1)前手順1.(2)で作成した対象アプリ(counter \ lib \ main.dart)中から、カタログ化したいウィジェットを選択します。

① 今回は、以下の「(A)floatingActionButton」を選択しました。

(当然ですが、今回たまたまmain.dart から選択しますが、別にどのファイルにあるウィジェットでも良いわけです。)

(1)前手順1.(2)で作成した対象アプリ(counter \ lib \ main.dart)中から、カタログ化したいウィジェットを選択します。
import 'package:flutter/material.dart';

void main() {
  runApp(const MyApp());
}

class MyApp extends StatelessWidget {
  const MyApp({super.key});

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Flutter Demo',
      theme: ThemeData(
        colorScheme: ColorScheme.fromSeed(seedColor: Colors.deepPurple),
        useMaterial3: true,
      ),
      home: const MyHomePage(title: 'Flutter Demo Home Page'),
    );
  }
}

class MyHomePage extends StatefulWidget {
  const MyHomePage({super.key, required this.title});

  final String title;

  @override
  State<MyHomePage> createState() => _MyHomePageState();
}

class _MyHomePageState extends State<MyHomePage> {
  int _counter = 0;

  void _incrementCounter() {
    setState(() {
      _counter++;
    });
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        backgroundColor: Theme.of(context).colorScheme.inversePrimary,
        title: Text(widget.title),
      ),
      body: Center(
        child: Column(
          mainAxisAlignment: MainAxisAlignment.center,
          children: <Widget>[
            const Text(
              'You have pushed the button this many times:',
            ),
            Text(
              '$_counter',
              style: Theme.of(context).textTheme.headlineMedium,
            ),
          ],
        ),
      ),
      
      //(A) ↓ カタログ化対象ウィジェット ↓
      floatingActionButton: FloatingActionButton(
        onPressed: _incrementCounter,
        tooltip: 'Increment',
        child: const Icon(Icons.add),
      ),
      //      ↑ カタログ化対象ウィジェット ↑
      
    );
  }
}

(2)widgetbook \ lib 直下に、対象ウィジェットのユースケース定義ファイルを新規作成します。

まずは空のファイル
(ファイル名は、自由に付けられます。ここでは、「floating_action_button.dart」 としました。)
を作成します。

この時点では、まだ、このファイルは空ですよね。
(空のファイルを作成しましたので)

(3)上記(1)で選択した「(A)floatingActionButton」を、上記(2)で作成したファイルに移植します。

Dart
import 'package:flutter/material.dart';
import 'package:widgetbook_annotation/widgetbook_annotation.dart' as widgetbook;

@widgetbook.UseCase(name: 'Default', type: FloatingActionButton)
Widget buildDefaultFloatingActionButtonUseCase(BuildContext context){
  return FloatingActionButton(
    onPressed: () {
      //処理作成
    },
    tooltip: 'Increment',
    child: const Icon(Icons.add),
  );
}

2-8.widgetbook エントリーポイント作成

(1)widgetbook \ lib 直下の main.dart を次の様に変更します。

(B)のファイル(main.directories.g.dart)は次の手順(「9.コードジェネレータ実行」)で自動生成されるファイルです。故に、次のコード
import ‘main.directories.g.dart’;
で、エラーが表示されていても構わず次の手順を実施します。

(widgetbook \ lib 直下の main.dart )(1)widgetbook \ lib 直下の main.dart を次の様に変更します。:
import 'package:flutter/material.dart';
import 'package:widgetbook/widgetbook.dart';
import 'package:widgetbook_annotation/widgetbook_annotation.dart' as widgetbook;

//(B)このファイルは次の手順(「8.コードジェネレータ実行」)により生成されるファイルです。
// ここでエラーが表示されていても構わず次の手順を実施します。
import 'main.directories.g.dart';

void main() {
  runApp(const WidgetbookApp());
}

@widgetbook.App()
class WidgetbookApp extends StatelessWidget {
  const WidgetbookApp({super.key});

  @override
  Widget build(BuildContext context) {
    return Widgetbook.material(
      // The [directories] variable does not exist yet,
      // it will be generated in the next step
      directories: directories,
    );
  }
}

2-9.コードジェネレータ実行

(1)widgetbook PJフォルダ直下で、次のコマンドを実行します。

> flutter pub run build_runner build –delete-conflicting-outputs

補足) –delete-conflicting-outputs オプションを付けていると、2回目以降に再度実行した際に、旧ファイルを削除して実行する

(1)widgetbook PJフォルダ直下で、次のコマンドを実行します。
> cd widgetbook



widgetbook> flutter pub run build_runner build --delete-conflicting-outputs

Deprecated. Use `dart run` instead.
Building package executable...
Built build_runner:build_runner.
[INFO] Generating build script completed, took 383ms
[INFO] Reading cached asset graph completed, took 135ms
[INFO] Checking for updates since last build completed, took 1.3s
[INFO] Running build completed, took 21.7s
[INFO] Caching finalized dependency graph completed, took 120ms
[INFO] Succeeded after 21.8s with 499 outputs (997 actions)

//すると、widgetbook¥lib フォルダ配下に、main.directories.g.dart が自動生成されます。

すると、前手順「8」で発生していたエラーは解消します。

2-10.Widgetbook起動

(1)Widgetbookを、widgetbook PJフォルダ直下で、次のコマンドを実行することで、起動します。

> flutter run -d windows

(1)Widgetbookを、widgetbook PJフォルダ直下で、次のコマンドを実行することで、起動します。
\widgetbook>flutter run -d windows


Launching lib\main.dart on Windows in debug mode...
Building Windows application...                                     8.2s
Built build\windows\x64\runner\Debug\widgetbook.exe
Syncing files to device Windows...                                 111ms

Flutter run key commands.
r Hot reload.
R Hot restart.
h List all available interactive commands.
d Detach (terminate "flutter run" but leave application running).
c Clear the screen
q Quit (terminate the application on the device).

A Dart VM Service on Windows is available at: http://127.0.0.1:56492/7YdFnlvRm30=/
The Flutter DevTools debugger and profiler on Windows is available at:
http://127.0.0.1:9101?uri=http://127.0.0.1:56492/7YdFnlvRm30=/

//するとWidgetbookが起動します。

するとWidgetbookが起動します。

(2)どれかウィジェットを選択します。(ここでは1つしかカタログ化していませんので1つですが)

すると、選択したウィジェットが、表示されます。

コメントを残す