A community contribution from Christopher Nwosu-Madueke 🎉
Disclaimer: This article is about Widgetbook 2.0 Parts of the content may be out of date.
If as a Flutter developer, you have ever wanted to display and verify that your implementation of a designed UI is same with what was designed, or you have ever wanted to separately test out how components look in different state without compromising on code structure, then Widgetbook has got you covered.
Before we go rambling about Widgetbook and its uses, we have to understand what it does or solves, or more precisely, we have to understand what UI documentation is. To do that, we have to understand some terms.
Now that we have this out of the way, we can begin rambling about Widgetbook
Widgetbook is a UI component development environment for flutter developers. It allows developers create and showcase UI components in an isolated environment and test them outside the context of a full app. This helps the development process on different phases to test UI components with different properties such as devices/screen sizes, themes, orientations and confirm responsiveness.
It is the flutter counterpart for Storybook.js. Yes, it supports add-ons which allow developers to extend the functionality of the tool with additional features, such as custom panel options; it is also a collaborative tool for teams, allowing designers and front-end developers to work together to create high-quality, polished components.
Widgetbook has a bunch of features that enable us as Flutter developers in our development process to visualize our components(widgets) in isolation and ultimately document our product and its development process. Some of which are:
In order to gain a practical understanding of Widgetbook and how to use it effectively, we will be taking a project-based approach. This approach will allow us to see firsthand how to apply Widgetbook in a real-world scenario, and provide us with actionable insights on how to utilize it in our own projects.
Prerequisites: To follow along with this article, you would need
1. good knowledge of flutter
2. familiarity with command-line
3. understanding of annotations in flutter
NB: You can find the initial/starting code here.
For this sample project we would be designing a three page application that has an onboarding page, a login page and a home page as shown below, but here we will make it as real as possible, linking each screen and mocking some app setup that each screen should be dependent on.
Here are a few details on the project.
With this, we have an idea of the design we are implementing, and how we can go about it.
Widgetbook has two methods of setting up your UI for review, either by explicitly and manually writing it out; this is suitable for small projects. The second is by making use of Widgetbook annotations, Widgetbook generator and build runner. With these packages, we won’t have to spend much time writing each widget; this method makes it easier to setup and maintain.
Since we are simulating a large app, we will be going with the second method.
Now we open our `pubspec.yaml` and make two groups of changes
In the end, our `pubspec.yaml` should have the following updates.
Widgetbook allows us to arrange our UI based on predefined organizers. Organizers, in this case, are widgets that helps developers manage their UI components or catalogs. Think of it as a helpers to group and arrange your UI components. These organizers are:
From the documentation:
Both `WidgetbookCategory` and `WidgetbookFolder` can contain sub folders and `WidgetbookComponent` elements. However, `WidgetbookComponent` can only contain `WidgetbookUseCases`.
These organizers can be used explicitly when using the first method, but like I mentioned earlier, we are making use of the second method(`widgetbook_annotations` and `widgetbook_generator`). This will create a widgetbook reference of our widget and arrange them according to the folder structure on the Widgetbook dashboard.
Note: Widgetbook dashboard here refers to the resulting application that happens when you run the widgetbook code.
The aim here is to catalogue all views and widgets in the project.The first step would be register our app by annotating our Root app with `@Widgetbook.material()`. This can be switched between (`Widgetbook.cupertino()` and `WidgetbookApp()` depending on whether you have a material, cupertino or a custom theme).
After registering our app, we can annotate each of our views (a sample of the onboarding view is shown)
Here, we make use of `WidgetbookUseCase` annotation which takes in two arguments; A title of the view that will show on your Widgetbook dashboard and the type of the data you want to display, this will be used to group widgets of similar type.
NB: A function has to be created and then annotated. This is according to Widgetbook syntax and also to simulate a builder function(i.e. a function that takes in a BuildContext argument and returns a widget.
A similar thing can be done for the rest of the views.
We then move to the `shared` folder, we annotate the Widget similar to how we did for the views, but since these widgets have arguments, we can make it interactive so we can pass data to it from our Widgetbook console.
To achieve this we make use of Knobs. Knobs are UI controls that allow you to interact with and modify the properties of your widgets in real-time. They can be used to adjust properties such as colour, size, and text content, among others.
We start with the `app_button.dart` file, and make the following changes to it.
Here, we assign different knobs to each argument depending on the type of the argument. For String, we use text knob, for double, we use the number knob and also convert it to double to keep it type safe, use boolean for bool types, etc. But for options where the data type does not have a knob, we use the option knob as we did in `prefixWidget`, `suffixWidget` and `fontWeight`.
We do something similar to the other two widgets in the shared folder. We have `app_textfield.dart` updated to:
And `home_item.dart` updated to:
Now that we are done setting up Widgetbook annotations for all our widgets, we start the process of viewing and testing what we have done.
We go to our terminal and run the command
This creates a new file in the root lib folder with the name `main.widgetbook.dart` containing the generated code of our setup earlier. We then set our target device to desktop(or mac) and run this code in our terminal.
As at the time of writing this, Widget book is optimized to run on MacOS, Windows, Linux and Web.
When we run this, we notice that all the screens have errors, this is because there are some setup we are yet to do. They are:
To fix this, we make use of one more annotation, i.e. `WidgetbookAppBuilder`. The `builder` parameter in the `MaterialApp` widget is a callback function that is used to modify the `BuildContext` before it is passed to the `MaterialApp` widget's children. It allows you to customize the widget tree for your app by adding additional widgets or modifying existing ones.
In our case, we will use `WidgetbookAppBuilder` annotation to initialize the service and screen utilities before each widget is built. To do that, we append this code to the `main.dart`
Here, we check if the service is registered and register it if it is not. This is to avoid `service already registered` error when each widget builds. Also we initialize screen utilility for each widget.
We then re-run `build_runner` using the command from earlier
flutter pub run `build_runner build — delete-conflicting-outputs` and hot restart the application. We then see that each screen comes up, we are able to switch device frames, themes, as well as check different orientations, etc. The view should then look like this.
In the first image, we get a preview of different themes available for our application’s home view. The second image shows a preview of the home view on different devices and screen sizes. Lastly, the third image showcases how we can utilize the knobs we set up earlier to manipulate the values passed into a text field widget and observe how it displays it.
With these practical demonstrations, we have gained a better understanding of the potential of Widgetbook.
Widgetbook provides several benefits for Flutter developers and can be a useful tool for UI development and documentation. Some of the benefits include:
In conclusion, Widgetbook is a powerful tool for creating and documenting UI components in Flutter. It provides a simple and efficient way to design and preview widgets in isolation, making it easy to experiment with different configurations and visualize how they would look in the app. Additionally, the ability to export and share stories makes collaboration and code sharing a breeze. Whether you are a solo developer, a member of a team, or an open-source contributor, Widgetbook can help streamline your UI development process and improve the quality of your code.
With Widgetbook, creating functional and testable UI components has never been easier. Keep exploring the many features and capabilities of Widgetbook to unlock its full potential and take your UI development to the next level.