$npx -y skills add flutter/agent-plugins --skill flutter-add-widget-previewAdds interactive widget previews to the project using the previews.dart system. Use when creating new UI components or updating existing screens to ensure consistent design and interactive testing.
| 1 | # Previewing Flutter Widgets |
| 2 | |
| 3 | ## Contents |
| 4 | - [Preview Guidelines](#preview-guidelines) |
| 5 | - [Handling Limitations](#handling-limitations) |
| 6 | - [Workflows](#workflows) |
| 7 | - [Examples](#examples) |
| 8 | |
| 9 | ## Preview Guidelines |
| 10 | |
| 11 | Use the Flutter Widget Previewer to render widgets in real-time, isolated from the full application context. |
| 12 | |
| 13 | - **Target Elements:** Apply the `@Preview` annotation to top-level functions, static methods within a class, or public widget constructors/factories that have no required arguments and return a `Widget` or `WidgetBuilder`. |
| 14 | - **Imports:** Always import `package:flutter/widget_previews.dart` to access the preview annotations. |
| 15 | - **Custom Annotations:** Extend the `Preview` class to create custom annotations that inject common properties (e.g., themes, wrappers) across multiple widgets. |
| 16 | - **Multiple Configurations:** Apply multiple `@Preview` annotations to a single target to generate multiple preview instances. Alternatively, extend `MultiPreview` to encapsulate common multi-preview configurations. |
| 17 | - **Runtime Transformations:** Override the `transform()` method in custom `Preview` or `MultiPreview` classes to modify preview configurations dynamically at runtime (e.g., generating names based on dynamic values, which is impossible in a `const` context). |
| 18 | |
| 19 | ## Handling Limitations |
| 20 | |
| 21 | Adhere to the following constraints when authoring previewable widgets, as the Widget Previewer runs in a web environment: |
| 22 | |
| 23 | - **No Native APIs:** Do not use native plugins or APIs from `dart:io` or `dart:ffi`. Widgets with transitive dependencies on `dart:io` or `dart:ffi` will throw exceptions upon invocation. Use conditional imports to mock or bypass these in preview mode. |
| 24 | - **Asset Paths:** Use package-based paths for assets loaded via `dart:ui` `fromAsset` APIs (e.g., `packages/my_package_name/assets/my_image.png` instead of `assets/my_image.png`). |
| 25 | - **Public Callbacks:** Ensure all callback arguments provided to preview annotations are public and constant to satisfy code generation requirements. |
| 26 | - **Constraints:** Apply explicit constraints using the `size` parameter in the `@Preview` annotation if your widget is unconstrained, as the previewer defaults to constraining them to approximately half the viewport. |
| 27 | |
| 28 | ## Workflows |
| 29 | |
| 30 | ### Creating a Widget Preview |
| 31 | Copy and track this checklist when implementing a new widget preview: |
| 32 | |
| 33 | - [ ] Import `package:flutter/widget_previews.dart`. |
| 34 | - [ ] Identify a valid target (top-level function, static method, or parameter-less public constructor). |
| 35 | - [ ] Apply the `@Preview` annotation to the target. |
| 36 | - [ ] Configure preview parameters (`name`, `group`, `size`, `theme`, `brightness`, etc.) as needed. |
| 37 | - [ ] If applying the same configuration to multiple widgets, extract the configuration into a custom class extending `Preview`. |
| 38 | |
| 39 | ### Interacting with Previews |
| 40 | Follow the appropriate conditional workflow to launch and interact with the Widget Previewer: |
| 41 | |
| 42 | **If using a supported IDE (Android Studio, IntelliJ, VS Code with Flutter 3.38+):** |
| 43 | 1. Launch the IDE. The Widget Previewer starts automatically. |
| 44 | 2. Open the "Flutter Widget Preview" tab in the sidebar. |
| 45 | 3. Toggle "Filter previews by selected file" at the bottom left if you want to view previews outside the currently active file. |
| 46 | |
| 47 | **If using the Command Line:** |
| 48 | 1. Navigate to the Flutter project's root directory. |
| 49 | 2. Run `flutter widget-preview start`. |
| 50 | 3. View the automatically opened Chrome environment. |
| 51 | |
| 52 | **Feedback Loop: Preview Iteration** |
| 53 | 1. Modify the widget code or preview configuration. |
| 54 | 2. Observe the automatic update in the Widget Previewer. |
| 55 | 3. If global state (e.g., static initializers) was modified: Click the global hot restart button at the bottom right. |
| 56 | 4. If only the local widget state needs resetting: Click the individual hot restart button on the specific preview card. |
| 57 | 5. Review errors in the IDE/CLI console -> fix -> repeat. |
| 58 | |
| 59 | ## Examples |
| 60 | |
| 61 | ### Basic Preview |
| 62 | ```dart |
| 63 | import 'package:flutter/widget_previews.dart'; |
| 64 | import 'package:flutter/material.dart'; |
| 65 | |
| 66 | @Preview(name: 'My Sample Text', group: 'Typography') |
| 67 | Widget mySampleText() { |
| 68 | return const Text('Hello, World!'); |
| 69 | } |
| 70 | ``` |
| 71 | |
| 72 | ### Custom Preview with Runtime Transformation |
| 73 | ```dart |
| 74 | import 'package:flutter/widget_previews.dart'; |
| 75 | import 'package:flutter/material.dart'; |
| 76 | |
| 77 | final class TransformativePreview extends Preview { |
| 78 | const TransformativePreview({ |
| 79 | super.name, |
| 80 | super.group, |
| 81 | }); |
| 82 | |
| 83 | PreviewThemeData _themeBuilder() { |
| 84 | return PreviewThemeData( |
| 85 | materialLight: ThemeData.light(), |
| 86 | materialDark: ThemeData.dark(), |
| 87 | ); |
| 88 | } |
| 89 | |
| 90 | @override |
| 91 | Preview transform() { |
| 92 | final originalPreview = super.transform(); |
| 93 | final builder = o |