Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[EuiScreenReaderOnly] Add preventCopy prop #6806

Closed
wants to merge 7 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
39 changes: 37 additions & 2 deletions src-docs/src/views/accessibility/accessibility_example.js
Original file line number Diff line number Diff line change
Expand Up @@ -15,13 +15,15 @@ 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';

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');
Expand Down Expand Up @@ -74,7 +76,8 @@ export const AccessibilityExample = {
<EuiSpacer />
<p>
<em>
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.
</em>
</p>
</>
Expand All @@ -87,6 +90,38 @@ export const AccessibilityExample = {
</EuiScreenReaderOnly>`,
demo: <ScreenReaderOnly />,
},
{
source: [
{
type: GuideSectionTypes.JS,
code: screenReaderPreventCopySource,
},
],
text: (
<>
<h3 id="preventCopy">Preventing users from copying hidden text</h3>
<p>
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 <EuiCode>preventCopy</EuiCode>{' '}
prop.
</p>
<p>
<em>
Select and copy both lines in the below demo and confirm only the
visible lines are copied.
</em>
</p>
</>
),
props: {
EuiScreenReaderOnly,
},
snippet: `<EuiScreenReaderOnly preventCopy>
<!-- visually hidden content, cannot be selected or copied -->
</EuiScreenReaderOnly>`,
demo: <ScreenReaderPreventCopy />,
},
{
source: [
{
Expand All @@ -96,7 +131,7 @@ export const AccessibilityExample = {
],
text: (
<>
<h3>Showing on focus</h3>
<h3 id="showOnFocus">Showing on focus</h3>
<p>
If the wrapped element <strong>is focusable</strong>, you must use
the <EuiCode>showOnFocus</EuiCode> prop to visibly show the element
Expand Down
16 changes: 16 additions & 0 deletions src-docs/src/views/accessibility/screen_reader_prevent_copy.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
import React from 'react';

import { EuiScreenReaderOnly, EuiText } from '../../../../src/components';

export default () => (
<EuiText>
<p>This is the first paragraph. It is visible and copyable.</p>
<EuiScreenReaderOnly preventCopy>
<p>
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.
</p>
</EuiScreenReaderOnly>
<p>This is the third paragraph. It is visible and copyable.</p>
</EuiText>
);
Original file line number Diff line number Diff line change
Expand Up @@ -4,21 +4,29 @@ exports[`EuiScreenReaderOnly adds an accessibility class to a child element and
<p
class="foo bar emotion-euiScreenReaderOnly"
>
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.
</p>
`;

exports[`EuiScreenReaderOnly adds an accessibility class to a child element when used with no props 1`] = `
<p
class="emotion-euiScreenReaderOnly"
>
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.
</p>
`;

exports[`EuiScreenReaderOnly will show on focus 1`] = `
exports[`EuiScreenReaderOnly preventCopy 1`] = `
<span
class="emotion-euiScreenReaderOnly-preventCopy"
>
Text
</span>
`;

exports[`EuiScreenReaderOnly showOnFocus 1`] = `
<a
class="emotion-euiScreenReaderOnly"
class="emotion-euiScreenReaderOnly-showOnFocus"
href="#"
>
Link
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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;
`,
});
Original file line number Diff line number Diff line change
Expand Up @@ -17,19 +17,20 @@ describe('EuiScreenReaderOnly', () => {
const $paragraph = render(
<EuiScreenReaderOnly>
<p>
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.
</p>
</EuiScreenReaderOnly>
);

expect($paragraph).toMatchSnapshot();
});

test('and combines other classNames (foo, bar) given as props on the child', () => {
const $paragraph = render(
<EuiScreenReaderOnly>
<p className="foo bar">
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.
</p>
</EuiScreenReaderOnly>
Expand All @@ -39,7 +40,7 @@ describe('EuiScreenReaderOnly', () => {
});
});

test('will show on focus', () => {
test('showOnFocus', () => {
const component = render(
<EuiScreenReaderOnly showOnFocus>
<a href="#">Link</a>
Expand All @@ -48,4 +49,14 @@ describe('EuiScreenReaderOnly', () => {

expect(component).toMatchSnapshot();
});

test('preventCopy', () => {
const component = render(
<EuiScreenReaderOnly preventCopy>
<span>Text</span>
</EuiScreenReaderOnly>
);

expect(component).toMatchSnapshot();
});
});
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
exports[`EuiSkipLink is rendered 1`] = `
<a
aria-label="aria-label"
class="euiSkipLink testClass1 testClass2 emotion-euiButtonDisplay-s-defaultMinWidth-s-fill-primary-euiSkipLink-euiScreenReaderOnly"
class="euiSkipLink testClass1 testClass2 emotion-euiButtonDisplay-s-defaultMinWidth-s-fill-primary-euiSkipLink-euiScreenReaderOnly-showOnFocus"
data-test-subj="test subject string"
href="#somewhere"
rel="noreferrer"
Expand All @@ -22,7 +22,7 @@ exports[`EuiSkipLink is rendered 1`] = `

exports[`EuiSkipLink props position absolute is rendered 1`] = `
<a
class="euiSkipLink emotion-euiButtonDisplay-s-defaultMinWidth-s-fill-primary-euiSkipLink-absolute-euiScreenReaderOnly"
class="euiSkipLink emotion-euiButtonDisplay-s-defaultMinWidth-s-fill-primary-euiSkipLink-absolute-euiScreenReaderOnly-showOnFocus"
href="#somewhere"
rel="noreferrer"
>
Expand All @@ -34,7 +34,7 @@ exports[`EuiSkipLink props position absolute is rendered 1`] = `

exports[`EuiSkipLink props position fixed is rendered 1`] = `
<a
class="euiSkipLink emotion-euiButtonDisplay-s-defaultMinWidth-s-fill-primary-euiSkipLink-fixed-euiScreenReaderOnly"
class="euiSkipLink emotion-euiButtonDisplay-s-defaultMinWidth-s-fill-primary-euiSkipLink-fixed-euiScreenReaderOnly-showOnFocus"
href="#somewhere"
rel="noreferrer"
tabindex="0"
Expand All @@ -47,7 +47,7 @@ exports[`EuiSkipLink props position fixed is rendered 1`] = `

exports[`EuiSkipLink props position static is rendered 1`] = `
<a
class="euiSkipLink emotion-euiButtonDisplay-s-defaultMinWidth-s-fill-primary-euiSkipLink-euiScreenReaderOnly"
class="euiSkipLink emotion-euiButtonDisplay-s-defaultMinWidth-s-fill-primary-euiSkipLink-euiScreenReaderOnly-showOnFocus"
href="#somewhere"
rel="noreferrer"
>
Expand All @@ -59,7 +59,7 @@ exports[`EuiSkipLink props position static is rendered 1`] = `

exports[`EuiSkipLink props tabIndex is rendered 1`] = `
<a
class="euiSkipLink emotion-euiButtonDisplay-s-defaultMinWidth-s-fill-primary-euiSkipLink-euiScreenReaderOnly"
class="euiSkipLink emotion-euiButtonDisplay-s-defaultMinWidth-s-fill-primary-euiSkipLink-euiScreenReaderOnly-showOnFocus"
href="#somewhere"
rel="noreferrer"
tabindex="-1"
Expand Down
Loading