diff --git a/src/_data/sidenav.yml b/src/_data/sidenav.yml index 76478c4a4de..6fc28d4b05e 100644 --- a/src/_data/sidenav.yml +++ b/src/_data/sidenav.yml @@ -424,13 +424,22 @@ - title: API overview permalink: /ui/animations/overview -- title: Accessibility & internationalization - permalink: /ui/accessibility-and-internationalization +- title: Accessibility + permalink: /ui/accessibility children: - - title: Accessibility - permalink: /ui/accessibility-and-internationalization/accessibility - - title: Internationalization - permalink: /ui/accessibility-and-internationalization/internationalization + - title: Introduction + permalink: /ui/accessibility + - title: UI Design & Styling + permalink: /ui/accessibility/ui-design-and-styling + - title: Assistive technologies + permalink: /ui/accessibility/assistive-technologies + - title: Accessibility testing + permalink: /ui/accessibility/accessibility-testing + - title: Web accessibility + permalink: /ui/accessibility/web-accessibility + +- title: Internationalization + permalink: /ui/internationalization - divider - header: Beyond UI diff --git a/src/content/assets/images/docs/a18n/app-large-fonts.png b/src/content/assets/images/docs/a11y/app-large-fonts.png similarity index 100% rename from src/content/assets/images/docs/a18n/app-large-fonts.png rename to src/content/assets/images/docs/a11y/app-large-fonts.png diff --git a/src/content/assets/images/docs/a18n/app-regular-fonts.png b/src/content/assets/images/docs/a11y/app-regular-fonts.png similarity index 100% rename from src/content/assets/images/docs/a18n/app-regular-fonts.png rename to src/content/assets/images/docs/a11y/app-regular-fonts.png diff --git a/src/content/assets/images/docs/a11y/tap-target-size.png b/src/content/assets/images/docs/a11y/tap-target-size.png new file mode 100644 index 00000000000..0105569a16b Binary files /dev/null and b/src/content/assets/images/docs/a11y/tap-target-size.png differ diff --git a/src/content/assets/images/docs/a11y/text-contrast.png b/src/content/assets/images/docs/a11y/text-contrast.png new file mode 100644 index 00000000000..c169e8ef494 Binary files /dev/null and b/src/content/assets/images/docs/a11y/text-contrast.png differ diff --git a/src/content/ui/accessibility-and-internationalization/accessibility.md b/src/content/ui/accessibility-and-internationalization/accessibility.md deleted file mode 100644 index 9cea2be6cc7..00000000000 --- a/src/content/ui/accessibility-and-internationalization/accessibility.md +++ /dev/null @@ -1,421 +0,0 @@ ---- -title: Accessibility -description: Information on Flutter's accessibility support. ---- - -Ensuring apps are accessible to a broad range of users is an essential -part of building a high-quality app. Applications that are poorly -designed create barriers to people of all ages. The [UN Convention on -the Rights of Persons with Disabilities][CRPD] states the moral and legal -imperative to ensure universal access to information systems; countries -around the world enforce accessibility as a requirement; and companies -recognize the business advantages of maximizing access to their services. - -We strongly encourage you to include an accessibility checklist -as a key criteria before shipping your app. Flutter is committed to -supporting developers in making their apps more accessible, and includes -first-class framework support for accessibility in addition to that -provided by the underlying operating system, including: - -[**Large fonts**][] -: Render text widgets with user-specified font sizes - -[**Screen readers**][] -: Communicate spoken feedback about UI contents - -[**Sufficient contrast**][] -: Render widgets with colors that have sufficient contrast - -Details of these features are discussed below. - -## Inspecting accessibility support - -In addition to testing for these specific topics, -we recommend using automated accessibility scanners: - -* For Android: - 1. Install the [Accessibility Scanner][] for Android - 1. Enable the Accessibility Scanner from - **Android Settings > Accessibility > - Accessibility Scanner > On** - 1. Navigate to the Accessibility Scanner 'checkbox' - icon button to initiate a scan - -* For iOS: - 1. Open the `iOS` folder of your Flutter app in Xcode - 1. Select a Simulator as the target, and click **Run** button - 1. In Xcode, select - **Xcode > Open Developer Tools > Accessibility Inspector** - 1. In the Accessibility Inspector, - select **Inspection > Enable Point to Inspect**, - and then select the various user interface elements in running - Flutter app to inspect their accessibility attributes - 1. In the Accessibility Inspector, - select **Audit** in the toolbar, and then - select **Run Audit** to get a report of potential issues - -* For web: - 1. Open Chrome DevTools (or similar tools in other browsers) - 2. Inspect the HTML tree containing the ARIA attributes generated by Flutter. - 3. In Chrome, the "Elements" tab has a "Accessibility" sub-tab - that can be used to inspect the data exported to semantics tree - -## Large fonts - -Both Android and iOS contain system settings to configure the desired font -sizes used by apps. Flutter text widgets respect this OS setting when -determining font sizes. - -Font sizes are calculated automatically by Flutter based on the OS setting. -However, as a developer you should make sure your layout has enough room to -render all its contents when the font sizes are increased. -For example, you can test all parts of your app on a small-screen -device configured to use the largest font setting. - -### Example - -The following two screenshots show the standard Flutter app -template rendered with the default iOS font setting, -and with the largest font setting selected in iOS accessibility settings. - -
- {% render docs/app-figure.md, image:"a18n/app-regular-fonts.png", caption:"Default font setting", img-class:"simple-border", img-style:"max-height: 480px;" %} - {% render docs/app-figure.md, image:"a18n/app-large-fonts.png", caption:"Largest accessibility font setting", img-class:"simple-border", img-style:"max-height: 480px;" %} -
- -## Screen readers - -For mobile, screen readers ([TalkBack][], [VoiceOver][]) -enable visually impaired users to get spoken feedback about -the contents of the screen and interact with the UI by using -gestures on mobile and keyboard shortcuts on desktop. -Turn on VoiceOver or TalkBack on your mobile device and -navigate around your app. - -**To turn on the screen reader on your device, complete the following steps:** - -{% tabs %} -{% tab "TalkBack on Android" %} - -1. On your device, open **Settings**. -2. Select **Accessibility** and then **TalkBack**. -3. Turn 'Use TalkBack' on or off. -4. Select Ok. - -To learn how to find and customize Android's -accessibility features, view the following video. - -{% ytEmbed 'FQyj_XTl01w', 'Customize Pixel and Android accessibility features' %} - -{% endtab %} -{% tab "VoiceOver on iPhone" %} - -1. On your device, open **Settings > Accessibility > VoiceOver** -2. Turn the VoiceOver setting on or off - -To learn how to find and customize iOS -accessibility features, view the following video. - -{% ytEmbed 'ROIe49kXOc8', 'How to navigate your iPhone or iPad with VoiceOver' %} - -{% endtab %} -{% tab "Browsers" %} - -For web, the following screen readers are currently supported: - -Mobile browsers: - -* iOS - VoiceOver -* Android - TalkBack - -Desktop browsers: - -* macOS - VoiceOver -* Windows - JAWs & NVDA - -Screen readers users on web must toggle the -"Enable accessibility" button to build the semantics tree. -Users can skip this step if you programmatically auto-enable -accessibility for your app using this API: - -```dart -import 'package:flutter/material.dart'; -import 'package:flutter/semantics.dart'; - -void main() { - runApp(const MyApp()); - SemanticsBinding.instance.ensureSemantics(); -} -``` - -{% endtab %} -{% tab "Desktop" %} - -Windows comes with a screen reader called Narrator -but some developers recommend using the more popular -NVDA screen reader. To learn about using NVDA to test -Windows apps, check out -[Screen Readers 101 For Front-End Developers (Windows)][nvda]. - -[nvda]: https://get-evinced.com/blog/screen-readers-101-for-front-end-developers-windows - -On a Mac, you can use the desktop version of VoiceOver, -which is included in macOS. - -{% ytEmbed '5R-6WvAihms', 'Screen reader basics: VoiceOver' %} - -On Linux, a popular screen reader is called Orca. -It comes pre-installed with some distributions -and is available on package repositories such as `apt`. -To learn about using Orca, check out -[Getting started with Orca screen reader on Gnome desktop][orca]. - -[orca]: https://www.a11yproject.com/posts/getting-started-with-orca - -{% endtab %} -{% endtabs %} - -
- -Check out the following [video demo][] to see Victor Tsaran, -using VoiceOver with the now-archived [Flutter Gallery][] web app. - -Flutter's standard widgets generate an accessibility tree automatically. -However, if your app needs something different, -it can be customized using the [`Semantics` widget][]. - -When there is text in your app that should be voiced -with a specific voice, inform the screen reader -which voice to use by calling [`TextSpan.locale`][]. -Note that `MaterialApp.locale` and `Localizations.override` -don't affect which voice the screen reader uses. -Usually, the screen reader uses the system voice -except where you explicitly set it with `TextSpan.locale`. - -[Flutter Gallery]: {{site.gallery-archive}} -[`TextSpan.locale`]: {{site.api}}/flutter/painting/TextSpan/locale.html - -## Sufficient contrast - -Sufficient color contrast makes text and images easier to read. -Along with benefitting users with various visual impairments, -sufficient color contrast helps all users when viewing an interface -on devices in extreme lighting conditions, -such as when exposed to direct sunlight or on a display with low -brightness. - -The [W3C recommends][]: - -* At least 4.5:1 for small text (below 18 point regular or 14 point bold) -* At least 3.0:1 for large text (18 point and above regular or 14 point and - above bold) - -## Building with accessibility in mind - -Ensuring your app can be used by everyone means building accessibility -into it from the start. For some apps, that's easier said than done. -In the video below, two of our engineers take a mobile app from a dire -accessibility state to one that takes advantage of Flutter's built-in -widgets to offer a dramatically more accessible experience. - -{% ytEmbed 'bWbBgbmAdQs', 'Building Flutter apps with accessibility in mind' %} - -## Enhancing Accessibility with Semantic Roles - -### What are Semantic Roles? - -Semantic roles define the purpose of a UI element, helping screen readers -and other assistive tools interpret and present your application effectively -to users. For example, a role can indicate if a widget is a button, a link, -a heading, a slider, or part of a table. - -While Flutter's standard widgets often provide these semantics automatically, -a custom component without a clearly defined role can be incomprehensible -to a screen reader user. - - -By assigning appropriate roles, you ensure that: - -* Screen readers can announce the type and purpose of elements correctly. -* Users can navigate your application more effectively using assistive technologies. -* Your application adheres to web accessibility standards, improving usability. - -### Using `SemanticsRole` in Flutter for web - -Flutter provides the [`Semantics` widget][] with the [`SemanticsRole` enum][] -to allow developers to assign specific roles to their widgets. When your -Flutter web app is rendered, these Flutter-specific roles are translated into -corresponding ARIA roles in the web page's HTML structure. - -[`SemanticsRole` enum]: {{site.api}}/flutter/dart-ui/SemanticsRole.html - -**1. Automatic Semantics from Standard Widgets:** - -Many standard Flutter widgets, like `TabBar`, `MenuAnchor`, and `Table`, -automatically include semantic information along with their roles. -Whenever possible, prefer using these standard widgets -as they handle many accessibility aspects out-of-the-box. - -**2. Explicitly adding or overriding roles:** - -For custom components or when the default semantics aren't sufficient, -use the `Semantics` widget to define the role: - -Here's an example of how you might explicitly define a list and its items: - -```dart -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) { - // This example shows how to explicitly assign list and listitem roles - // when building a custom list structure. - return Semantics( - role: SemanticsRole.list, - explicitChildNodes: true, - child: Column( - children: [ - 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.'), - ), - ), - ], - ), - ); - } -} - -``` - -## Testing accessibility on mobile - -Test your app using Flutter's [Accessibility Guideline API][]. -This API checks if your app's UI meets Flutter's accessibility recommendations. -These cover recommendations for text contrast, target size, and target labels. - -The following snippet shows how to use the Guideline API on -a sample widget named `AccessibleApp`: - - -```dart title="test/a11y_test.dart" -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()); - - // Checks that tappable nodes have a minimum size of 48 by 48 pixels - // for Android. - await expectLater(tester, meetsGuideline(androidTapTargetGuideline)); - - // Checks that tappable nodes have a minimum size of 44 by 44 pixels - // for iOS. - await expectLater(tester, meetsGuideline(iOSTapTargetGuideline)); - - // Checks that touch targets with a tap or long press action are labeled. - await expectLater(tester, meetsGuideline(labeledTapTargetGuideline)); - - // Checks whether semantic nodes meet the minimum text contrast levels. - // The recommended text contrast is 3:1 for larger text - // (18 point and above regular). - await expectLater(tester, meetsGuideline(textContrastGuideline)); - handle.dispose(); - }); -} -``` - -To try these tests out, run them on the app you create in the -[Write your first Flutter app](/get-started/codelab) codelab. -Each button on that app's main screen serves as a tappable target -with text rendered in an 18 point font. - -You can add Guideline API tests alongside other [widget tests][], -or in a separate file, such as `test/a11y_test.dart` in this example. - -[Accessibility Guideline API]: {{site.api}}/flutter/flutter_test/AccessibilityGuideline-class.html -[widget tests]: /testing/overview#widget-tests - -## Testing accessibility on web - -You can debug accessibility by visualizing the semantic nodes created for your web app -using the following command line flag in profile and release modes: - -```console -flutter run -d chrome --profile --dart-define=FLUTTER_WEB_DEBUG_SHOW_SEMANTICS=true -``` - -With the flag activated, the semantic nodes appear on top of the widgets; -you can verify that the semantic elements are placed where they should be. -If the semantic nodes are incorrectly placed, please [file a bug report][]. - -## Accessibility release checklist - -Here is a non-exhaustive list of things to consider as you prepare your -app for release. - -* **Active interactions**. Ensure that all active interactions do -something. Any button that can -be pushed should do something when pushed. For example, if you have a -no-op callback for an `onPressed` event, change it to show a `SnackBar` -on the screen explaining which control you just pushed. -* **Screen reader testing**. The screen reader should be able to -describe all controls on the page when you tap on them, and the -descriptions should be intelligible. Test your app with [TalkBack][] -(Android) and [VoiceOver][] (iOS). -* **Contrast ratios**. We encourage you to have a contrast ratio of at -least 4.5:1 between controls or text and the background, with the -exception of disabled components. Images should also be vetted for -sufficient contrast. -* **Context switching**. Nothing should change the user's context -automatically while typing in information. Generally, the widgets -should avoid changing the user's context without some sort of -confirmation action. -* **Tappable targets**. All tappable targets should be at least 48x48 -pixels. -* **Errors**. Important actions should be able to be undone. In fields -that show errors, suggest a correction if possible. -* **Color vision deficiency testing**. Controls should be usable and -legible in colorblind and grayscale modes. -* **Scale factors**. The UI should remain legible and usable at very -large scale factors for text size and display scaling. - -## Learn more - -To learn more about Flutter and accessibility, check out -the following articles written by community members: - -* [A deep dive into Flutter's accessibility widgets][] -* [Semantics in Flutter][] -* [Flutter: Crafting a great experience for screen readers][] - -[CRPD]: https://www.un.org/development/desa/disabilities/convention-on-the-rights-of-persons-with-disabilities/article-9-accessibility.html -[A deep dive into Flutter's accessibility widgets]: {{site.medium}}/flutter-community/a-deep-dive-into-flutters-accessibility-widgets-eb0ef9455bc -[Flutter: Crafting a great experience for screen readers]: https://blog.gskinner.com/archives/2022/09/flutter-crafting-a-great-experience-for-screen-readers.html -[Accessibility Scanner]: https://play.google.com/store/apps/details?id=com.google.android.apps.accessibility.auditor&hl=en -[**Large fonts**]: #large-fonts -[**Screen readers**]: #screen-readers -[Semantics in Flutter]: https://www.didierboelens.com/2018/07/semantics/ -[`Semantics` widget]: {{site.api}}/flutter/widgets/Semantics-class.html -[**Sufficient contrast**]: #sufficient-contrast -[TalkBack]: https://support.google.com/accessibility/android/answer/6283677?hl=en -[W3C recommends]: https://www.w3.org/TR/UNDERSTANDING-WCAG20/visual-audio-contrast-contrast.html -[VoiceOver]: https://www.apple.com/lae/accessibility/iphone/vision/ -[video demo]: {{site.yt.watch}}?v=A6Sx0lBP8PI -[file a bug report]: https://goo.gle/flutter_web_issue diff --git a/src/content/ui/accessibility-and-internationalization/index.md b/src/content/ui/accessibility-and-internationalization/index.md deleted file mode 100644 index ecdd5a14a6d..00000000000 --- a/src/content/ui/accessibility-and-internationalization/index.md +++ /dev/null @@ -1,7 +0,0 @@ ---- -layout: toc -title: Accessibility & internationalization -shortTitle: a11y & i18n -description: > - Content covering accessibility and internationalization in Flutter apps. ---- diff --git a/src/content/ui/accessibility/accessibility-testing.md b/src/content/ui/accessibility/accessibility-testing.md new file mode 100644 index 00000000000..2caed137310 --- /dev/null +++ b/src/content/ui/accessibility/accessibility-testing.md @@ -0,0 +1,104 @@ +--- +title: Accessibility Testing +description: Information on Flutter's accessibility testing. +--- + +## Inspecting accessibility support + +we recommend using automated accessibility scanners to test: + +* For Android: + 1. Install the [Accessibility Scanner][] for Android + 1. Enable the Accessibility Scanner from + **Android Settings > Accessibility > + Accessibility Scanner > On** + 1. Navigate to the Accessibility Scanner 'checkbox' + icon button to initiate a scan + +* For iOS: + 1. Open the `iOS` folder of your Flutter app in Xcode + 1. Select a Simulator as the target, and click **Run** button + 1. In Xcode, select + **Xcode > Open Developer Tools > Accessibility Inspector** + 1. In the Accessibility Inspector, + select **Inspection > Enable Point to Inspect**, + and then select the various user interface elements in running + Flutter app to inspect their accessibility attributes + 1. In the Accessibility Inspector, + select **Audit** in the toolbar, and then + select **Run Audit** to get a report of potential issues + +* For web: + 1. Open Chrome DevTools (or similar tools in other browsers) + 2. Inspect the HTML tree containing the ARIA attributes generated by + Flutter. + 3. In Chrome, the "Elements" tab has a "Accessibility" sub-tab + that can be used to inspect the data exported to semantics tree + + +## Testing accessibility on mobile + +Test your app using Flutter's [Accessibility Guideline API][]. +This API checks if your app's UI meets Flutter's accessibility recommendations. +These cover recommendations for text contrast, target size, and target labels. + +The following snippet shows how to use the Guideline API on +a sample widget named `AccessibleApp`: + + +```dart title="test/a11y_test.dart" +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()); + + // Checks that tappable nodes have a minimum size of 48 by 48 pixels + // for Android. + await expectLater(tester, meetsGuideline(androidTapTargetGuideline)); + + // Checks that tappable nodes have a minimum size of 44 by 44 pixels + // for iOS. + await expectLater(tester, meetsGuideline(iOSTapTargetGuideline)); + + // Checks that touch targets with a tap or long press action are labeled. + await expectLater(tester, meetsGuideline(labeledTapTargetGuideline)); + + // Checks whether semantic nodes meet the minimum text contrast levels. + // The recommended text contrast is 3:1 for larger text + // (18 point and above regular). + await expectLater(tester, meetsGuideline(textContrastGuideline)); + handle.dispose(); + }); +} +``` + +To try these tests out, run them on the app you create in the +[Write your first Flutter app](/get-started/codelab) codelab. +Each button on that app's main screen serves as a tappable target +with text rendered in an 18 point font. + +You can add Guideline API tests alongside other [widget tests][], +or in a separate file, such as `test/a11y_test.dart` in this example. + +[Accessibility Guideline API]: {{site.api}}/flutter/flutter_test/AccessibilityGuideline-class.html +[widget tests]: /testing/overview#widget-tests + +## Testing accessibility on web + +You can debug accessibility by visualizing the semantic nodes created for your web app +using the following command line flag in profile and release modes: + +```console +flutter run -d chrome --profile --dart-define=FLUTTER_WEB_DEBUG_SHOW_SEMANTICS=true +``` + +With the flag activated, the semantic nodes appear on top of the widgets; +you can verify that the semantic elements are placed where they should be. +If the semantic nodes are incorrectly placed, please [file a bug report][]. + + +[Accessibility Scanner]: https://play.google.com/store/apps/details?id=com.google.android.apps.accessibility.auditor&hl=en +[file a bug report]: https://goo.gle/flutter_web_issue \ No newline at end of file diff --git a/src/content/ui/accessibility/assistive-technologies.md b/src/content/ui/accessibility/assistive-technologies.md new file mode 100644 index 00000000000..7a94c0c205c --- /dev/null +++ b/src/content/ui/accessibility/assistive-technologies.md @@ -0,0 +1,184 @@ +--- +title: Accessibility Technologies +description: Information about accessibility +--- +## Summary + +Assistive technologies are essential for making digital content accessible to +individuals with disabilities. This document provides an overview of two key +categories of assistive technologies relevant to Flutter development: screen +readers for users with visual impairments and mobility support tools for +those with motor limitations. By understanding and testing with these +technologies, you can ensure your Flutter application provides a more inclusive +and user-friendly experience for everyone. + +## Screen readers + +For mobile, screen readers ([TalkBack][], [VoiceOver][]) +enable visually impaired users to get spoken feedback about +the contents of the screen and interact with the UI by using +gestures on mobile and keyboard shortcuts on desktop. +Turn on VoiceOver or TalkBack on your mobile device and +navigate around your app. + +**To turn on the screen reader on your device, complete the following steps:** + +{% tabs %} +{% tab "TalkBack on Android" %} + +1. On your device, open **Settings**. +2. Select **Accessibility** and then **TalkBack**. +3. Turn 'Use TalkBack' on or off. +4. Select Ok. + +To learn how to find and customize Android's +accessibility features, view the following video. + +{% ytEmbed 'FQyj_XTl01w', 'Customize Pixel and Android accessibility features' %} + +{% endtab %} +{% tab "VoiceOver on iPhone" %} + +1. On your device, open **Settings > Accessibility > VoiceOver** +2. Turn the VoiceOver setting on or off + +To learn how to find and customize iOS +accessibility features, view the following video. + +{% ytEmbed 'ROIe49kXOc8', 'How to navigate your iPhone or iPad with VoiceOver' %} + +{% endtab %} +{% tab "Browsers" %} + +For web, the following screen readers are currently supported: + +Mobile browsers: + +* iOS - VoiceOver +* Android - TalkBack + +Desktop browsers: + +* macOS - VoiceOver +* Windows - JAWs & NVDA + +Screen readers users on web must toggle the +"Enable accessibility" button to build the semantics tree. +Users can skip this step if you programmatically auto-enable +accessibility for your app using this API: + +```dart +import 'package:flutter/material.dart'; +import 'package:flutter/semantics.dart'; + +void main() { + runApp(const MyApp()); + SemanticsBinding.instance.ensureSemantics(); +} +``` + +{% endtab %} +{% tab "Desktop" %} + +Windows comes with a screen reader called Narrator +but some developers recommend using the more popular +NVDA screen reader. To learn about using NVDA to test +Windows apps, check out +[Screen Readers 101 For Front-End Developers (Windows)][nvda]. + +[nvda]: https://get-evinced.com/blog/screen-readers-101-for-front-end-developers-windows + +On a Mac, you can use the desktop version of VoiceOver, +which is included in macOS. + +{% ytEmbed '5R-6WvAihms', 'Screen reader basics: VoiceOver' %} + +On Linux, a popular screen reader is called Orca. +It comes pre-installed with some distributions +and is available on package repositories such as `apt`. +To learn about using Orca, check out +[Getting started with Orca screen reader on Gnome desktop][orca]. + +[orca]: https://www.a11yproject.com/posts/getting-started-with-orca + +{% endtab %} +{% endtabs %} + +
+ +Check out the following [video demo][] to see Victor Tsaran, +using VoiceOver with the now-archived [Flutter Gallery][] web app. + +Flutter's standard widgets generate an accessibility tree automatically. +However, if your app needs something different, +it can be customized using the [`Semantics` widget][]. + +When there is text in your app that should be voiced +with a specific voice, inform the screen reader +which voice to use by calling [`TextSpan.locale`][]. +Note that `MaterialApp.locale` and `Localizations.override` +don't affect which voice the screen reader uses. +Usually, the screen reader uses the system voice +except where you explicitly set it with `TextSpan.locale`. + +[Flutter Gallery]: {{site.gallery-archive}} +[`TextSpan.locale`]: {{site.api}}/flutter/painting/TextSpan/locale.html +[`Semantics` widget]: {{site.api}}/flutter/widgets/Semantics-class.html +[TalkBack]: https://support.google.com/accessibility/android/answer/6283677?hl=en +[VoiceOver]: https://www.apple.com/lae/accessibility/iphone/vision/ +[video demo]: {{site.yt.watch}}?v=A6Sx0lBP8PI + +## Mobility support + +For users with limited dexterity or hand strength, mobility support features +can be helpful. Both Android and iOS offer a range of tools designed to make +navigation and control easier. +These features allow users to operate their devices through external switches, +voice commands, or simplified on-screen menus. + +Android provides Switch Access, Voice Access and Accessibility Menu, +while iOS offers Switch Control, Voice Control, and AssistiveTouch. +Understanding these tools helps in creating +apps that are usable by people with diverse physical abilities. + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
OSFeatures Functions
AndroidSwitch Access As an alternate input method, you can use Switch Access and Camera Switches
AndroidVoice Access Control your device with your voice
AndroidAccessibility Menu A floating, on-screen menu that provides simplified buttons to control essential phone functions.
iOSSwitch Control Use switches as an alternate input methods
iOSVoice Control Control your device with your voice
iOSAssistiveTouch Use AssistiveTouch to replace multi-finger gestures or hardware button actions
diff --git a/src/content/ui/accessibility/index.md b/src/content/ui/accessibility/index.md new file mode 100644 index 00000000000..c4df4ae8695 --- /dev/null +++ b/src/content/ui/accessibility/index.md @@ -0,0 +1,123 @@ +--- +title: Accessibility +description: Information on Flutter's accessibility support. +--- + +## Background +Ensuring apps are accessible to a broad range of users is an essential +part of building a high-quality app. Applications that are poorly +designed create barriers to people of all ages. The [UN Convention on +the Rights of Persons with Disabilities][CRPD] states the moral and legal +imperative to ensure universal access to information systems; countries +around the world enforce accessibility as a requirement; and companies +recognize the business advantages of maximizing access to their services. + +We strongly encourage you to include an accessibility checklist +as a key criteria before shipping your app. Flutter is committed to +supporting developers in making their apps more accessible, and includes +first-class framework support for accessibility in addition to that +provided by the underlying operating system, including: + +[UI Design and styling][] + +[Assistive Technologies (Screen Reader) supports][] + +[UI Design and styling]: /ui/accessibility/ui-design-and-styling +[Assistive Technologies (Screen Reader) supports]:/ui/accessibility/assistive-technologies + +## Accessibility regulations + +Accessibility standards and regulations help ensure that products are +accessible to people with disabilities. Many of these have been enacted into +laws and policies, making them requirements for products and services. + +* **WCAG 2**: [Web Content Accessibility Guidelines (WCAG) 2][] is an +internationally recognized standard for making web content more accessible +to people with disabilities. It is a stable, technical standard developed +by the World Wide Web Consortium (W3C). + +* **EN 301 549**: [EN 301 549][] is the European harmonized standard for +accessibility requirements for Information and Communication Technology (ICT) +products and services. + +* **VPAT**: The [Voluntary Product Accessibility Template (VPAT)][] is a +free template that translates accessibility requirements and standards into + actionable testing criteria for products and services. + +Laws around the world require digital content and services to be accessible +to people with disabilities. +In the U.S., the [Americans with Disabilities Act (ADA)][] prohibits +discrimination in public accommodations. +[Section 508 of the Rehabilitation Act ][] requires federal agencies and their +contractors to meet WCAG standards for all ICT. + +In the EU, the [European Accessibility Act (EAA)][] requires a wide range of +public and private sector services to be accessible, primarily using +the [EN 301 549][] as its technical basis. + + + +[Web Content Accessibility Guidelines (WCAG) 2]: https://www.w3.org/WAI/standards-guidelines/wcag/ +[EN 301 549]: https://www.etsi.org/deliver/etsi_en/301500_301599/301549/03.02.01_60/en_301549v030201p.pdf +[Voluntary Product Accessibility Template (VPAT)]: https://www.itic.org/policy/accessibility/vpat + +[Americans with Disabilities Act (ADA)]: https://www.ada.gov/ +[Section 508 of the Rehabilitation Act]: https://www.section508.gov/ +[European Accessibility Act (EAA)]: https://commission.europa.eu/strategy-and-policy/policies/justice-and-fundamental-rights/disability/union-equality-strategy-rights-persons-disabilities-2021-2030/european-accessibility-act_en + + +## Building with accessibility in mind + +Ensuring your app can be used by everyone means building accessibility +into it from the start. For some apps, that's easier said than done. +In the video below, two of our engineers take a mobile app from a dire +accessibility state to one that takes advantage of Flutter's built-in +widgets to offer a dramatically more accessible experience. + +{% ytEmbed 'bWbBgbmAdQs', 'Building Flutter apps with accessibility in mind' %} + + +## Accessibility release checklist + +Here is a non-exhaustive list of things to consider as you prepare your +app for release. + +* **Active interactions**. Ensure that all active interactions do +something. Any button that can +be pushed should do something when pushed. For example, if you have a +no-op callback for an `onPressed` event, change it to show a `SnackBar` +on the screen explaining which control you just pushed. +* **Screen reader testing**. The screen reader should be able to +describe all controls on the page when you tap on them, and the +descriptions should be intelligible. Test your app with [TalkBack][] +(Android) and [VoiceOver][] (iOS). +* **Contrast ratios**. We encourage you to have a contrast ratio of at +least 4.5:1 between controls or text and the background, with the +exception of disabled components. Images should also be vetted for +sufficient contrast. +* **Context switching**. Nothing should change the user's context +automatically while typing in information. Generally, the widgets +should avoid changing the user's context without some sort of +confirmation action. +* **Tappable targets**. All tappable targets should be at least 48x48 +pixels. +* **Errors**. Important actions should be able to be undone. In fields +that show errors, suggest a correction if possible. +* **Color vision deficiency testing**. Controls should be usable and +legible in colorblind and grayscale modes. +* **Scale factors**. The UI should remain legible and usable at very +large scale factors for text size and display scaling. + +## Learn more + +To learn more about Flutter and accessibility, check out +the following articles written by community members: + +* [A deep dive into Flutter's accessibility widgets][] +* [Semantics in Flutter][] +* [Flutter: Crafting a great experience for screen readers][] + +[CRPD]: https://www.un.org/development/desa/disabilities/convention-on-the-rights-of-persons-with-disabilities/article-9-accessibility.html +[A deep dive into Flutter's accessibility widgets]: {{site.medium}}/flutter-community/a-deep-dive-into-flutters-accessibility-widgets-eb0ef9455bc +[Flutter: Crafting a great experience for screen readers]: https://blog.gskinner.com/archives/2022/09/flutter-crafting-a-great-experience-for-screen-readers.html +[Semantics in Flutter]: https://www.didierboelens.com/2018/07/semantics/ diff --git a/src/content/ui/accessibility/ui-design-and-styling.md b/src/content/ui/accessibility/ui-design-and-styling.md new file mode 100644 index 00000000000..38ae84e1f5e --- /dev/null +++ b/src/content/ui/accessibility/ui-design-and-styling.md @@ -0,0 +1,75 @@ +--- +title: UI Design & Styling +description: Information on Flutter's accessibility support. +--- + +To create an accessible app, design your UI with accessibility in mind. +This page covers key aspects of accessible UI design and styling. + +## Large fonts + +Both Android and iOS contain system settings to configure the desired font +sizes used by apps. Flutter text widgets respect this OS setting when +determining font sizes. + +Font sizes are calculated automatically by Flutter based on the OS setting. +However, as a developer you should make sure your layout has enough room to +render all its contents when the font sizes are increased. +For example, you can test all parts of your app on a small-screen +device configured to use the largest font setting. + +### Example + +The following two screenshots show the standard Flutter app +template rendered with the default iOS font setting, +and with the largest font setting selected in iOS accessibility settings. + +
+ {% render docs/app-figure.md, image:"a11y/app-regular-fonts.png", caption:"Default font setting", img-class:"simple-border", img-style:"max-height: 480px;" %} + {% render docs/app-figure.md, image:"a11y/app-large-fonts.png", caption:"Largest accessibility font setting", img-class:"simple-border", img-style:"max-height: 480px;" %} +
+ + +## Sufficient contrast + +Sufficient color contrast makes text and images easier to read. +Along with benefitting users with various visual impairments, +sufficient color contrast helps all users when viewing an interface +on devices in extreme lighting conditions, +such as when exposed to direct sunlight or on a display with low +brightness. + +The [W3C recommends][]: + +* At least 4.5:1 for small text (below 18 point regular or 14 point bold) +* At least 3.0:1 for large text (18 point and above regular or 14 point and + above bold) + +[W3C recommends]: https://www.w3.org/TR/UNDERSTANDING-WCAG20/visual-audio-contrast-contrast.html + +### Example +The following screenshot shows good and bad examples for text color contrast. + + {% render docs/app-figure.md, image:"a11y/text-contrast.png", caption:"text contrast", img-class:"simple-border", img-style:"max-height: 480px;" %} + + +## Tap target size + +Controls that are too small are hard for many people to interact with and select. +Ensure that interactive elements have a large enough tap target to be easily +pressed by users. + +Both [Android][] and [iOS][] recommend a minimum tap target size of 48x48 dp and 44x44 pts respectively. + +The [W3C] recommends a minimum target size of 44 by 44 CSS pixels, + +[Android]: https://developer.android.com/guide/topics/ui/accessibility/apps#large-controls +[iOS]: https://developer.apple.com/design/human-interface-guidelines/accessibility#Mobility +[W3C]: https://www.w3.org/WAI/WCAG21/Understanding/target-size.html + + +### Example + +The following screenshot shows how to make these widgets to have at least an 48x48 tap target. + + {% render docs/app-figure.md, image:"a11y/tap-target-size.png", caption:"tap target size", img-class:"simple-border", img-style:"max-height: 480px;" %} diff --git a/src/content/ui/accessibility/web-accessibility.md b/src/content/ui/accessibility/web-accessibility.md new file mode 100644 index 00000000000..378a4f316fd --- /dev/null +++ b/src/content/ui/accessibility/web-accessibility.md @@ -0,0 +1,123 @@ +--- +title: Web Accessibility +description: Information about web accessibility +--- + +## Background +Flutter supports web accessibility by translating its internal +Semantics tree into an accessible HTML DOM structure that +screen readers can understand. +Since Flutter renders its UI on a single canvas, it needs a special layer +to expose the UI's meaning and structure to web browsers. + + +## Opt-in Web Accessibility + +### Invisible button + +For performance reasons, Flutter's web accessibility is not on by default. +To turn on accessibility, the user needs to press an invisible button with +`aria-label="Enable accessibility"`. +After pressing the button, the DOM tree will reflect all accessibility +information for the widgets. + +### Turn on accessibility mode in code + +An alternative approach is to turn on accessibility mode +by adding the following code when running an app. +```dart +import 'package:flutter/semantics.dart'; + +void main() { + runApp(const MyApp()); + if (kIsWeb) { + SemanticsBinding.instance.ensureSemantics(); + } +} +``` + + + +## Enhancing Accessibility with Semantic Roles + +### What are Semantic Roles? + +Semantic roles define the purpose of a UI element, helping screen readers +and other assistive tools interpret and present your application effectively +to users. For example, a role can indicate if a widget is a button, a link, +to users. For example, a role can indicate whether a widget is a button, a link, +a heading, a slider, or part of a table. + +While Flutter's standard widgets often provide these semantics automatically, +a custom component without a clearly defined role can be incomprehensible +to a screen reader user. + + +By assigning appropriate roles, you ensure that: + +* Screen readers can announce the type and purpose of elements correctly. +* Users can navigate your application more effectively using assistive technologies. +* Your application adheres to web accessibility standards, improving usability. + +### Using `SemanticsRole` in Flutter for web + +Flutter provides the [`Semantics` widget][] with the [`SemanticsRole` enum][] +to allow developers to assign specific roles to their widgets. When your +Flutter web app is rendered, these Flutter-specific roles are translated into +corresponding ARIA roles in the web page's HTML structure. + +[`SemanticsRole` enum]: {{site.api}}/flutter/dart-ui/SemanticsRole.html + +**1. Automatic Semantics from Standard Widgets:** + +Many standard Flutter widgets, like `TabBar`, `MenuAnchor`, and `Table`, +automatically include semantic information along with their roles. +Whenever possible, prefer using these standard widgets +as they handle many accessibility aspects out-of-the-box. + +**2. Explicitly adding or overriding roles:** + +For custom components or when the default semantics aren't sufficient, +use the `Semantics` widget to define the role: + +Here's an example of how you might explicitly define a list and its items: + +```dart +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) { + // This example shows how to explicitly assign list and listitem roles + // when building a custom list structure. + return Semantics( + role: SemanticsRole.list, + explicitChildNodes: true, + child: Column( + children: [ + 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.'), + ), + ), + ], + ), + ); + } +} + +``` + diff --git a/src/content/ui/accessibility-and-internationalization/internationalization.md b/src/content/ui/internationalization/internationalization.md similarity index 100% rename from src/content/ui/accessibility-and-internationalization/internationalization.md rename to src/content/ui/internationalization/internationalization.md