diff --git a/src-docs/src/views/accessibility/accessibility_example.js b/src-docs/src/views/accessibility/accessibility_example.js index 60ee25bfede..309724778bc 100644 --- a/src-docs/src/views/accessibility/accessibility_example.js +++ b/src-docs/src/views/accessibility/accessibility_example.js @@ -15,6 +15,7 @@ import { import ScreenReaderLive from './screen_reader_live'; import ScreenReaderLiveFocus from './screen_reader_live_focus'; import ScreenReaderOnly from './screen_reader'; +import ScreenReaderPreventCopy from './screen_reader_prevent_copy'; import ScreenReaderFocus from './screen_reader_focus'; import SkipLink from './skip_link'; import StylesHelpers from './styles_helpers'; @@ -22,6 +23,7 @@ import StylesHelpers from './styles_helpers'; const screenReaderLiveSource = require('!!raw-loader!./screen_reader_live'); const screenReaderLiveFocusSource = require('!!raw-loader!./screen_reader_live_focus'); const screenReaderOnlySource = require('!!raw-loader!./screen_reader'); +const screenReaderPreventCopySource = require('!!raw-loader!./screen_reader_prevent_copy'); const screenReaderFocusSource = require('!!raw-loader!./screen_reader_focus'); const skipLinkSource = require('!!raw-loader!./skip_link'); @@ -74,7 +76,8 @@ export const AccessibilityExample = {

- Using a screen reader, verify that there is a second paragraph. + Use a screen reader, or select and copy both lines in the below + demo, to verify that there is a second paragraph.

@@ -87,6 +90,38 @@ export const AccessibilityExample = { `, demo: , }, + { + source: [ + { + type: GuideSectionTypes.JS, + code: screenReaderPreventCopySource, + }, + ], + text: ( + <> +

Preventing users from copying hidden text

+

+ As you may have noticed in the previous demo, screen reader only + text is still selectable and copyable. If for any reason you do not + want this behavior, simply use the preventCopy{' '} + prop. +

+

+ + Select and copy both lines in the below demo and confirm only the + visible lines are copied. + +

+ + ), + props: { + EuiScreenReaderOnly, + }, + snippet: ` + +`, + demo: , + }, { source: [ { @@ -96,7 +131,7 @@ export const AccessibilityExample = { ], text: ( <> -

Showing on focus

+

Showing on focus

If the wrapped element is focusable, you must use the showOnFocus prop to visibly show the element diff --git a/src-docs/src/views/accessibility/screen_reader_prevent_copy.tsx b/src-docs/src/views/accessibility/screen_reader_prevent_copy.tsx new file mode 100644 index 00000000000..e62ecf47bfb --- /dev/null +++ b/src-docs/src/views/accessibility/screen_reader_prevent_copy.tsx @@ -0,0 +1,16 @@ +import React from 'react'; + +import { EuiScreenReaderOnly, EuiText } from '../../../../src/components'; + +export default () => ( + +

This is the first paragraph. It is visible and copyable.

+ +

+ This is the second paragraph. It is hidden for sighted users, and is not + selectable or copyable by users, but remains visible to screen readers. +

+
+

This is the third paragraph. It is visible and copyable.

+ +); diff --git a/src/components/accessibility/screen_reader_only/__snapshots__/screen_reader_only.test.tsx.snap b/src/components/accessibility/screen_reader_only/__snapshots__/screen_reader_only.test.tsx.snap index b96c8872fdc..a457d70a23b 100644 --- a/src/components/accessibility/screen_reader_only/__snapshots__/screen_reader_only.test.tsx.snap +++ b/src/components/accessibility/screen_reader_only/__snapshots__/screen_reader_only.test.tsx.snap @@ -4,7 +4,7 @@ exports[`EuiScreenReaderOnly adds an accessibility class to a child element and

- This paragraph is not visibile to sighted users but will be read by screenreaders. + This paragraph is not visible to sighted users but will be read by screenreaders.

`; @@ -12,13 +12,21 @@ exports[`EuiScreenReaderOnly adds an accessibility class to a child element when

- This paragraph is not visibile to sighted users but will be read by screenreaders. + This paragraph is not visible to sighted users but will be read by screenreaders.

`; -exports[`EuiScreenReaderOnly will show on focus 1`] = ` +exports[`EuiScreenReaderOnly preventCopy 1`] = ` + + Text + +`; + +exports[`EuiScreenReaderOnly showOnFocus 1`] = ` Link diff --git a/src/components/accessibility/screen_reader_only/screen_reader_only.styles.ts b/src/components/accessibility/screen_reader_only/screen_reader_only.styles.ts index 3599923538a..0983d2847b4 100644 --- a/src/components/accessibility/screen_reader_only/screen_reader_only.styles.ts +++ b/src/components/accessibility/screen_reader_only/screen_reader_only.styles.ts @@ -34,13 +34,18 @@ export const euiScreenReaderOnly = () => ` /* * Styles */ -export const euiScreenReaderOnlyStyles = (showOnFocus?: boolean) => ({ - euiScreenReaderOnly: showOnFocus - ? css` - // The :active selector is necessary for Safari which removes :focus when a button is pressed - &:not(:focus):not(:active):not(:focus-within) { - ${euiScreenReaderOnly()} - } - ` - : css(euiScreenReaderOnly()), +export const euiScreenReaderOnlyStyles = () => ({ + // Note: the default SR only CSS and `showOnFocus` CSS are mutually exclusive + euiScreenReaderOnly: css` + ${euiScreenReaderOnly()} + `, + 'euiScreenReaderOnly-showOnFocus': css` + // The :active selector is necessary for Safari which removes :focus when a button is pressed + &:not(:focus):not(:active):not(:focus-within) { + ${euiScreenReaderOnly()} + } + `, + preventCopy: css` + user-select: none; + `, }); diff --git a/src/components/accessibility/screen_reader_only/screen_reader_only.test.tsx b/src/components/accessibility/screen_reader_only/screen_reader_only.test.tsx index 5adeb8dad54..83fed7298ea 100644 --- a/src/components/accessibility/screen_reader_only/screen_reader_only.test.tsx +++ b/src/components/accessibility/screen_reader_only/screen_reader_only.test.tsx @@ -17,7 +17,7 @@ describe('EuiScreenReaderOnly', () => { const $paragraph = render(

- This paragraph is not visibile to sighted users but will be read by + This paragraph is not visible to sighted users but will be read by screenreaders.

@@ -25,11 +25,12 @@ describe('EuiScreenReaderOnly', () => { expect($paragraph).toMatchSnapshot(); }); + test('and combines other classNames (foo, bar) given as props on the child', () => { const $paragraph = render(

- This paragraph is not visibile to sighted users but will be read by + This paragraph is not visible to sighted users but will be read by screenreaders.

@@ -39,7 +40,7 @@ describe('EuiScreenReaderOnly', () => { }); }); - test('will show on focus', () => { + test('showOnFocus', () => { const component = render(
Link @@ -48,4 +49,14 @@ describe('EuiScreenReaderOnly', () => { expect(component).toMatchSnapshot(); }); + + test('preventCopy', () => { + const component = render( + + Text + + ); + + expect(component).toMatchSnapshot(); + }); }); diff --git a/src/components/accessibility/screen_reader_only/screen_reader_only.tsx b/src/components/accessibility/screen_reader_only/screen_reader_only.tsx index faf1b9d38f3..be0ca696bb1 100644 --- a/src/components/accessibility/screen_reader_only/screen_reader_only.tsx +++ b/src/components/accessibility/screen_reader_only/screen_reader_only.tsx @@ -18,20 +18,33 @@ export interface EuiScreenReaderOnlyProps { */ children: ReactElement; + className?: string; + /** * For keyboard navigation, force content to display visually upon focus/focus-within. */ showOnFocus?: boolean; - className?: string; + + /** + * Despite being visually hidden, text within `EuiScreenReaderOnly` will still + * be selectable and copyable. Set this to `true` if you do not want your + * screen reader text to be copied. + */ + preventCopy?: boolean; } export const EuiScreenReaderOnly: FunctionComponent< EuiScreenReaderOnlyProps -> = ({ children, className, showOnFocus }) => { +> = ({ children, className, showOnFocus, preventCopy }) => { const classes = classNames(className, children.props.className); - const styles = euiScreenReaderOnlyStyles(showOnFocus); - const cssStyles = [styles.euiScreenReaderOnly]; + const styles = euiScreenReaderOnlyStyles(); + const cssStyles = [ + showOnFocus + ? styles['euiScreenReaderOnly-showOnFocus'] + : styles.euiScreenReaderOnly, + preventCopy && styles.preventCopy, + ]; const props = { className: classes.length ? classes : undefined, diff --git a/src/components/accessibility/skip_link/__snapshots__/skip_link.test.tsx.snap b/src/components/accessibility/skip_link/__snapshots__/skip_link.test.tsx.snap index 53af988e3e1..6a24e7e1840 100644 --- a/src/components/accessibility/skip_link/__snapshots__/skip_link.test.tsx.snap +++ b/src/components/accessibility/skip_link/__snapshots__/skip_link.test.tsx.snap @@ -3,7 +3,7 @@ exports[`EuiSkipLink is rendered 1`] = ` @@ -34,7 +34,7 @@ exports[`EuiSkipLink props position absolute is rendered 1`] = ` exports[`EuiSkipLink props position fixed is rendered 1`] = ` @@ -59,7 +59,7 @@ exports[`EuiSkipLink props position static is rendered 1`] = ` exports[`EuiSkipLink props tabIndex is rendered 1`] = ` @@ -767,8 +766,7 @@ Array [ 0, B @@ -800,8 +798,7 @@ Array [ 1, A @@ -833,8 +830,7 @@ Array [ 1, B @@ -866,8 +862,7 @@ Array [ 2, A @@ -899,8 +894,7 @@ Array [ 2, B @@ -1252,8 +1246,7 @@ Array [ 0 @@ -1291,8 +1284,7 @@ Array [ 0, A @@ -1324,8 +1316,7 @@ Array [ 0, B @@ -1365,8 +1356,7 @@ Array [ 0 @@ -1412,8 +1402,7 @@ Array [ 1 @@ -1451,8 +1440,7 @@ Array [ 1, A @@ -1484,8 +1472,7 @@ Array [ 1, B @@ -1525,8 +1512,7 @@ Array [ 1 @@ -1572,8 +1558,7 @@ Array [ 2 @@ -1611,8 +1596,7 @@ Array [ 2, A @@ -1644,8 +1628,7 @@ Array [ 2, B @@ -1685,8 +1668,7 @@ Array [ 2 @@ -1997,8 +1979,7 @@ Array [ 0, A @@ -2030,8 +2011,7 @@ Array [ 0, B @@ -2063,8 +2043,7 @@ Array [ 1, A @@ -2096,8 +2075,7 @@ Array [ 1, B @@ -2129,8 +2107,7 @@ Array [ 2, A @@ -2162,8 +2139,7 @@ Array [ 2, B @@ -2466,8 +2442,7 @@ Array [ 0, A @@ -2499,8 +2474,7 @@ Array [ 0, B @@ -2532,8 +2506,7 @@ Array [ 1, A @@ -2565,8 +2538,7 @@ Array [ 1, B @@ -2598,8 +2570,7 @@ Array [ 2, A @@ -2631,8 +2602,7 @@ Array [ 2, B diff --git a/src/components/datagrid/body/__snapshots__/data_grid_body_custom.test.tsx.snap b/src/components/datagrid/body/__snapshots__/data_grid_body_custom.test.tsx.snap index bce634a36b1..a4be2ea4b04 100644 --- a/src/components/datagrid/body/__snapshots__/data_grid_body_custom.test.tsx.snap +++ b/src/components/datagrid/body/__snapshots__/data_grid_body_custom.test.tsx.snap @@ -146,8 +146,7 @@ exports[`EuiDataGridBodyCustomRender treats \`renderCustomGridBody\` as a render hello @@ -180,8 +179,7 @@ exports[`EuiDataGridBodyVirtualized renders 1`] = ` diff --git a/src/components/datagrid/body/__snapshots__/data_grid_cell.test.tsx.snap b/src/components/datagrid/body/__snapshots__/data_grid_cell.test.tsx.snap index a652e4938d7..9267e0c7674 100644 --- a/src/components/datagrid/body/__snapshots__/data_grid_cell.test.tsx.snap +++ b/src/components/datagrid/body/__snapshots__/data_grid_cell.test.tsx.snap @@ -72,8 +72,7 @@ exports[`EuiDataGridCell renders 1`] = ` diff --git a/src/components/datagrid/body/data_grid_cell.tsx b/src/components/datagrid/body/data_grid_cell.tsx index 12af15fa800..6a0112c54e0 100644 --- a/src/components/datagrid/body/data_grid_cell.tsx +++ b/src/components/datagrid/body/data_grid_cell.tsx @@ -47,7 +47,6 @@ const EuiDataGridCellContent: FunctionComponent< setCellContentsRef: EuiDataGridCell['setCellContentsRef']; isExpanded: boolean; isDefinedHeight: boolean; - isFocused: boolean; ariaRowIndex: number; } > = memo( @@ -61,7 +60,6 @@ const EuiDataGridCellContent: FunctionComponent< ariaRowIndex, rowHeightUtils, isDefinedHeight, - isFocused, ...rest }) => { // React is more permissible than the TS types indicate @@ -93,8 +91,8 @@ const EuiDataGridCellContent: FunctionComponent< {...rest} /> - -

{'- '} {sortingScreenReaderText && ( - +

{sortingScreenReaderText}

)} diff --git a/upcoming_changelogs/6806.md b/upcoming_changelogs/6806.md new file mode 100644 index 00000000000..eb462c1e8ea --- /dev/null +++ b/upcoming_changelogs/6806.md @@ -0,0 +1,5 @@ +- Updated `EuiScreenReaderOnly` with a new `preventCopy` prop + +**Bug fixes** + +- Users attempting to copy and paste multiple cells from `EuiDataGrid` will no longer copy row/column data diff --git a/upcoming_changelogs/6817.md b/upcoming_changelogs/6817.md deleted file mode 100644 index 64a517b1d00..00000000000 --- a/upcoming_changelogs/6817.md +++ /dev/null @@ -1 +0,0 @@ -- Updated `EuiDataGrid` to only render screen reader text announcing cell position if the cell is currently focused. This should improve the ability to copy and paste multiple cells without SR text.