Skip to content

Commit

Permalink
feat(Rows): a11y update (#1180)
Browse files Browse the repository at this point in the history
  • Loading branch information
marcoskolodny authored Jul 30, 2024
1 parent 7e2135a commit 5f995ad
Show file tree
Hide file tree
Showing 3 changed files with 44 additions and 10 deletions.
25 changes: 19 additions & 6 deletions src/__tests__/list-test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -214,7 +214,7 @@ test('RowList inside Form', async () => {
radio: 'banana',
});
});
});
}, 20000);

test('Row list with icon buttons', async () => {
const firstButtonSpy = jest.fn();
Expand Down Expand Up @@ -304,6 +304,8 @@ test('Text content is read by screen readers in the right order in Rows with lin
subtitle="Subtitle"
description="Description"
detail="Detail"
right="right"
asset={<IconShopRegular />}
extra={
<Stack space={4}>
<Text2 regular>Extra line 1</Text2>
Expand All @@ -318,7 +320,7 @@ test('Text content is read by screen readers in the right order in Rows with lin

const row = screen.getByRole('link', {
// WARN: There should be a space between the extra lines, but jsdom doesn't support .innerText method, so we fallback to .textContent https://github.com/jsdom/jsdom/issues/1245
name: 'Title Headline Subtitle Description Extra line 1Extra line 2 Detail',
name: 'Title Headline Subtitle Description Extra line 1Extra line 2 Detail right',
});
expect(row).toBeInTheDocument();
});
Expand All @@ -333,6 +335,8 @@ test('Text content is read by screen readers in the right order in Rows with but
subtitle="Subtitle"
description="Description"
detail="Detail"
right="right"
asset={<IconShopRegular />}
extra={
<Stack space={4}>
<Text2 regular>Extra line 1</Text2>
Expand All @@ -346,7 +350,7 @@ test('Text content is read by screen readers in the right order in Rows with but
);

const row = screen.getByRole('button', {
name: 'Title Headline Subtitle Description Extra line 1 Extra line 2 Detail',
name: 'Title Headline Subtitle Description Extra line 1 Extra line 2 Detail right',
});
expect(row).toBeInTheDocument();
});
Expand All @@ -366,14 +370,17 @@ test('Text content is read by screen readers in the right order in Rows with che
<Text2 regular>Extra line 2</Text2>
</Stack>
}
detail="detail"
right="right"
asset={<IconShopRegular />}
checkbox={{defaultValue: false}}
/>
</RowList>
</ThemeContextProvider>
);

const row = screen.getByRole('checkbox', {
name: 'Title Headline Subtitle Description Extra line 1 Extra line 2',
name: 'Title Headline Subtitle Description Extra line 1 Extra line 2 detail right',
});
expect(row).toBeInTheDocument();
});
Expand All @@ -393,14 +400,17 @@ test('Text content is read by screen readers in the right order in Rows with swi
<Text2 regular>Extra line 2</Text2>
</Stack>
}
detail="detail"
right="right"
asset={<IconShopRegular />}
switch={{defaultValue: false}}
/>
</RowList>
</ThemeContextProvider>
);

const row = screen.getByRole('switch', {
name: 'Title Headline Subtitle Description Extra line 1 Extra line 2',
name: 'Title Headline Subtitle Description Extra line 1 Extra line 2 detail right',
});
expect(row).toBeInTheDocument();
});
Expand All @@ -421,6 +431,9 @@ test('Text content is read by screen readers in the right order in Rows with rad
<Text2 regular>Extra line 2</Text2>
</Stack>
}
detail="detail"
right="right"
asset={<IconShopRegular />}
radioValue="radio1"
/>
</RowList>
Expand All @@ -429,7 +442,7 @@ test('Text content is read by screen readers in the right order in Rows with rad
);

const row = screen.getByRole('radio', {
name: 'Title Headline Subtitle Description Extra line 1 Extra line 2',
name: 'Title Headline Subtitle Description Extra line 1 Extra line 2 detail right',
});
expect(row).toBeInTheDocument();
});
3 changes: 3 additions & 0 deletions src/box.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ type Props = {
dataAttributes?: DataAttributes;
'aria-label'?: string;
'aria-hidden'?: React.HTMLAttributes<HTMLAnchorElement>['aria-hidden'];
id?: string;
};

