flutter-add-widget-preview

Ajoute des aperçus interactifs de widgets au projet via le système previews.dart. À utiliser lors de la création de nouveaux composants UI ou de la mise à jour d'écrans existants pour garantir un design cohérent et des tests interactifs.

npx skills add https://github.com/flutter/skills --skill flutter-add-widget-preview

Prévisualisation des widgets Flutter

Sommaire

Directives de prévisualisation

Utilisez le Widget Previewer de Flutter pour afficher les widgets en temps réel, isolés du contexte complet de l'application.

  • Éléments cibles : Appliquez l'annotation @Preview à des fonctions de niveau supérieur, des méthodes statiques au sein d'une classe, ou des constructeurs/factories de widget publics sans arguments requis et retournant un Widget ou WidgetBuilder.
  • Imports : Importez toujours package:flutter/widget_previews.dart pour accéder aux annotations de prévisualisation.
  • Annotations personnalisées : Étendez la classe Preview pour créer des annotations personnalisées qui injectent des propriétés communes (par exemple, thèmes, wrappers) à travers plusieurs widgets.
  • Configurations multiples : Appliquez plusieurs annotations @Preview à une même cible pour générer plusieurs instances de prévisualisation. Alternativement, étendez MultiPreview pour encapsuler les configurations multi-prévisualisation courantes.
  • Transformations à l'exécution : Surchargez la méthode transform() dans les classes Preview ou MultiPreview personnalisées pour modifier les configurations de prévisualisation dynamiquement à l'exécution (par exemple, générer des noms basés sur des valeurs dynamiques, ce qui est impossible dans un contexte const).

Gestion des limitations

Respectez les contraintes suivantes lors de la création de widgets prévisualisables, car le Widget Previewer s'exécute dans un environnement web :

  • Pas d'APIs natives : N'utilisez pas de plugins natifs ni d'APIs provenant de dart:io ou dart:ffi. Les widgets avec des dépendances transitives sur dart:io ou dart:ffi lèveront des exceptions lors de l'invocation. Utilisez des imports conditionnels pour les simuler ou les contourner en mode prévisualisation.
  • Chemins des ressources : Utilisez des chemins basés sur les packages pour les ressources chargées via les APIs fromAsset de dart:ui (par exemple, packages/my_package_name/assets/my_image.png au lieu de assets/my_image.png).
  • Callbacks publics : Assurez-vous que tous les arguments de callback fournis aux annotations de prévisualisation sont publics et constants pour satisfaire les exigences de génération de code.
  • Contraintes : Appliquez des contraintes explicites via le paramètre size de l'annotation @Preview si votre widget n'est pas contraint, car le previewer les contraint par défaut à approximativement la moitié de la fenêtre d'affichage.

Workflows

Créer une prévisualisation de widget

Copiez et suivez cette liste de contrôle lors de l'implémentation d'une nouvelle prévisualisation de widget :

  • [ ] Importez package:flutter/widget_previews.dart.
  • [ ] Identifiez une cible valide (fonction de niveau supérieur, méthode statique, ou constructeur public sans paramètres).
  • [ ] Appliquez l'annotation @Preview à la cible.
  • [ ] Configurez les paramètres de prévisualisation (name, group, size, theme, brightness, etc.) selon vos besoins.
  • [ ] Si vous appliquez la même configuration à plusieurs widgets, extrayez la configuration dans une classe personnalisée étendant Preview.

Interagir avec les prévisualisations

Suivez le workflow conditionnel approprié pour lancer et interagir avec le Widget Previewer :

Si vous utilisez un IDE supporté (Android Studio, IntelliJ, VS Code avec Flutter 3.38+) :

  1. Lancez l'IDE. Le Widget Previewer démarre automatiquement.
  2. Ouvrez l'onglet « Flutter Widget Preview » dans la barre latérale.
  3. Basculez « Filter previews by selected file » en bas à gauche si vous souhaitez afficher les prévisualisations en dehors du fichier actuellement actif.

Si vous utilisez la ligne de commande :

  1. Accédez au répertoire racine du projet Flutter.
  2. Exécutez flutter widget-preview start.
  3. Consultez l'environnement Chrome qui s'ouvre automatiquement.

Boucle de rétroaction : Itération de prévisualisation

  1. Modifiez le code du widget ou la configuration de prévisualisation.
  2. Observez la mise à jour automatique dans le Widget Previewer.
  3. Si l'état global (par exemple, les initialisateurs statiques) a été modifié : Cliquez sur le bouton de redémarrage à chaud global en bas à droite.
  4. Si seul l'état local du widget doit être réinitialisé : Cliquez sur le bouton de redémarrage à chaud individuel sur la carte de prévisualisation spécifique.
  5. Examinez les erreurs dans la console IDE/CLI -> corrigez -> répétez.

Exemples

Prévisualisation basique

import 'package:flutter/widget_previews.dart';
import 'package:flutter/material.dart';

@Preview(name: 'My Sample Text', group: 'Typography')
Widget mySampleText() {
  return const Text('Hello, World!');
}

Prévisualisation personnalisée avec transformation à l'exécution

import 'package:flutter/widget_previews.dart';
import 'package:flutter/material.dart';

final class TransformativePreview extends Preview {
  const TransformativePreview({
    super.name,
    super.group,
  });

  PreviewThemeData _themeBuilder() {
    return PreviewThemeData(
      materialLight: ThemeData.light(),
      materialDark: ThemeData.dark(),
    );
  }

  @override
  Preview transform() {
    final originalPreview = super.transform();
    final builder = originalPreview.toBuilder();

    builder
      ..name = 'Transformed - ${originalPreview.name}'
      ..theme = _themeBuilder;

    return builder.toPreview();
  }
}

@TransformativePreview(name: 'Custom Themed Button')
Widget myButton() => const ElevatedButton(onPressed: null, child: Text('Click'));

Implémentation MultiPreview

import 'package:flutter/widget_previews.dart';
import 'package:flutter/material.dart';

/// Crée automatiquement des prévisualisations en mode clair et sombre.
final class MultiBrightnessPreview extends MultiPreview {
  const MultiBrightnessPreview({required this.name});

  final String name;

  @override
  List<Preview> get previews => const [
        Preview(brightness: Brightness.light),
        Preview(brightness: Brightness.dark),
      ];

  @override
  List<Preview> transform() {
    final previews = super.transform();
    return previews.map((preview) {
      final builder = preview.toBuilder()
        ..group = 'Brightness'
        ..name = '$name - ${preview.brightness!.name}';
      return builder.toPreview();
    }).toList();
  }
}

@MultiBrightnessPreview(name: 'Primary Card')
Widget cardPreview() => const Card(child: Padding(padding: EdgeInsets.all(8.0), child: Text('Content')));

Skills similaires