Skip to content

Commit

Permalink
fix: indicator semantic labels
Browse files Browse the repository at this point in the history
fix: navigation bar semantic labels
  • Loading branch information
DE7924 committed Nov 15, 2024
1 parent 8d10ee5 commit 56e4433
Show file tree
Hide file tree
Showing 5 changed files with 97 additions and 28 deletions.
37 changes: 22 additions & 15 deletions lib/src/components/badges/indicator.dart
Original file line number Diff line number Diff line change
Expand Up @@ -92,6 +92,7 @@ class ZetaIndicator extends ZetaStatelessWidget {
int? value,
bool? inverse,
Key? key,
String? semanticLabel,
}) {
return ZetaIndicator(
key: key ?? this.key,
Expand All @@ -100,6 +101,7 @@ class ZetaIndicator extends ZetaStatelessWidget {
icon: icon ?? this.icon,
value: value ?? this.value,
inverse: inverse ?? this.inverse,
semanticLabel: semanticLabel ?? this.semanticLabel,
);
}

Expand All @@ -111,18 +113,20 @@ class ZetaIndicator extends ZetaStatelessWidget {
final sizePixels = _getSizePixels(size, type, context);

return Semantics(
value: semanticLabel ?? value?.toString() ?? '',
label: semanticLabel,
child: Container(
width: sizePixels + Zeta.of(context).spacing.minimum,
height: sizePixels + Zeta.of(context).spacing.minimum,
decoration: BoxDecoration(
border: Border.all(
width: ZetaBorders.medium,
color: Zeta.of(context).colors.borderSubtle,
),
color: (inverse ? foregroundColor : Colors.transparent),
borderRadius: Zeta.of(context).radius.full,
),
decoration: type == ZetaIndicatorType.icon
? BoxDecoration(
border: Border.all(
width: ZetaBorders.medium,
color: Zeta.of(context).colors.borderSubtle,
),
color: (inverse ? foregroundColor : Colors.transparent),
borderRadius: Zeta.of(context).radius.full,
)
: null,
child: Center(
child: Container(
width: sizePixels,
Expand Down Expand Up @@ -155,12 +159,15 @@ class ZetaIndicator extends ZetaStatelessWidget {
);
case ZetaIndicatorType.notification:
return Center(
child: Text(
value.formatMaxChars(),
style: ZetaTextStyles.labelIndicator.copyWith(
color: foregroundColor,
fontSize: size == ZetaWidgetSize.large ? 12 : 11,
height: size == ZetaWidgetSize.large ? 1 : (12 / 16),
child: ExcludeSemantics(
excluding: semanticLabel != null,
child: Text(
value.formatMaxChars(),
style: ZetaTextStyles.labelIndicator.copyWith(
color: foregroundColor,
fontSize: size == ZetaWidgetSize.large ? 12 : 11,
height: size == ZetaWidgetSize.large ? 1 : (0.5 / 16),
),
),
),
);
Expand Down
12 changes: 7 additions & 5 deletions lib/src/components/navigation bar/navigation_bar.dart
Original file line number Diff line number Diff line change
Expand Up @@ -239,7 +239,7 @@ class NavigationItem extends ZetaStatelessWidget {
right: Zeta.of(context).spacing.minimum,
child: DecoratedBox(
decoration: BoxDecoration(
color: colors.surfacePrimary,
color: colors.surfaceDefault,
borderRadius: Zeta.of(context).radius.full,
),
child: item.badge?.copyWith(
Expand All @@ -249,6 +249,7 @@ class NavigationItem extends ZetaStatelessWidget {
? ZetaWidgetSize.medium
: null,
type: ZetaIndicatorType.notification,
semanticLabel: item.badge?.semanticLabel,
),
),
);
Expand All @@ -268,7 +269,6 @@ class NavigationItem extends ZetaStatelessWidget {
highlightShape: BoxShape.rectangle,
child: Semantics(
button: true,
excludeSemantics: true,
label: item.label,
child: Container(
padding: EdgeInsets.only(
Expand All @@ -293,9 +293,11 @@ class NavigationItem extends ZetaStatelessWidget {
),
SizedBox(height: Zeta.of(context).spacing.small),
if (item.label != null)
Text(
item.label!,
style: Theme.of(context).textTheme.labelSmall?.copyWith(color: elementColor),
ExcludeSemantics(
child: Text(
item.label!,
style: Theme.of(context).textTheme.labelSmall?.copyWith(color: elementColor),
),
),
],
),
Expand Down
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
46 changes: 45 additions & 1 deletion test/src/components/badge/indicator_test.dart
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,46 @@ void main() {
goldenFileComparator = TolerantComparator(goldenFile.uri);
});

group('Accessibility Tests', () {});
group('Accessibility Tests', () {
for (int i = 0; i < 10; i++) {
testWidgets('medium notification value $i meets accessibility standards', (tester) async {
final SemanticsHandle handle = tester.ensureSemantics();
await tester.pumpWidget(
TestApp(
home: ZetaIndicator(
size: ZetaWidgetSize.medium,
value: i,
),
),
);

await expectLater(tester, meetsGuideline(androidTapTargetGuideline));
await expectLater(tester, meetsGuideline(iOSTapTargetGuideline));
await expectLater(tester, meetsGuideline(labeledTapTargetGuideline));
await expectLater(tester, meetsGuideline(textContrastGuideline));

handle.dispose();
});

testWidgets('default notification value $i meets accessibility standards', (tester) async {
final SemanticsHandle handle = tester.ensureSemantics();
await tester.pumpWidget(
TestApp(
home: ZetaIndicator(
value: i,
),
),
);

await expectLater(tester, meetsGuideline(androidTapTargetGuideline));
await expectLater(tester, meetsGuideline(iOSTapTargetGuideline));
await expectLater(tester, meetsGuideline(labeledTapTargetGuideline));
await expectLater(tester, meetsGuideline(textContrastGuideline));

handle.dispose();
});
}
});
group('Content Tests', () {
final debugFillProperties = {
'color': 'MaterialColor(primary value: Color(0xffff9800))',
Expand Down Expand Up @@ -170,6 +209,11 @@ void main() {
'indicator_icon_values',
);
goldenTest(goldenFile, const ZetaIndicator.notification(), 'indicator_notification_default');
goldenTest(
goldenFile,
const ZetaIndicator.notification(value: 3, size: ZetaWidgetSize.medium),
'indicator_notification_with_value',
);
goldenTest(
goldenFile,
const ZetaIndicator.notification(
Expand Down
30 changes: 23 additions & 7 deletions test/src/components/navigation_bar/navigation_bar_test.dart
Original file line number Diff line number Diff line change
Expand Up @@ -17,8 +17,13 @@ void main() {
});

const items = [
ZetaNavigationBarItem(icon: ZetaIcons.star, label: 'Label0', badge: ZetaIndicator(value: 2)),
ZetaNavigationBarItem(icon: ZetaIcons.star, label: 'Label1'),
ZetaNavigationBarItem(
icon: ZetaIcons.star,
label: 'Label0',
badge: ZetaIndicator(
value: 2,
)),
ZetaNavigationBarItem(icon: ZetaIcons.star, label: 'Label1', badge: ZetaIndicator(value: 2)),
ZetaNavigationBarItem(icon: ZetaIcons.star, label: 'Label2'),
ZetaNavigationBarItem(icon: ZetaIcons.star, label: 'Label3'),
];
Expand All @@ -29,6 +34,7 @@ void main() {

group('Accessibility Tests', () {
testWidgets('meets accessibility requirements', (WidgetTester tester) async {
final SemanticsHandle handle = tester.ensureSemantics();
await tester.pumpWidget(
TestApp(
home: ZetaNavigationBar(
Expand All @@ -42,9 +48,11 @@ void main() {
await expectLater(tester, meetsGuideline(iOSTapTargetGuideline));
await expectLater(tester, meetsGuideline(labeledTapTargetGuideline));
await expectLater(tester, meetsGuideline(textContrastGuideline));
handle.dispose();
});

testWidgets('meets accessibility requirements with action', (WidgetTester tester) async {
final SemanticsHandle handle = tester.ensureSemantics();
await tester.pumpWidget(
TestApp(
home: ZetaNavigationBar.action(
Expand All @@ -58,9 +66,11 @@ void main() {
await expectLater(tester, meetsGuideline(iOSTapTargetGuideline));
await expectLater(tester, meetsGuideline(labeledTapTargetGuideline));
await expectLater(tester, meetsGuideline(textContrastGuideline));
handle.dispose();
});

testWidgets('meets accessibility requirements with divider', (WidgetTester tester) async {
final SemanticsHandle handle = tester.ensureSemantics();
await tester.pumpWidget(
const TestApp(
home: ZetaNavigationBar.divided(
Expand All @@ -74,9 +84,11 @@ void main() {
await expectLater(tester, meetsGuideline(iOSTapTargetGuideline));
await expectLater(tester, meetsGuideline(labeledTapTargetGuideline));
await expectLater(tester, meetsGuideline(textContrastGuideline));
handle.dispose();
});

testWidgets('meets accessibility requirements with split', (WidgetTester tester) async {
final SemanticsHandle handle = tester.ensureSemantics();
await tester.pumpWidget(
const TestApp(
home: ZetaNavigationBar.split(
Expand All @@ -89,21 +101,25 @@ void main() {
await expectLater(tester, meetsGuideline(iOSTapTargetGuideline));
await expectLater(tester, meetsGuideline(labeledTapTargetGuideline));
await expectLater(tester, meetsGuideline(textContrastGuideline));
handle.dispose();
});

testWidgets('items have semantic labels', (WidgetTester tester) async {
testWidgets('meets accessibility requirements with shrink items', (WidgetTester tester) async {
final SemanticsHandle handle = tester.ensureSemantics();
await tester.pumpWidget(
TestApp(
home: ZetaNavigationBar(
items: items,
shrinkItems: true,
),
),
);

for (int i = 0; i < items.length; i++) {
final itemsFinder = find.bySemanticsLabel('Label$i');
expect(itemsFinder, findsOneWidget);
}
await expectLater(tester, meetsGuideline(androidTapTargetGuideline));
await expectLater(tester, meetsGuideline(iOSTapTargetGuideline));
await expectLater(tester, meetsGuideline(labeledTapTargetGuideline));
await expectLater(tester, meetsGuideline(textContrastGuideline));
handle.dispose();
});
});

Expand Down

0 comments on commit 56e4433

Please sign in to comment.