Skip to content

Commit

Permalink
feat(Row): allow aria-label in informative rows (#1269)
Browse files Browse the repository at this point in the history
https://jira.tid.es/browse/WEB-2061
By default, the browser will read text content inside rows one by one
(title, description, etc).
With the changes in this PR, if an aria-label is provided to the
informative row, the whole row will be read as a single text (the one
provided in the aria-label prop)

This PR also fixes https://jira.tid.es/browse/WEB-1885 which is a
basically revert of #942.
As part of this PR we allow passing custom styles (via `className` prop)
to `ScreenReaderOnly` to workaround possible style issues found (like
the one described originally in
#942).
  • Loading branch information
atabel authored Oct 23, 2024
1 parent fc63201 commit 65b5d42
Show file tree
Hide file tree
Showing 4 changed files with 33 additions and 9 deletions.
17 changes: 17 additions & 0 deletions src/__tests__/list-test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -446,3 +446,20 @@ test('Text content is read by screen readers in the right order in Rows with rad
});
expect(row).toBeInTheDocument();
});

test('aria-label is read by screen readers in informative rows', () => {
render(
<ThemeContextProvider theme={makeTheme()}>
<RowList>
<Row
aria-label="Some custom label"
headline={<Tag type="promo">Headline</Tag>}
title="Title"
description="Description"
/>
</RowList>
</ThemeContextProvider>
);

expect(screen.getByText('Some custom label')).toBeInTheDocument();
});
10 changes: 9 additions & 1 deletion src/list.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ import * as mediaStyles from './image.css';
import {vars} from './skins/skin-contract.css';
import {applyCssVars} from './utils/css';
import {IconButton, ToggleIconButton} from './icon-button';
import ScreenReaderOnly from './screen-reader-only';

import type {IconButtonProps, ToggleIconButtonProps} from './icon-button';
import type {TouchableElement, TouchableProps} from './touchable';
Expand Down Expand Up @@ -633,14 +634,21 @@ const RowContent = React.forwardRef<TouchableElement, RowContentProps>((props, r
);
}

const hasCustomAriaLabel = !!props['aria-label'];

return (
<div
className={classNames(styles.rowContent, styles.rowContentPadding)}
role={role}
{...getPrefixedDataAttributes(dataAttributes)}
ref={ref as React.Ref<HTMLDivElement>}
>
{renderContent()}
<div aria-hidden={hasCustomAriaLabel}>{renderContent()}</div>
{hasCustomAriaLabel && (
<ScreenReaderOnly>
<span>{props['aria-label']}</span>
</ScreenReaderOnly>
)}
</div>
);
});
Expand Down
5 changes: 2 additions & 3 deletions src/screen-reader-only.css.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,9 +13,8 @@ export const screenReaderOnly = style([
width: 1,
height: 1,
clip: 'rect(0, 0, 0, 0)',
clipPath: 'inset(50%)',
whiteSpace: 'nowrap',
userSelect: 'none',
// move the element out of the screen to avoid scrolling issues. See https://github.com/Telefonica/mistica-web/pull/942
left: -10000,
top: -10000,
},
]);
10 changes: 5 additions & 5 deletions src/screen-reader-only.tsx
Original file line number Diff line number Diff line change
@@ -1,30 +1,30 @@
import * as React from 'react';
import * as styles from './screen-reader-only.css';
import {getPrefixedDataAttributes} from './utils/dom';
import classnames from 'classnames';

import type {DataAttributes} from './utils/types';

type Props = {
children: React.ReactNode;
className?: string;
dataAttributes?: DataAttributes;
};

const ScreenReaderOnly = ({children, dataAttributes}: Props): JSX.Element => {
const ScreenReaderOnly = ({children, className, dataAttributes}: Props): JSX.Element => {
const prefixedDataAttributes = getPrefixedDataAttributes(dataAttributes, 'ScreenReaderOnly');

if (React.Children.count(children) === 1) {
const element = React.Children.only(children);
if (React.isValidElement(element)) {
return React.cloneElement(element as React.ReactElement, {
className: element.props.className
? element.props.className + ' ' + styles.screenReaderOnly
: styles.screenReaderOnly,
className: classnames(element.props.className, styles.screenReaderOnly, className),
...prefixedDataAttributes,
});
}
}
return (
<div className={styles.screenReaderOnly} {...prefixedDataAttributes}>
<div className={classnames(styles.screenReaderOnly, className)} {...prefixedDataAttributes}>
{children}
</div>
);
Expand Down

1 comment on commit 65b5d42

@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-fphcgtk2o-flows-projects-65bb050e.vercel.app

Built with commit 65b5d42.
This pull request is being automatically deployed with vercel-action

Please sign in to comment.