{"id":19058621,"url":"https://github.com/playbook-ui/playbook-flutter","last_synced_at":"2025-04-05T18:12:01.834Z","repository":{"id":39891249,"uuid":"357133747","full_name":"playbook-ui/playbook-flutter","owner":"playbook-ui","description":null,"archived":false,"fork":false,"pushed_at":"2025-03-27T02:23:35.000Z","size":764,"stargazers_count":78,"open_issues_count":7,"forks_count":12,"subscribers_count":3,"default_branch":"main","last_synced_at":"2025-03-29T17:08:36.478Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":null,"language":"Dart","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"bsd-3-clause","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/playbook-ui.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2021-04-12T09:28:26.000Z","updated_at":"2025-03-27T02:23:37.000Z","dependencies_parsed_at":"2022-09-22T18:51:53.131Z","dependency_job_id":"c2fde818-ed20-4294-b2d6-359f4b627eee","html_url":"https://github.com/playbook-ui/playbook-flutter","commit_stats":{"total_commits":260,"total_committers":10,"mean_commits":26.0,"dds":0.4807692307692307,"last_synced_commit":"8f824dbe16d35493e6865e2fea01620b242b6946"},"previous_names":[],"tags_count":39,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/playbook-ui%2Fplaybook-flutter","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/playbook-ui%2Fplaybook-flutter/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/playbook-ui%2Fplaybook-flutter/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/playbook-ui%2Fplaybook-flutter/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/playbook-ui","download_url":"https://codeload.github.com/playbook-ui/playbook-flutter/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":247378152,"owners_count":20929297,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":[],"created_at":"2024-11-09T00:01:00.699Z","updated_at":"2025-04-05T18:12:01.815Z","avatar_url":"https://github.com/playbook-ui.png","language":"Dart","readme":"\u003cp align=\"center\"\u003e\n\u003cimg src=\"https://raw.githubusercontent.com/playbook-ui/mediakit/master/logo/default-h%402x.png\" alt=\"Playbook\" width=\"400\"\u003e\n\u003c/p\u003e\n\n\u003cp align=\"center\"\u003eA library for isolated developing UI components and automatically taking snapshots of them.\u003c/p\u003e\n\n# Playbook\n\n`Playbook` is a library that provides a sandbox for building UI components without having to worry about application-specific dependencies, strongly inspired by [Storybook](https://storybook.js.org/) for JavaScript in web-frontend development.  \n\nComponents built by using `Playbook` can generate a standalone app as living styleguide.  \nThis allows you to not only review UI quickly but also deliver more robost designs by separating business logics out of components.\n\nBesides, snapshots of each component can be automatically generated by unit tests, and visual regression testing can be performed using arbitrary third-party tools.\n\nFor complex modern app development, it’s important to catch UI changes more sensitively and keep improving them faster.  \nWith the `Playbook`, you don't have to struggle through preparing the data and spend human resources for manual testings.  \n\n---\n\n### Playbook\n\n`Playbook` components are uniquely stored as scenarios. A `Scenario` has the way to layout component.\n\n```dart\nPlaybook(\n  stories: [\n    Story(\n      'Home',\n      scenarios: [\n        Scenario(\n          'CategoryHome',\n          layout: ScenarioLayout.fill(),\n          child: CategoryHome(userData: UserData.stub),\n        ),\n        Scenario(\n          'LandmarkList',\n          layout: ScenarioLayout.fill(),\n          child: Scaffold(\n            appBar: AppBar(),\n            body: LandmarkList(userData: UserData.stub),\n          ),\n        ),\n        Scenario(\n          'Container red',\n          layout: ScenarioLayout.fixed(100, 100),\n          child: Container(color: Colors.red),\n        ),\n      ],\n    ),\n  ],\n);\n```\n\n---\n\n### PlaybookUI\n\n`PlaybookUI` provides user interfaces for browsing a list of scenarios.\n\n#### PlaybookGallery\n\nThe component visuals are listed and displayed.  \nThose that are displayed on the top screen are not actually doing layout, but rather display the snapshots that are efficiently generated at runtime.  \n\n| Browser | Detail |\n| ------- | ------ |\n|\u003cimg src=\"https://github.com/playbook-ui/playbook-flutter/assets/5707132/5d5a6d87-159c-4083-90e7-1f06be4f394f\" width=\"150\"\u003e|\u003cimg src=\"https://github.com/playbook-ui/playbook-flutter/assets/5707132/e5f98d67-f0ed-4af7-a630-567a71f20bfa\" width=\"150\"\u003e|\n\n---\n\n### PlaybookSnapshot\n\nScenarios can be tested by the instance of types conform to `TestTool` class.\n`Snapshot` is one of them, which can generate the snapshots of all scenarios with simulate the screen size and safe area of the given devices.  \n\n```dart\nFuture\u003cvoid\u003e main() async {\n  testWidgets('Take snapshots', (tester) async {\n    await Playbook(\n      stories: [\n        barStory(),\n        fooWidgetStory(),\n        assetImageStory(),\n        homePageStory(),\n        scrollableStory(),\n      ],\n    ).run(\n      Snapshot(\n        devices: [SnapshotDevice.iPhoneSE2nd],\n      ),\n      (widget, device) {\n        return MaterialApp(\n          debugShowCheckedModeBanner: false,\n          theme: ThemeData(\n            fontFamily: 'Roboto',\n            platform: device.platform,\n          ),\n          home: widget,\n        );\n      },\n    );\n  });\n}\n```\n\n\u003cimg src=\"https://github.com/playbook-ui/playbook-flutter/assets/5707132/baddc8eb-864c-435c-bec4-c3fc2141d73b\" alt=\"generate images\" width=\"660\"\u003e\n\n#### Configuration\n\n`pubspec.yaml` can be configured to define the location of the font file and snapshot output directory path.\n\n```yaml\nplaybook_snapshot:\n  fonts:\n    - family: Roboto\n      fonts:\n        - asset: assets/fonts/Roboto-Regular.ttf\n  # default is /snapshots\n  snapshot_dir: iOS\n  # default is empty\n  sub_dir: service\n```\n\nWith the above settings, snapshots will be saved in the following directory.\n\n```\n/test/iOS/${DeviceName}/service/${StoryTitle}/${ScenarioTitle}.png\n```\n\nIf you want to change path dynamically, you can use `snapshotDir` and `subDir` arguments in the `Snapshot`.\n\n#### Notes\n\n`Snapshot` (internally `flutter test --update-goldens`) requires you to prepare and load the fonts yourself. By defining the location of the font file in `flutter` or `playbook_snapshot` in `pubspec.yaml` and preparing the font file in the directory, the font file will be loaded automatically.\n\n```yaml\nflutter:\n  fonts:\n    - family: Roboto\n      fonts:\n        - asset: assets/fonts/Roboto-Regular.ttf\n```\n\nor\n\n```yaml\nplaybook_snapshot:\n  fonts:\n    - family: Roboto\n      fonts:\n        - asset: assets/fonts/Roboto-Regular.ttf\n```\n\nAnd then, should be prepared the font file in the directory.\n\n---\n\n### PlaybookGenerator\n\nSupports generating stories and scenarios from any `.dart` files.\n\n```dart\n// some_story.dart\n\nconst storyTitle = 'Home';\n\n@GenerateScenario(\n  layout: ScenarioLayout.fill(),\n)\nWidget $CategoryHome() =\u003e CategoryHome(userData: UserData.stub);\n\n@GenerateScenario(\n  layout: ScenarioLayout.fill(),\n)\nWidget $LandmarkList() =\u003e Scaffold(\n      appBar: AppBar(),\n      body: LandmarkList(userData: UserData.stub),\n    );\n\n@GenerateScenario(\n  title: 'Container red',\n  layout: ScenarioLayout.fixed(100, 100),\n)\nWidget containerRed() =\u003e Container(color: Colors.red);\n\n@GenerateScenario(\n  title: 'Device pixel ratio',\n  layout: ScenarioLayout.fixed(300, 300),\n)\nWidget devicePixelRatio(BuildContext context) =\u003e\n    Text('Device pixel ratio is ${MediaQuery.of(context).devicePixelRatio}');\n```\n\nYou can reference the playbook instance.\n\n```dart\nvoid main() {\n  runApp(MyApp());\n}\n\nclass MyApp extends StatelessWidget {\n  @override\n  Widget build(BuildContext context) {\n    return MaterialApp(\n      title: 'Playbook Demo',\n      theme: ThemeData.light(),\n      home: PlaybookGallery(\n        title: 'Sample app',\n        playbook: playbook,\n      ),\n    );\n  }\n}\n```\n\nCan set glob for find assets and output file name in `build.yaml`. Default input value is `lib/**.dart` and output value is `generated_playbook.dart`.\n\n```yaml\ntargets:\n  $default:\n    builders:\n      playbook_generator:stories:\n        options:\n          input: lib/**.dart\n          output: generated_playbook.dart\n```\n\n---\n\n### Integration with Third-party Tools\n\nThe generated snapshot images can be used for more advanced visual regression testing by using a variety of third party tools.  \n\n#### [percy](https://percy.io)\n\n\u003cimg src=\"https://raw.githubusercontent.com/playbook-ui/playbook-ios/master/assets/percy.png\" alt=\"percy\" width=\"600\"\u003e\n\n#### [reg-viz/reg-suit](https://github.com/reg-viz/reg-suit)\n\n\u003cimg src=\"https://github.com/playbook-ui/playbook-ios/blob/master/assets/reg_report.png\" alt=\"reg-suit\" width=\"600\"\u003e\n\n---\n\n## Requirements\n\n- Dart 3.0.0+\n- flutter 3.0.0+\n\n---\n\n## License\n\nPlaybook is released under the [BSD-3-Clause License](./LICENSE).\n\n\u003cbr\u003e\n\u003cp align=\"center\"\u003e\n\u003cimg alt=\"Playbook\" src=\"https://raw.githubusercontent.com/playbook-ui/mediakit/master/logo/default%402x.png\" width=\"280\"\u003e\n\u003c/p\u003e\n","funding_links":[],"categories":[],"sub_categories":[],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fplaybook-ui%2Fplaybook-flutter","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fplaybook-ui%2Fplaybook-flutter","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fplaybook-ui%2Fplaybook-flutter/lists"}