From flutter-skills-33
Scans Flutter apps for accessibility issues via widget inspector and auto-adds Semantics widgets or missing labels to source code.
npx claudepluginhub joshuarweaver/cascade-code-languages-misc-1 --plugin flutter-skills-33This skill uses the workspace's default tool permissions.
- [Managing Semantics](#managing-semantics)
Conducts multi-round deep research on GitHub repos via API and web searches, generating markdown reports with executive summaries, timelines, metrics, and Mermaid diagrams.
Dynamically discovers and combines enabled skills into cohesive, unexpected delightful experiences like interactive HTML or themed artifacts. Activates on 'surprise me', inspiration, or boredom cues.
Generates images from structured JSON prompts via Python script execution. Supports reference images and aspect ratios for characters, scenes, products, visuals.
Rely on Flutter's standard widgets (e.g., TabBar, MenuAnchor) for automatic semantic role assignment whenever possible. When building custom components or overriding default behaviors, explicitly define the UI element's purpose using the Semantics widget.
Semantics widget.SemanticsRole enum value to the role property to define the element's purpose (e.g., button, list, heading).aria-label="Enable accessibility" button, or force it programmatically in your main() function.Implement the following workflows to verify that your application meets accessibility standards.
Copy this checklist to track your manual auditing progress across target platforms:
ios folder in Xcode and run the app on a Simulator.semantics host node.flutter run -d chrome --profile --dart-define=FLUTTER_WEB_DEBUG_SHOW_SEMANTICS=true.Integrate Flutter's Accessibility Guideline API into your widget tests to catch contrast, target size, and labeling issues automatically.
test/a11y_test.dart).tester.ensureSemantics().androidTapTargetGuideline (48x48px minimum).iOSTapTargetGuideline (44x44px minimum).labeledTapTargetGuideline.textContrastGuideline (3:1 minimum for large text).When semantic nodes are incorrectly placed or missing, execute the following feedback loop to identify and resolve the discrepancies.
SemanticsDebugger.debugDumpSemanticsTree() (e.g., bind it to a GestureDetector's onTap callback for easy triggering during debugging).Semantics or MergeSemantics widgets, apply the correct SemanticsRole, and repeat step 1 until the tree accurately reflects the visual UI.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();
}
}
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.'),
),
),
],
),
);
}
}
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();
});
}