mirror of
https://github.com/flutter/flutter.git
synced 2026-02-20 02:29:02 +08:00
## Description Please check comment: https://github.com/flutter/flutter/pull/171040#issuecomment-3014250567. This PR adds `SemanticsLabelBuilder`, a new utility class for creating accessible concatenated labels with proper text direction handling and spacing. Currently, developers manually concatenate semantic labels using string interpolation, which is error-prone and leads to accessibility issues like missing spaces, incorrect text direction for RTL languages. The new builder provides automatic spacing, Unicode bidirectional text embedding for mixed LTR/RTL content. ### Before (error-prone manual concatenation): ```dart // Missing space String label = "$firstName$lastName"; // "JohnDoe" String englishText = "Welcome"; String arabicText = "مرحبا"; // Arabic "Hello" // Manual Concatenation (WITHOUT Unicode embedding): aria-label="Welcome 欢迎 مرحبا स्वागत है to our global app" // Problem: Arabic does not have proper text direction handling ``` ### After (automatic and accessible): Demo app after the change: https://label-0702.web.app/ ```dart // Automatic spacing and text direction handling final label = (SemanticsLabelBuilder() ..addPart(firstName) ..addPart(lastName)).build(); // Result: "John Doe" with proper aria-label generation // SemanticsLabelBuilder (WITH Unicode embedding): aria-label="Welcome 欢迎 [U+202B]مرحبا[U+202C] स्वागत है to our global app" // Result: Arabic has proper text direction handling ``` ## Issues Fixed This fixes https://github.com/flutter/flutter/issues/162094. This PR addresses the general accessibility problem of error-prone manual label concatenation that affects screen reader users. While not fixing a specific filed issue, it provides a robust solution for the common pattern of building complex semantic labels that are critical for accessibility compliance, particularly for multilingual applications and complex UI components like contact cards, dashboards, and e-commerce listings. ## Breaking Changes No breaking changes were made. This is a purely additive API that doesn't modify existing behavior or require any migration. ## Key Features Added - **SemanticsLabelBuilder**: Main builder class for concatenating text parts - **Automatic spacing**: Configurable separators with intelligent empty part handling - **Text direction support**: Unicode bidirectional embedding for RTL/LTR mixed content ## Example Usage ```dart // Basic usage final label = (SemanticsLabelBuilder() ..addPart('Contact') ..addPart('John Doe') ..addPart('Phone: +1-555-0123')).build(); // Result: "Contact John Doe Phone: +1-555-0123" // Custom separator final label = (SemanticsLabelBuilder(separator: ', ') ..addPart('Name: Alice') ..addPart('Status: Online')).build(); // Result: "Name: Alice, Status: Online" // Multilingual support final label = (SemanticsLabelBuilder(textDirection: TextDirection.ltr) ..addPart('Welcome', textDirection: TextDirection.ltr) ..addPart('مرحبا', textDirection: TextDirection.rtl) ..addPart('to our app')).build(); // Result: "Welcome مرحبا to our app" (with proper RTL embedding) ``` ``` ## Pre-launch Checklist - [x] I read the [Contributor Guide] and followed the process outlined there for submitting PRs. - [x] I read the [Tree Hygiene] wiki page, which explains my responsibilities. - [x] I read and followed the [Flutter Style Guide], including [Features we expect every widget to implement]. - [x] I signed the [CLA]. - [x] I listed at least one issue that this PR fixes in the description above. - [x] I updated/added relevant documentation (doc comments with `///`). - [x] I added new tests to check the change I am making, or this PR is [test-exempt]. - [x] I followed the [breaking change policy] and added [Data Driven Fixes] where supported. - [x] All existing and new tests are passing. --------- Co-authored-by: Mouad Debbar <mouad.debbar@gmail.com>