Come usare
- Copia il comando e controlla il pacchetto prima di installarlo nel tuo ambiente agente.
- Controlla strumenti, credenziali e ambienti richiesti nel documento originale.
- Descrivi input e risultato desiderato; confronta l’output con le fonti.
npx skills add https://github.com/thesimpleapp/flutter-app-skills --skill flutter-improving-accessibilityPrima di iniziare
- L’installazione non include abbonamenti, quote API o accesso ai file.
- Stelle e installazioni indicano attività, non un test indipendente di qualità o sicurezza.
Contenuto dal repository con titoli, esempi, codice, tabelle, link e immagini preservati.
Flutter accessibility
Prefer built-in Material and Cupertino widgets — they already emit a TalkBack / VoiceOver / JAWS / NVDA tree. Add Semantics (or Semantics.fromProperties) only on custom painted or gestured widgets.
If this repo already has a Semantics helper, a11y test harness, labeled-control convention, or a pressable with semanticLabel, extend that. Do not wrap it in a second Semantics(label:) that repeats visible text.
Official: Accessibility, assistive technologies, UI design and styling, accessibility testing.
References
Read references/recipes.md when implementing a custom control, merge/exclude/block, MediaQuery wiring, or the guideline test.
Detect first
Search the repo for Semantics(, MergeSemantics, ExcludeSemantics, BlockSemantics, semanticLabel, excludeFromSemantics, tooltip:, meetsGuideline(, ensureSemantics(, highContrastTheme, accessibleNavigationOf, textScalerOf. Open a nearby production screen and copy that pattern.
Hard rules
Semantics
- Custom paint /
GestureDetector/InkWell: setlabel, a role flag (button,slider,textField),tooltip/hint, andonTapso the node is announced as a control. - Role is a flag:
Semantics(button: true, label: 'Submit'). Never put "button" in the label.label/hint/tooltiprequire an ambientDirectionalityor an explicittextDirection. Transient status:liveRegion: true. container: trueintroduces aSemanticsNode— use it for a distinct TalkBack/VoiceOver focus stop.
Merge, exclude, block
- One control + its visible
Text: wrap both inMergeSemantics. Never merge two checkboxes, two tappable children, or conflictingselected/checkedvalues. ExcludeSemanticsonly for decorative or redundant descendants.Semantics(excludeSemantics: true)replaces all child semantics with this node. Hide widgets painted behind a modal orDrawerwithBlockSemanticson the overlay, notExcludeSemanticson the overlay child.
Hit targets and names
- Every tappable target ≥ 48×48 logical pixels (
kMinInteractiveDimension). Cupertino floor iskMinInteractiveDimensionCupertino(44.0). PreferIconButtonso the hit region stays 48 regardless oficonSize. Do not passIconButton.constraintsor compactVisualDensitythat shrinks below 48. - Icon-only
IconButton/ FAB:tooltipis a short action name. Custom icon taps:Semantics(label: ..., button: true). DecorativeIcon:semanticLabel. MeaningfulImage:semanticLabel. DecorativeImage:excludeFromSemantics: true.
Text scale
- Read with
MediaQuery.textScalerOf(context)and compute sizes withtextScaler.scale(fontSize). NevertextScaleFactor— deprecated and cannot represent Android 14 nonlinear scaling. Textalready honors the OS font-size setting. Test every screen on a small device at the largest OS text size.MediaQuery.withNoTextScalingonly to stop icon fonts from scaling. Never disable scaling at theMaterialApproot.
MediaQuery flags
- Call
MediaQuery.accessibleNavigationOf,highContrastOf,disableAnimationsOf, andtextScalerOf— notMediaQuery.of. - When
accessibleNavigationOfis true, disable timeouts or raise their minimum duration. - When
highContrastOfis true, setMaterialApp.highContrastThemeandhighContrastDarkTheme. Wrapping a subtree inMediaQuery(data: copyWith(highContrast: true))does not switch those themes. disableAnimationsOfis Android Remove animations.AnimationControlleralready honorsSemanticsBinding.disableAnimations. Custom explicit animations must still readdisableAnimationsOf. iOS Reduce Motion isAccessibilityFeatures.reduceMotionand does not setdisableAnimations.
Traversal
- TalkBack/VoiceOver sibling order:
Semantics(sortKey: OrdinalSortKey(n)). Keyboard/Tab order is a different tree:FocusTraversalGroup/FocusTraversalOrder. Do not usesortKeyto fix Tab order.
Contrast
- At least 4.5:1 between text/controls and background (except disabled). 3.0:1 for large text (18pt+ regular or 14pt+ bold). Do not convey state by color alone.
Tests and devices
tester.ensureSemantics(), thenexpectLater(tester, meetsGuideline(...)), thenhandle.dispose(). Guidelines:androidTapTargetGuideline,iOSTapTargetGuideline,labeledTapTargetGuideline,textContrastGuideline.- Walk every changed screen with TalkBack and VoiceOver. Flutter web:
SemanticsBinding.instance.ensureSemantics()inmain(). Debug withshowSemanticsDebuggerorflutter run -d chrome --profile --dart-define=FLUTTER_WEB_DEBUG_SHOW_SEMANTICS=true.
Samples
Semantics(
button: true,
label: 'Submit',
hint: 'Sends the form',
onTap: onSubmit,
child: CustomPaint(painter: SubmitPainter()),
)
IconButton(
tooltip: 'Search',
icon: const Icon(Icons.search),
onPressed: onSearch,
)
final TextScaler scaler = MediaQuery.textScalerOf(context);
final bool screenReader = MediaQuery.accessibleNavigationOf(context);Do not
- Wrap an already-semantic Material/Cupertino widget in
Semantics(label:)that repeats visible text. - Put
ExcludeSemanticsaround interactive content, or use it instead ofBlockSemanticsto hide widgets behind a dialog. MergeSemanticsover two checkboxes or two tappable children.- Icon-only control with no
tooltip, noSemantics.label, and noIcon.semanticLabel. MediaQuery.of(context).textScaleFactororText(textScaleFactor:).- Disable text scaling at the app root, or shrink
IconButtonbelow 48. - Assume
MediaQuery(data: copyWith(disableAnimations: true))stopsAnimationController. - Write the role into the label (
label: 'Submit button'). - Use
Semantics.sortKeyto fix keyboard Tab order.
Fix a screen
- Detect the existing a11y convention and reuse it.
- Leave stock Material/Cupertino widgets unlabeled unless they are custom-painted or icon-only.
- Give every icon-only control a
tooltiporSemantics(label:, button: true). Pad the hit target to 48, not the glyph. - Read
MediaQuery.*Of. Honor largest text, high-contrast themes, screen-reader timeouts, and reduced motion. - Add the guideline test. Walk TalkBack and VoiceOver.
Verify
tester.ensureSemantics()+ the fourmeetsGuidelinechecks +handle.dispose()on the screen you touched.- Layout still fits at the OS largest text size on a small device.
- Contrast ≥ 4.5:1 (3:1 large text); state is not color-only.
- TalkBack and VoiceOver: every control has an intelligible name and the right role.
- Web: semantics enabled from
main().



