vgv-ui-package

Par verygoodopensource · vgv-ai-flutter-plugin

Bonnes pratiques pour créer un package Flutter UI au-dessus de Material — composants personnalisés, thématisation basée sur `ThemeExtension`, API cohérentes et tests de widgets. Compatible avec le template `app_ui_package`.

npx skills add https://github.com/verygoodopensource/vgv-ai-flutter-plugin --skill vgv-ui-package

UI Package

Meilleures pratiques pour créer un package UI Flutter — une bibliothèque de widgets réutilisables qui s'appuie sur package:flutter/material.dart, l'étend avec des composants spécifiques à l'application, des design tokens personnalisés via ThemeExtension, et une surface API cohérente.

Fondation de thématisation : Cette skill se concentre sur la structure du package UI, les APIs de widgets et les tests. Pour la thématisation Material 3 fondamentale (ColorScheme, TextTheme, thèmes de composants, constantes d'espacement, mode clair/sombre), voir la skill Material Theming (/vgv-material-theming). Les deux skills sont complémentaires — Material Theming couvre comment configurer et utiliser ThemeData ; cette skill couvre comment l'étendre avec des tokens ThemeExtension et packager des widgets réutilisables autour.

Standards Fondamentaux

Appliquez ces standards à TOUS les travaux de package UI :

  • Construire sur Material — dépendre de flutter/material.dart et composer des widgets Material ; ne pas reconstruire les primitives que Material fournit déjà
  • Un widget par fichier — chaque widget public vit dans son propre fichier nommé d'après le widget en snake_case (ex. app_button.dart)
  • Fichier barrel pour l'API publique — exposer tous les widgets publics et les classes de thème via un unique fichier barrel (ex. lib/my_ui.dart) qui ré-exporte aussi material.dart
  • Étendre la thématisation avec ThemeExtension — utiliser ThemeData, ColorScheme, et TextTheme de Material comme base (voir skill Material Theming) ; ajouter des tokens spécifiques à l'application (espacement, couleurs personnalisées) via ThemeExtension<T>
  • Chaque widget a un test de widget correspondant — les tests comportementaux vérifient les interactions, callbacks et changements d'état
  • Préfixer toutes les classes publiques — utiliser un préfixe cohérent (ex. App, Vg) pour éviter les collisions de noms avec les widgets Material
  • Utiliser des constructeurs const partout où possible — tous les constructeurs de widget doivent être const quand c'est possible
  • Documenter chaque membre public — chaque classe publique, paramètre de constructeur et méthode a un commentaire dartdoc

Structure du Package

my_ui/
├── lib/
│   ├── my_ui.dart              # Fichier barrel — ré-exporte material.dart + toute l'API publique
│   └── src/
│       ├── theme/
│       │   ├── app_theme.dart        # Classe AppTheme avec les builders ThemeData clair/sombre
│       │   ├── app_colors.dart       # ThemeExtension AppColors pour les tokens de couleur personnalisés
│       │   ├── app_spacing.dart      # ThemeExtension AppSpacing pour les tokens d'espacement
│       │   └── app_text_styles.dart  # Optionnel : styles de texte supplémentaires au-delà de TextTheme de Material
│       ├── widgets/
│       │   ├── app_button.dart
│       │   ├── app_text_field.dart
│       │   ├── app_card.dart
│       │   └── ...
│       └── extensions/
│           └── build_context_extensions.dart  # Raccourcis context.appColors, context.appSpacing
├── test/
│   ├── src/
│   │   ├── theme/
│   │   │   └── app_theme_test.dart
│   │   └── widgets/
│   │       ├── app_button_test.dart
│   │       └── ...
│   └── helpers/
│       └── pump_app.dart         # Helper de test wrappant les widgets dans MaterialApp + thème
├── widgetbook/                   # Sous-module catalogue Widgetbook (sandbox + showcase)
│   └── ...
└── pubspec.yaml

Construire des Widgets

Directives d'API de Widget

  • Composer des widgets Material — utiliser FilledButton, OutlinedButton, TextField, Card, etc. comme briques de construction
  • Accepter uniquement les paramètres strictement nécessaires — éviter les constructeurs « fourre-tout »
  • Utiliser des paramètres nommés pour tout sauf key et child/children
  • Fournir des valeurs par défaut sensées dérivées du thème quand un paramètre n'est pas fourni
  • Exposer les callbacks avec ValueChanged<T> ou VoidCallback — ne pas utiliser Function brut
  • Utiliser Widget? pour la composition optionnelle basée sur des slots (icônes leading, trailing, etc.)

Anti-Patterns

Anti-Pattern Approche Correcte
Reconstruire des widgets que Material fournit déjà (ex. bouton personnalisé à partir de GestureDetector + DecoratedBox) Composer des widgets Material (FilledButton, OutlinedButton) et les styliser
Créer un système de thème parallèle avec InheritedWidget personnalisé Utiliser ThemeData de Material comme base et ThemeExtension pour les tokens personnalisés
Hardcoder Color(0xFF...) dans le code du widget Utiliser Theme.of(context).colorScheme pour les couleurs standard et context.appColors pour les tokens personnalisés
Dupliquer les rôles ColorScheme de Material dans une classe personnalisée Créer des tokens ThemeExtension uniquement pour les valeurs que Material ne couvre pas (ex. success, warning, info)
Utiliser dynamic ou Object pour les types de callback Utiliser VoidCallback, ValueChanged<T>, ou des typedefs de fonction spécifiques
Exposer directement les fichiers d'implémentation interne Utiliser un fichier barrel ; garder tous les fichiers sous src/ privés

Créer le Package

Utiliser l'outil MCP Very Good CLI pour scaffolder l'app_ui_package.

Skills similaires