diff --git a/core/lib/core.dart b/core/lib/core.dart index 7cb178146..ec36fbcdf 100644 --- a/core/lib/core.dart +++ b/core/lib/core.dart @@ -100,6 +100,9 @@ export 'presentation/views/loading/cupertino_loading_widget.dart'; export 'presentation/views/image/image_loader_mixin.dart'; export 'presentation/views/pull_to_refresh/pull_to_refresh_widget.dart'; export 'presentation/views/button/multi_click_widget.dart'; +export 'presentation/views/semantics/checkbox_semantics.dart'; +export 'presentation/views/semantics/text_field_semantics.dart'; +export 'presentation/views/semantics/icon_semantics.dart'; // Resources export 'presentation/resources/assets_paths.dart'; diff --git a/core/lib/presentation/views/semantics/text_field_semantics.dart b/core/lib/presentation/views/semantics/text_field_semantics.dart new file mode 100644 index 000000000..e9e8e51ad --- /dev/null +++ b/core/lib/presentation/views/semantics/text_field_semantics.dart @@ -0,0 +1,19 @@ +import 'package:flutter/material.dart'; + +class TextFieldSemantics extends StatelessWidget { + final Widget child; + final String label; + final String value; + + const TextFieldSemantics({ + super.key, + required this.child, + required this.label, + required this.value, + }); + + @override + Widget build(BuildContext context) { + return Semantics(label: label, value: value, container: true, child: child); + } +} diff --git a/core/lib/presentation/views/text/text_field_builder.dart b/core/lib/presentation/views/text/text_field_builder.dart index bc31baa14..4934594ff 100644 --- a/core/lib/presentation/views/text/text_field_builder.dart +++ b/core/lib/presentation/views/text/text_field_builder.dart @@ -1,4 +1,5 @@ import 'package:core/presentation/extensions/color_extension.dart'; +import 'package:core/presentation/views/semantics/text_field_semantics.dart'; import 'package:core/utils/direction_utils.dart'; import 'package:flutter/material.dart'; @@ -25,6 +26,7 @@ class TextFieldBuilder extends StatefulWidget { final TextDirection textDirection; final bool readOnly; final MouseCursor? mouseCursor; + final String? semanticLabel; const TextFieldBuilder({ super.key, @@ -45,6 +47,7 @@ class TextFieldBuilder extends StatefulWidget { this.fromValue, this.keyboardAppearance, this.mouseCursor, + this.semanticLabel, this.onTap, this.onTapOutside, this.onTextChange, @@ -76,7 +79,7 @@ class _TextFieldBuilderState extends State { @override Widget build(BuildContext context) { - return TextField( + final textField = TextField( key: widget.key, controller: _controller, cursorColor: widget.cursorColor, @@ -99,6 +102,16 @@ class _TextFieldBuilderState extends State { onTap: widget.onTap, onTapOutside: widget.onTapOutside, ); + + if (widget.semanticLabel != null) { + return TextFieldSemantics( + label: widget.semanticLabel!, + value: _controller?.text ?? '', + child: textField, + ); + } else { + return textField; + } } void _onTextChanged(String value) { diff --git a/lib/features/identity_creator/presentation/widgets/identity_input_field_builder.dart b/lib/features/identity_creator/presentation/widgets/identity_input_field_builder.dart index a82cd0abb..75188146a 100644 --- a/lib/features/identity_creator/presentation/widgets/identity_input_field_builder.dart +++ b/lib/features/identity_creator/presentation/widgets/identity_input_field_builder.dart @@ -52,6 +52,7 @@ class IdentityInputFieldBuilder extends StatelessWidget { focusNode: focusNode, textStyle: const TextStyle(color: Colors.black, fontSize: 16), keyboardType: inputType ?? TextInputType.text, + semanticLabel: 'Identity input field', decoration: (IdentityInputDecorationBuilder() ..setContentPadding(EdgeInsets.symmetric( vertical: PlatformInfo.isWeb ? 16 : 12,