flutter-accessibility-audit

Déclenche une analyse d'accessibilité via le widget_inspector et ajoute automatiquement des widgets Semantics ou des labels manquants au code source.

npx skills add https://github.com/flutter/skills --skill flutter-accessibility-audit

Mise en œuvre de l'accessibilité Flutter

Table des matières

Gestion de la sémantique

Appuyez-vous sur les widgets standard de Flutter (par exemple, TabBar, MenuAnchor) pour l'attribution automatique des rôles sémantiques dans la mesure du possible. Lors de la création de composants personnalisés ou du remplacement des comportements par défaut, définissez explicitement l'objectif de l'élément d'interface utilisateur à l'aide du widget Semantics.

  • Enveloppez les composants d'interface utilisateur personnalisés dans un widget Semantics.
  • Attribuez la valeur d'énumération SemanticsRole appropriée à la propriété role pour définir l'objectif de l'élément (par exemple, bouton, liste, titre).
  • Si vous développez pour Flutter Web, notez que Flutter traduit ces rôles en rôles ARIA correspondants dans le DOM HTML.
  • Activez explicitement l'accessibilité web. Elle est désactivée par défaut pour des raisons de performance. Soit demandez aux utilisateurs d'appuyer sur le bouton invisible aria-label="Enable accessibility", soit forcez-le par programmation dans votre fonction main().

Audit de l'accessibilité

Mettez en œuvre les workflows suivants pour vérifier que votre application respecte les normes d'accessibilité.

Progression des tâches : Analyse spécifique à la plateforme

Copiez cette liste de contrôle pour suivre votre progression d'audit manuel sur les plateformes cibles :

  • [ ] Si vous testez sur Android :
    1. Installez l'Accessibility Scanner à partir de Google Play.
    2. Activez-le via Settings > Accessibility > Accessibility Scanner > On.
    3. Appuyez sur l'icône de coche d'Accessibility Scanner au-dessus de votre application en cours d'exécution pour lancer l'analyse.
  • [ ] Si vous testez sur iOS :
    1. Ouvrez le dossier ios dans Xcode et exécutez l'application sur un Simulator.
    2. Accédez à Xcode > Open Developer Tools > Accessibility Inspector.
    3. Sélectionnez Inspection > Enable Point to Inspect et cliquez sur les éléments d'interface utilisateur pour vérifier les attributs.
    4. Sélectionnez Audit > Run Audit pour générer un rapport de problèmes.
  • [ ] Si vous testez sur Web :
    1. Ouvrez Chrome DevTools.
    2. Inspectez l'arborescence HTML sous le nœud semantics host.
    3. Accédez à l'onglet Elements et ouvrez le sous-onglet Accessibility pour inspecter les données ARIA exportées.
    4. Visualisez les nœuds sémantiques en exécutant l'application avec : flutter run -d chrome --profile --dart-define=FLUTTER_WEB_DEBUG_SHOW_SEMANTICS=true.

Progression des tâches : Tests automatisés

Intégrez l'API Accessibility Guideline de Flutter dans vos tests de widget pour détecter automatiquement les problèmes de contraste, de taille de cible et d'étiquetage.

  • [ ] Créez un fichier de test dédié (par exemple, test/a11y_test.dart).
  • [ ] Initialisez la poignée de sémantique en utilisant tester.ensureSemantics().
  • [ ] Faites des assertions par rapport à androidTapTargetGuideline (minimum 48x48px).
  • [ ] Faites des assertions par rapport à iOSTapTargetGuideline (minimum 44x44px).
  • [ ] Faites des assertions par rapport à labeledTapTargetGuideline.
  • [ ] Faites des assertions par rapport à textContrastGuideline (minimum 3:1 pour le texte large).
  • [ ] Disposez de la poignée de sémantique à la fin du test.

Débogage de l'arborescence sémantique

Lorsque les nœuds sémantiques sont mal placés ou manquants, exécutez la boucle de rétroaction suivante pour identifier et résoudre les divergences.

  1. Exécutez le validateur : Déclenchez un vidage de l'arborescence Semantics sur la console.
    • Activez l'accessibilité via un outil système ou SemanticsDebugger.
    • Invoquez debugDumpSemanticsTree() (par exemple, liez-le au rappel onTap d'un GestureDetector pour un déclenchement facile lors du débogage).
  2. Passez en revue les erreurs : Analysez la sortie de la console pour localiser les étiquettes manquantes, les rôles incorrects ou les nœuds sémantiques mal imbriqués.
  3. Corrigez : Enveloppez les widgets problématiques dans des widgets Semantics ou MergeSemantics, appliquez le bon SemanticsRole, et répétez l'étape 1 jusqu'à ce que l'arborescence reflète avec précision l'interface utilisateur visuelle.

Exemples

Activation par programmation de l'accessibilité Web

Forcez l'arborescence Semantics à se construire immédiatement sur Flutter Web.

import 'package:flutter/foundation.dart';
import 'package:flutter/material.dart';
import 'package:flutter/semantics.dart';

void main() {
  runApp(const MyApp());
  if (kIsWeb) {
    SemanticsBinding.instance.ensureSemantics();
  }
}

Définition explicite des rôles sémantiques

Attribuez des rôles de liste et d'élément de liste explicites à une disposition personnalisée.

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

class MyCustomListWidget extends StatelessWidget {
  const MyCustomListWidget({Key? key}) : super(key: key);

  @override
  Widget build(BuildContext context) {
    return Semantics(
      role: SemanticsRole.list,
      explicitChildNodes: true,
      child: Column(
        children: <Widget>[
          Semantics(
            role: SemanticsRole.listItem,
            child: const Padding(
              padding: EdgeInsets.all(8.0),
              child: Text('Content of the first custom list item.'),
            ),
          ),
          Semantics(
            role: SemanticsRole.listItem,
            child: const Padding(
              padding: EdgeInsets.all(8.0),
              child: Text('Content of the second custom list item.'),
            ),
          ),
        ],
      ),
    );
  }
}

Tests d'accessibilité automatisés

Mettez en œuvre l'API Accessibility Guideline dans un test de widget.

import 'package:flutter_test/flutter_test.dart';
import 'package:your_accessible_app/main.dart';

void main() {
  testWidgets('Follows a11y guidelines', (tester) async {
    final SemanticsHandle handle = tester.ensureSemantics();
    await tester.pumpWidget(const AccessibleApp());

    // Check tap target sizes
    await expectLater(tester, meetsGuideline(androidTapTargetGuideline));
    await expectLater(tester, meetsGuideline(iOSTapTargetGuideline));

    // Check labels and contrast
    await expectLater(tester, meetsGuideline(labeledTapTargetGuideline));
    await expectLater(tester, meetsGuideline(textContrastGuideline));

    handle.dispose();
  });
}