Skip to content

Commit 4726dbb

Browse files
feat: ✨ Enhance tooltip accessibility using Semantics live region (#604)
1 parent 343efe3 commit 4726dbb

File tree

6 files changed

+35
-3
lines changed

6 files changed

+35
-3
lines changed

CHANGELOG.md

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,8 @@
44
- Fixed [#587](https://github.com/SimformSolutionsPvtLtd/showcaseview/issues/587) - Fixed ShowcaseView.withWidget container positioning issues on web
55
- Fixed [#588](https://github.com/SimformSolutionsPvtLtd/showcaseview/issues/588) & [#593](https://github.com/SimformSolutionsPvtLtd/showcaseview/issues/593) - Fixed incorrect ShowcaseView callback scope by adding optional scope parameter
66
- Feature [#600](https://github.com/SimformSolutionsPvtLtd/showcaseview/issues/600) - Added dynamic onComplete callback registration with `addOnCompleteCallback` and `removeOnCompleteCallback` methods
7-
- Fixed [#577](https://github.com/SimformSolutionsPvtLtd/showcaseview/issues/577) - Resolve issue where long tooltip text was rendered outside the screen bounds
7+
- Fixed [#577](https://github.com/SimformSolutionsPvtLtd/showcaseview/issues/577) - Resolve issue where long tooltip text was rendered outside the screen bounds
8+
- Feature [#586](https://github.com/SimformSolutionsPvtLtd/showcaseview/issues/586): Enhance tooltip accessibility using Semantics live region
89

910
## [5.0.1]
1011

doc/documentation.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -129,6 +129,7 @@ Reference](https://pub.dev/documentation/showcaseview/latest/showcaseview/).
129129
```dart
130130
ShowcaseView.register(
131131
autoPlayDelay: const Duration(seconds: 3),
132+
semanticEnable: true, // Enable accessibility support globally
132133
globalFloatingActionWidget: (showcaseContext) => FloatingActionWidget(
133134
left: 16,
134135
bottom: 16,

lib/src/showcase/showcase_controller.dart

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -350,6 +350,7 @@ class ShowcaseController {
350350
targetPadding: config.targetPadding,
351351
targetTooltipGap: config.targetTooltipGap,
352352
showcaseController: this,
353+
semanticEnable: showcaseView.semanticEnable,
353354
),
354355
if (_getFloatingActionWidget case final floatAction?) floatAction,
355356
];

lib/src/showcase/showcase_view.dart

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -80,6 +80,7 @@ class ShowcaseView {
8080
this.globalTooltipActions,
8181
this.globalFloatingActionWidget,
8282
this.hideFloatingActionWidgetForShowcase = const [],
83+
this.semanticEnable = false,
8384
}) {
8485
ShowcaseService.instance.register(this, scope: scope);
8586
_hideFloatingWidgetKeys = {
@@ -145,6 +146,15 @@ class ShowcaseView {
145146
/// Enable/disable showcase globally.
146147
bool enableShowcase;
147148

149+
/// Whether to enable semantic properties for accessibility.
150+
///
151+
/// When set to true, semantic widgets will be added to improve
152+
/// screen reader support throughout the showcase. When false,
153+
/// semantic properties will not be applied.
154+
///
155+
/// Defaults to false.
156+
final bool semanticEnable;
157+
148158
/// Custom static floating action widget to show a static non-animating
149159
/// widget anywhere on the screen for all the showcase widget.
150160
FloatingActionBuilderCallback? globalFloatingActionWidget;

lib/src/tooltip/tooltip_wrapper.dart

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -66,6 +66,7 @@ class ToolTipWrapper extends StatefulWidget {
6666
required this.tooltipPadding,
6767
required this.toolTipSlideEndDistance,
6868
required this.targetTooltipGap,
69+
this.semanticEnable = false,
6970
this.scaleAnimationAlignment,
7071
this.tooltipPosition,
7172
this.titlePadding,
@@ -108,6 +109,7 @@ class ToolTipWrapper extends StatefulWidget {
108109
final EdgeInsets targetPadding;
109110
final ShowcaseController showcaseController;
110111
final double targetTooltipGap;
112+
final bool semanticEnable;
111113

112114
@override
113115
State<ToolTipWrapper> createState() => _ToolTipWrapperState();
@@ -254,7 +256,12 @@ class _ToolTipWrapperState extends State<ToolTipWrapper>
254256
_TooltipLayoutId(
255257
id: TooltipLayoutSlot.tooltipBox,
256258
key: UniqueKey(),
257-
child: defaultToolTipWidget,
259+
child: !widget.semanticEnable
260+
? defaultToolTipWidget
261+
: Semantics(
262+
liveRegion: true,
263+
child: defaultToolTipWidget,
264+
),
258265
),
259266
if (widget.tooltipActions.isNotEmpty &&
260267
(widget.tooltipActionConfig.position.isOutside ||

lib/src/widget/tooltip_action_button_widget.dart

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -51,7 +51,7 @@ class TooltipActionButtonWidget extends StatelessWidget {
5151
Widget build(BuildContext context) {
5252
final theme = Theme.of(context);
5353

54-
return config.button ??
54+
final child = config.button ??
5555
MouseRegion(
5656
cursor: SystemMouseCursors.click,
5757
child: GestureDetector(
@@ -85,6 +85,18 @@ class TooltipActionButtonWidget extends StatelessWidget {
8585
),
8686
),
8787
);
88+
89+
// Semantics widget is used to improve accessibility for screen readers.
90+
// Only applied when semanticEnable is true.
91+
if (showCaseState.semanticEnable) {
92+
return Semantics(
93+
button: true,
94+
liveRegion: true,
95+
child: child,
96+
);
97+
}
98+
99+
return child;
88100
}
89101

90102
void _handleOnTap() {

0 commit comments

Comments
 (0)