diff --git a/doc/api/Widget.json b/doc/api/Widget.json index ece0dc20..c16875b7 100644 --- a/doc/api/Widget.json +++ b/doc/api/Widget.json @@ -149,6 +149,11 @@ "returns": "boolean", "description": "Returns `true` if the widget has been disposed, otherwise `false`." }, + "accessibilityFocus": { + "parameters": [], + "returns": "this", + "description": "Sets focus on the widget when accessibility services are enabled, helping screen readers highlight the element for improved navigation." + }, "_setParent": { "protected": true, "parameters": [ @@ -351,6 +356,15 @@ "data": { "type": "TData", "description": "A general-purpose property that may be set to any object. Unlike other properties, `data` forwards change events from the object it contains. As it is initialized with an empty instance of ${doc:ObservableData}, modifying this initial `data` object also causes a ${doc:PropertyChangedEvent} for `data` to be fired.\n\n**Important:** If `data` is assigned a plain object, that object will be converted to an ${doc:ObservableData} instance, *so the original object will not be identical with the new `data` value*. If set to any other object the new value will be the same instance.\n\n When set as an attribute (via JSX or a widget factory) it has a special treatment: Unlike other properties it is set *after* the listeners have been registered. This is so to allow passing a data change listener (via 'onDataChanged' attribute) that will be invoked for the initial data value immediately." + }, + "accessibilityHidden": { + "type": "boolean", + "default": "false", + "description": "Hides the widget from accessibility services, preventing screen readers from announcing it when active." + }, + "accessibilityLabel": { + "type": "string", + "description": "Provides a textual description of the widget for screen readers, describing its purpose or function to visually impaired users." } }, "events": { diff --git a/src/tabris/Widget.ts b/src/tabris/Widget.ts index d9e37e6a..a59b41ed 100644 --- a/src/tabris/Widget.ts +++ b/src/tabris/Widget.ts @@ -55,6 +55,8 @@ abstract class Widget extends NativeObject { highlightOnTouch!: boolean; cornerRadius!: number; padding!: BoxDimensionsObject & number; + accessibilityHidden!: boolean; + accessibilityLabel!: string; onResize!: Listeners<{bounds: Bounds}>; onBoundsChanged!: Listeners<{bounds: Bounds}>; @@ -140,6 +142,11 @@ abstract class Widget extends NativeObject { return this._parent._children((widget: Widget) => widget !== this).filter(selector); } + accessibilityFocus() { + this._nativeCall('accessibilityFocus', {}); + return this; + } + set class(value: string | undefined) { if (this._isDisposed) { hint(this, 'Cannot set property "class" on disposed object'); @@ -450,6 +457,14 @@ NativeObject.defineProperties(Widget.prototype, { padding: { type: types.BoxDimensions, default: Object.freeze({left: 0, right: 0, top: 0, bottom: 0}) + }, + accessibilityHidden: { + type: types.boolean, + default: false + }, + accessibilityLabel: { + type: types.string, + default: '' } }); diff --git a/test/tabris/widgets/Widget.test.ts b/test/tabris/widgets/Widget.test.ts index 9ffbe308..e244fbc6 100644 --- a/test/tabris/widgets/Widget.test.ts +++ b/test/tabris/widgets/Widget.test.ts @@ -291,6 +291,8 @@ describe('Widget', function() { translationY: 0, translationZ: 0 }); + expect(widget.accessibilityHidden).to.be.false; + expect(widget.accessibilityLabel).to.equal(''); }); describe('data', function() { diff --git a/test/typescript/Widgets/Widget.test.ts b/test/typescript/Widgets/Widget.test.ts index f1b3f008..71b8e64c 100644 --- a/test/typescript/Widgets/Widget.test.ts +++ b/test/typescript/Widgets/Widget.test.ts @@ -58,6 +58,8 @@ let transform: Transformation; let visible: boolean; let width: Dimension|'auto'; let data: object; +let accessibilityHidden: boolean; +let accessibilityLabel: string; const leftOffset: number = 0; const topOffset: number = 0; background = widget.background; @@ -89,6 +91,8 @@ transform = widget.transform; visible = widget.visible; width = widget.width; data = widget.data; +accessibilityHidden = widget.accessibilityHidden; +accessibilityLabel = widget.accessibilityLabel; widget.background = background; widget.background = backgroundImage; widget.background = backgroundColor; @@ -116,6 +120,8 @@ widget.top = topMargin; widget.transform = transform; widget.visible = visible; widget.width = width; +widget.accessibilityHidden = accessibilityHidden; +widget.accessibilityLabel = accessibilityLabel; const properties: Properties = { background, baseline, @@ -139,7 +145,9 @@ const properties: Properties = { top: topMargin, transform, visible, - width + width, + accessibilityHidden, + accessibilityLabel }; widget.set(properties); // Methods @@ -162,6 +170,7 @@ thisReturnValue = widget.detach(); voidReturnValue = widget.dispose(); thisReturnValue = widget.insertAfter(otherWidget); thisReturnValue = widget.insertBefore(otherWidget); +thisReturnValue = widget.accessibilityFocus(); bool = widget.isDisposed(); composite = widget.parent(); composite = widget.parent('#foo');