diff --git a/packages/render-html/src/__tests__/component.render-html-a11y.test.tsx b/packages/render-html/src/__tests__/component.render-html-a11y.test.tsx index 9f98032b9..2a77e6979 100644 --- a/packages/render-html/src/__tests__/component.render-html-a11y.test.tsx +++ b/packages/render-html/src/__tests__/component.render-html-a11y.test.tsx @@ -1,7 +1,13 @@ +import { + defaultHTMLElementModels, + HTMLContentModel, + TBlock +} from '@native-html/transient-render-engine'; import { render } from '@testing-library/react-native'; import React from 'react'; import AccessibilityEngine from 'react-native-accessibility-engine'; import RenderHTML from '../RenderHTML'; +import { CustomRendererProps } from '../shared-types'; describe('RenderHTML a11y', () => { describe('regarding anchors', () => { @@ -82,4 +88,62 @@ describe('RenderHTML a11y', () => { expect(() => AccessibilityEngine.check(element)).not.toThrow(); }); }); + describe('regarding pressable custom renderers', () => { + it('should add a button role if onPress is defined for custom renderers with a block content model', () => { + const element = ( + ' + }} + customHTMLElementModels={{ + ...defaultHTMLElementModels, + button: defaultHTMLElementModels.button.extend({ + contentModel: HTMLContentModel.block + }) + }} + renderers={{ + button: ({ + TDefaultRenderer, + ...props + }: CustomRendererProps) => ( + {}} {...props} /> + ) + }} + debug={false} + contentWidth={200} + /> + ); + const { getByA11yRole } = render(element); + const buttonProps = getByA11yRole('button').props; + expect(buttonProps.accessibilityRole).toBe('button'); + expect(() => AccessibilityEngine.check(element)).not.toThrow(); + }); + it('should add a button role if onPress is defined for custom renderers with a textual content model', () => { + const element = ( + ' + }} + customHTMLElementModels={{ + ...defaultHTMLElementModels, + customlink: defaultHTMLElementModels.span + }} + renderers={{ + customlink: ({ + TDefaultRenderer, + ...props + }: CustomRendererProps) => ( + {}} {...props} /> + ) + }} + debug={false} + contentWidth={200} + /> + ); + const { getByA11yRole } = render(element); + const buttonProps = getByA11yRole('link').props; + expect(buttonProps.accessibilityRole).toBe('link'); + expect(() => AccessibilityEngine.check(element)).not.toThrow(); + }); + }); }); diff --git a/packages/render-html/src/helpers/getNativePropsForTNode.ts b/packages/render-html/src/helpers/getNativePropsForTNode.ts index e99370b7e..c39008034 100644 --- a/packages/render-html/src/helpers/getNativePropsForTNode.ts +++ b/packages/render-html/src/helpers/getNativePropsForTNode.ts @@ -1,4 +1,5 @@ import { TBlock, TPhrasing, TText } from '@native-html/transient-render-engine'; +import { TextProps, ViewProps } from 'react-native'; import { TDefaultRendererProps } from '../shared-types'; /** @@ -8,10 +9,13 @@ import { TDefaultRendererProps } from '../shared-types'; */ export default function getNativePropsForTNode( props: TDefaultRendererProps -) { +): TextProps | ViewProps { const { tnode, style, type, nativeProps, onPress } = props; const switchProp = type === 'block' ? props.viewProps : props.textProps; return { + ...(typeof onPress === 'function' + ? ({ accessibilityRole: type === 'block' ? 'button' : 'link' } as const) + : null), ...tnode.getReactNativeProps()?.[type === 'block' ? 'view' : 'text'], ...nativeProps, ...switchProp,