flutter-accessibility-audit

Triggers an accessibility scan through the widget_inspector and automatically adds Semantics widgets or missing labels to the source code.

INSTALLATION
npx skills add https://github.com/flutter/skills --skill flutter-accessibility-audit
Run in your project or agent environment. Adjust flags if your CLI version differs.

SKILL.md

$27

Task Progress: Platform-Specific Scanning

Copy this checklist to track your manual auditing progress across target platforms:

  • If testing on Android:
  • Install the Accessibility Scanner from Google Play.
  • Enable it via Settings > Accessibility > Accessibility Scanner > On.
  • Tap the Accessibility Scanner checkmark icon over your running app to initiate the scan.
  • If testing on iOS:
  • Open the ios folder in Xcode and run the app on a Simulator.
  • Navigate to Xcode > Open Developer Tools > Accessibility Inspector.
  • Select Inspection > Enable Point to Inspect and click UI elements to verify attributes.
  • Select Audit > Run Audit to generate an issue report.
  • If testing on Web:
  • Open Chrome DevTools.
  • Inspect the HTML tree under the semantics host node.
  • Navigate to the Elements tab and open the Accessibility sub-tab to inspect exported ARIA data.
  • Visualize semantic nodes by running the app with: flutter run -d chrome --profile --dart-define=FLUTTER_WEB_DEBUG_SHOW_SEMANTICS=true.

Task Progress: Automated Testing

Integrate Flutter's Accessibility Guideline API into your widget tests to catch contrast, target size, and labeling issues automatically.

  • Create a dedicated test file (e.g., test/a11y_test.dart).
  • Initialize the semantics handle using tester.ensureSemantics().
  • Assert against androidTapTargetGuideline (48x48px minimum).
  • Assert against iOSTapTargetGuideline (44x44px minimum).
  • Assert against labeledTapTargetGuideline.
  • Assert against textContrastGuideline (3:1 minimum for large text).
  • Dispose of the semantics handle at the end of the test.

Debugging the Semantics Tree

When semantic nodes are incorrectly placed or missing, execute the following feedback loop to identify and resolve the discrepancies.

  • Run validator: Trigger a dump of the Semantics tree to the console.
  • Enable accessibility via a system tool or SemanticsDebugger.
  • Invoke debugDumpSemanticsTree() (e.g., bind it to a GestureDetector's onTap callback for easy triggering during debugging).
  • Review errors: Analyze the console output to locate missing labels, incorrect roles, or improperly nested semantic nodes.
  • Fix: Wrap the offending widgets in Semantics or MergeSemantics widgets, apply the correct SemanticsRole, and repeat step 1 until the tree accurately reflects the visual UI.

Examples

Programmatically Enabling Web Accessibility

Force the Semantics tree to build immediately on 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();

  }

}

Explicitly Defining Semantic Roles

Assign explicit list and list-item roles to a custom layout.

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.'),

            ),

          ),

        ],

      ),

    );

  }

}

Automated Accessibility Testing

Implement the Accessibility Guideline API in a widget test.

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();

  });

}
BrowserAct

Let your agent run on any real-world website

Bypass CAPTCHA & anti-bot for free. Start local, scale to cloud.

Explore BrowserAct Skills →

Stop writing automation&scrapers

Install the CLI. Run your first Skill in 30 seconds. Scale when you're ready.

Start free
free · no credit card