Feature/aria labelledby support#171040
Conversation
| // If labelParts are provided, use them instead of the regular label | ||
| if (labelParts != null && labelParts.isNotEmpty) { | ||
| final String labelPartsValue = labelParts | ||
| .where((String part) => part.trim().isNotEmpty) | ||
| .join(' '); | ||
| if (labelPartsValue.isNotEmpty) { | ||
| // Combine labelParts with value if both exist | ||
| final String combinedValue = <String?>[ | ||
| labelPartsValue, | ||
| value, | ||
| ].whereType<String>().where((String element) => element.trim().isNotEmpty).join(' '); | ||
| return combinedValue.isNotEmpty ? combinedValue : null; | ||
| } | ||
| } | ||
|
|
||
| // Fallback to regular label + value logic | ||
| final String combinedValue = <String?>[ | ||
| label, | ||
| value, | ||
| ].whereType<String>().where((String element) => element.trim().isNotEmpty).join(' '); |
There was a problem hiding this comment.
To simplify this a little bit:
| // If labelParts are provided, use them instead of the regular label | |
| if (labelParts != null && labelParts.isNotEmpty) { | |
| final String labelPartsValue = labelParts | |
| .where((String part) => part.trim().isNotEmpty) | |
| .join(' '); | |
| if (labelPartsValue.isNotEmpty) { | |
| // Combine labelParts with value if both exist | |
| final String combinedValue = <String?>[ | |
| labelPartsValue, | |
| value, | |
| ].whereType<String>().where((String element) => element.trim().isNotEmpty).join(' '); | |
| return combinedValue.isNotEmpty ? combinedValue : null; | |
| } | |
| } | |
| // Fallback to regular label + value logic | |
| final String combinedValue = <String?>[ | |
| label, | |
| value, | |
| ].whereType<String>().where((String element) => element.trim().isNotEmpty).join(' '); | |
| List<String?>? allParts; | |
| // If labelParts are provided, use them instead of the regular label | |
| if (labelParts != null && labelParts.isNotEmpty) { | |
| final Iterable<String> validLabelParts = labelParts.where((String part) => part.trim().isNotEmpty); | |
| if (validLabelParts.isNotEmpty) { | |
| allParts = <String?>[...validLabelParts, value]; | |
| } | |
| } | |
| // Fallback to regular label + value | |
| allParts ??= <String?>[label, value]; | |
| final String combinedValue = allParts | |
| .whereType<String>() | |
| .where((String element) => element.trim().isNotEmpty) | |
| .join(' '); |
| final String labelId = '$idPrefix-${semanticsObject.id}-$i'; | ||
| labelIds.add(labelId); | ||
|
|
||
| DomElement? labelElement = containerElement.querySelector('#$labelId'); |
There was a problem hiding this comment.
Instead of relying on querySelector, I suggest keeping a list of these span elements, _labelPartElements or something like that.
| final String oldLabelId = '$idPrefix-${semanticsObject.id}-$i'; | ||
| containerElement.querySelector('#$oldLabelId')?.remove(); |
There was a problem hiding this comment.
This would become:
_labelPartElements[i].remove();and after the for loop:
_labelPartElements.length = labelParts.length;| for (int i = 0; i < _previousLabelParts!.length; i++) { | ||
| final String labelId = '$idPrefix-${semanticsObject.id}-$i'; | ||
| containerElement.querySelector('#$labelId')?.remove(); | ||
| } |
There was a problem hiding this comment.
this would become:
_labelPartElements.forEach((DomElement element) => element.remove());
_labelPartElements.clear();|
@chunhtai and I had the following conversation. @chunhtai : for this pr, what is the difference between between using aria-labelledby with spans of strings vs concatenate them and assign to aria-label? @flutter-zl : the major advantage i can think of is aria-labelledby programmatically concatenate strings. developers need to manually aria-label concatenate strings which may raise error. @chunhtai : if so, sounds like we can just provide a utility in dart side so they can use before setting the Semantics.label? Hi @yjbanov, what is your opinion since you already have the context of #162094? |
|
Yeah, I was thinking about some method of concatenation outside the Maybe what we need is a final class SemanticsLabelBuilder {
void addPart(String label);
void addAttributedPart(AttributedString label);
SemanticsLabel build();
}
final class SemanticsLabel {
/// The concatenation of labels made of parts supplied using `addPart` and `addAttributedPart` invocations.
String get label;
/// The attributed concatenation of labels made of parts supplied using `addPart` and `addAttributedPart` invocations.
///
/// Returns null if no attributed parts were supplied in `SemanticsLabelBuilder`.
AttributedString? get attributedLabel;
}Sample usage: // Plain label concatenation
var builder = SemanticsLabelBuilder()
..addPart('hello')
..addPart('world');
var label = builder build;
label.label; // returns 'hello world'
label.attributedLabel; // returns null
// Plain label concatenation
var builder = SemanticsLabelBuilder()
..addPart('hello')
..addAttributedPart(AttributedString('world', attributes = [LocaleStringAttribute(...)]));
var label = builder build;
label.label; // returns 'hello world' (loses attributes, but otherwise correct)
label.attributedLabel; // returns AttributedString with concatenated label and
// string attributes with adjusted text ranges, because text ranges
// can shift due to concatenation |
|
I also prefer having concatenation outside of semantics system, adding a property is costly to all embeddings. |
|
I created a new PR(#171683) based on the feedback in #171040 (comment) and #171040 (comment). |
## Description Please check comment: #171040 (comment). 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 #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 <[email protected]>
…#171683) ## Description Please check comment: flutter#171040 (comment). 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 flutter#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 <[email protected]>
…#171683) ## Description Please check comment: flutter#171040 (comment). 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 flutter#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 <[email protected]>
…#171683) ## Description Please check comment: flutter#171040 (comment). 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 flutter#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 <[email protected]>
…#171683) ## Description Please check comment: flutter#171040 (comment). 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 flutter#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 <[email protected]>
…#171683) ## Description Please check comment: flutter#171040 (comment). 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 flutter#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 <[email protected]>
Description
This PR implements comprehensive
aria-labelledbysupport for Flutter Web, enabling complex accessible labels composed of multiple semantic parts. This significantly improves web accessibility by allowing developers to create structured, screen reader-friendly labels that follow WAI-ARIA best practices.Problem Solved
#162094
Before: Flutter Web only supported single
aria-labelattributes, making it difficult to create complex form labels with multiple semantic components (e.g., field name + format instructions + requirement indicators).After: Developers can now create rich, multi-part labels that screen readers can properly interpret and announce to users.
Demo app: https://labelledby-0618.web.app/
Test 1: Customer Name + Required Field (2 parts)
Test 2: Email + Format Instructions + Required (3 parts)
Test 3: Submit Button + Keyboard Shortcut (Group semantics)
Test 4: Complex Password Instructions (4 parts)
Test 5: Single Label Comparison (Falls back to aria-label)
Pre-launch Checklist
///).If you need help, consider asking for advice on the #hackers-new channel on Discord.