const Box = React.forwardRef<HTMLDivElement, Props>(
Expand All @@ -39,6 +40,7 @@ const Box = React.forwardRef<HTMLDivElement, Props>(
paddingLeft = paddingX,
paddingRight = paddingX,
role,
id,
dataAttributes,
'aria-label': ariaLabel,
'aria-hidden': ariaHidden,
Expand Down Expand Up @@ -73,6 +75,7 @@ const Box = React.forwardRef<HTMLDivElement, Props>(
...(width !== undefined ? {width, boxSizing: 'border-box'} : {}),
...(!paddingClasses ? paddingStyles : {}),
}}
id={id}
>
{children}
</div>
Expand Down
26 changes: 22 additions & 4 deletions src/list.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -73,6 +73,7 @@ const renderRight = (right: Right, centerY: boolean) => {

interface ContentProps extends CommonProps {
headlineRef?: React.Ref<HTMLDivElement>;
rightRef?: React.Ref<HTMLDivElement>;
extraRef?: React.Ref<HTMLDivElement>;
control?: React.ReactNode;
/** This id is to link the title with the related control */
Expand All @@ -96,6 +97,7 @@ export const Content: React.FC<ContentProps> = ({
danger,
badge,
right,
rightRef,
extra,
labelId,
disabled,
Expand All @@ -106,11 +108,13 @@ export const Content: React.FC<ContentProps> = ({
const centerY = numTextLines === 1;

return (
<Box paddingY={16} className={styles.content}>
<Box paddingY={16} className={styles.content} id={labelId}>
{asset && (
<Box
paddingRight={16}
className={classNames({[styles.center]: centerY, [styles.disabled]: disabled})}
// We don't want asset to be readable by screen readers
aria-hidden
>
<div
className={styles.asset}
Expand All @@ -133,7 +137,6 @@ export const Content: React.FC<ContentProps> = ({
<div
className={classNames(styles.rowBody, {[styles.disabled]: disabled})}
style={{justifyContent: centerY ? 'center' : 'flex-start'}}
id={labelId}
>
<Text3
regular
Expand Down Expand Up @@ -206,6 +209,7 @@ export const Content: React.FC<ContentProps> = ({
[styles.detailRight]: !!detail,
[styles.disabled]: disabled,
})}
ref={rightRef}
>
{renderRight(right, centerY)}
</div>
Expand Down Expand Up @@ -362,9 +366,18 @@ const RowContent = React.forwardRef<TouchableElement, RowContentProps>((props, r

const [headlineText, setHeadlineText] = React.useState<string>('');
const [extraText, setExtraText] = React.useState<string>('');
const [rightText, setRightText] = React.useState<string>('');

// iOS voiceover reads links with multiple lines as separate links. By setting aria-label and marking content as aria-hidden, we can make it read the whole row as one link.
const computedAriaLabelForLink = [title, headlineText, subtitle, description, extraText, detail]
const computedAriaLabelForLink = [
title,
headlineText,
subtitle,
description,
extraText,
detail,
rightText,
]
.filter(Boolean)
.join(' ');

Expand Down Expand Up @@ -414,11 +427,16 @@ const RowContent = React.forwardRef<TouchableElement, RowContentProps>((props, r
detail={detail}
danger={danger}
right={right}
rightRef={(node) => {
if (node) {
// jsdom doesn't support innerText so we fallback to textContent https://github.com/jsdom/jsdom/issues/1245
setRightText(node.innerText || node.textContent || '');
}
}}
control={contentProps?.control}
extra={extra}
extraRef={(node) => {
if (node) {
// jsdom doesn't support innerText so we fallback to textContent https://github.com/jsdom/jsdom/issues/1245
setExtraText(node.innerText || node.textContent || '');
}
}}
Expand Down

1 comment on commit 5f995ad

@github-actions
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Deploy preview for mistica-web ready!

✅ Preview
https://mistica-e6yhbd8m1-flows-projects-65bb050e.vercel.app

Built with commit 5f995ad.
This pull request is being automatically deployed with vercel-action

Please sign in to comment.