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

Add showOnFocus prop to EuiScreenReader Only & Add EuiSkipLink #2976

Merged
merged 9 commits into from
Mar 5, 2020
Merged
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
3 changes: 3 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,8 @@
## [`master`](https://github.com/elastic/eui/tree/master)

- Added `showOnFocus` prop to `EuiScreenReaderOnly` to force display on keyboard focus ([#2976](https://github.com/elastic/eui/pull/2976))
- Added `EuiSkipLink` component ([#2976](https://github.com/elastic/eui/pull/2976))

**Bug Fixes**

- Fixed `EuiDataGrid`'s sort popover to behave properly on mobile screens ([#2979](https://github.com/elastic/eui/pull/2979))
Expand Down
105 changes: 85 additions & 20 deletions src-docs/src/views/accessibility/accessibility_example.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,26 +5,56 @@ import { renderToHtml } from '../../services';
import { GuideSectionTypes } from '../../components';

import {
EuiCallOut,
EuiCode,
EuiLink,
EuiKeyboardAccessible,
EuiScreenReaderOnly,
EuiSkipLink,
} from '../../../../src/components';

import KeyboardAccessible from './keyboard_accessible';
import ScreenReaderOnly from './screen_reader';
import SkipLink from './skip_link';

const keyboardAccessibleSource = require('!!raw-loader!./keyboard_accessible');
const keyboardAccessibleHtml = renderToHtml(KeyboardAccessible);
const keyboardAccessibleSnippet = `<EuiKeyboardAccessible>
<!-- interactive child element -->
</EuiKeyboardAccessible>`;

const screenReaderOnlyHtml = renderToHtml(ScreenReaderOnly);
const screenReaderOnlySource = require('!!raw-loader!./screen_reader');
const screenReaderOnlySnippet = [
`<EuiScreenReaderOnly>
<!-- visually hidden content -->
</EuiScreenReaderOnly>
`,
`<EuiScreenReaderOnly showOnFocus>
<!-- visually hidden content, displayed on focus -->
</EuiScreenReaderOnly>
`,
];

const skipLinkHtml = renderToHtml(SkipLink);
const skipLinkSource = require('!!raw-loader!./skip_link');
const skipLinkSnippet = [
`<EuiSkipLink destinationId="myAnchorId">
Skip to content
</EuiSkipLink>
`,
`<EuiSkipLink destinationId="myAnchorId" position="fixed">
Skip to main content
</EuiSkipLink>
`,
];

import { ScreenReaderOnlyDocsComponent } from './props';

export const AccessibilityExample = {
title: 'Accessibility',
sections: [
{
title: 'KeyboardAccessible',
title: 'Keyboard accessible',
source: [
{
type: GuideSectionTypes.JS,
Expand All @@ -37,17 +67,18 @@ export const AccessibilityExample = {
],
text: (
<p>
You can make interactive elements keyboard-accessible with this
component. This is necessary for non-button elements and{' '}
<EuiCode>a</EuiCode> tags without
You can make interactive elements keyboard-accessible with the{' '}
<EuiCode>EuiKeyboardAccessible</EuiCode> component. This is necessary
for non-button elements and <EuiCode>a</EuiCode> tags without{' '}
<EuiCode>href</EuiCode> attributes.
</p>
),
props: { EuiKeyboardAccessible },
snippet: keyboardAccessibleSnippet,
demo: <KeyboardAccessible />,
},
{
title: 'ScreenReaderOnly',
title: 'Screen reader only',
source: [
{
type: GuideSectionTypes.JS,
Expand All @@ -61,24 +92,58 @@ export const AccessibilityExample = {
text: (
<div>
<p>
This class can be useful to add accessibility to older designs that
are still in use, but it shouldn&rsquo;t be a permanent solution.
See{' '}
{
<EuiLink href="http://webaim.org/techniques/css/invisiblecontent/">
http://webaim.org/techniques/css/invisiblecontent/
</EuiLink>
}{' '}
for more information.
</p>
<p>
Use a screenreader to verify that there is a second paragraph in
this example:
Use the <EuiCode>EuiScreenReaderOnly</EuiCode> component to visually
hide elements while still allowing them to be read by screen
readers. In certain cases, you may want to use the{' '}
<EuiCode>showOnFocus</EuiCode> prop to display screen reader-only
content when in focus.
</p>
<EuiCallOut
color="warning"
iconType="accessibility"
title="WebAIM recommendation for screen reader-only content">
<p>
&quot;In most cases, if content (particularly content that
provides functionality or interactivity) is important enough to
provide to screen reader users, it should probably be made
available to all users.&quot;{' '}
<EuiLink
href="http://webaim.org/techniques/css/invisiblecontent/"
external>
Learn more about invisible content
</EuiLink>
</p>
</EuiCallOut>
</div>
),
props: { EuiScreenReaderOnly },
props: {
EuiScreenReaderOnly: ScreenReaderOnlyDocsComponent,
},
snippet: screenReaderOnlySnippet,
demo: <ScreenReaderOnly />,
},
{
title: 'Skip link',
source: [
{
type: GuideSectionTypes.JS,
code: skipLinkSource,
},
{
type: GuideSectionTypes.HTML,
code: skipLinkHtml,
},
],
text: (
<p>
The <EuiCode>EuiSkipLink</EuiCode> component allows users to bypass
navigation, or ornamental elements, and quickly reach the main content
of the page.
</p>
),
props: { EuiSkipLink },
snippet: skipLinkSnippet,
demo: <SkipLink />,
},
],
};
60 changes: 35 additions & 25 deletions src-docs/src/views/accessibility/keyboard_accessible.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import React from 'react';

import { EuiKeyboardAccessible } from '../../../../src/components';
import { EuiText } from '../../../../src/components/text';

// For custom components, we just need to make sure they delegate props to their rendered root
// element, e.g. onClick, tabIndex, and role.
Expand All @@ -10,33 +11,42 @@ const CustomComponent = ({ children, ...rest }) => (

export default () => (
<div>
<EuiKeyboardAccessible>
<div onClick={() => window.alert('Div clicked')}>Click this div</div>
</EuiKeyboardAccessible>
<EuiText>
<EuiKeyboardAccessible>
<div onClick={() => window.alert('Div clicked')}>Click this div</div>
</EuiKeyboardAccessible>

<EuiKeyboardAccessible>
<a className="euiLink" onClick={() => window.alert('Anchor tag clicked')}>
Click this anchor tag
</a>
</EuiKeyboardAccessible>
<EuiKeyboardAccessible>
<a
className="euiLink"
onClick={() => window.alert('Anchor tag clicked')}>
Click this anchor tag
</a>
</EuiKeyboardAccessible>

<EuiKeyboardAccessible>
<CustomComponent onClick={() => window.alert('Custom component clicked')}>
Click this custom component
</CustomComponent>
</EuiKeyboardAccessible>
<EuiKeyboardAccessible>
<CustomComponent
onClick={() => window.alert('Custom component clicked')}>
Click this custom component
</CustomComponent>
</EuiKeyboardAccessible>

<EuiKeyboardAccessible>
<div onClick={() => window.alert('Outer EuiKeyboardAccessible clicked')}>
This EuiKeyboardAccessible contains another EuiKeyboardAccessible&nbsp;
<EuiKeyboardAccessible>
<a
className="euiLink"
onClick={() => window.alert('Inner EuiKeyboardAccessible clicked')}>
Clicking this inner one should call both onClick handlers
</a>
</EuiKeyboardAccessible>
</div>
</EuiKeyboardAccessible>
<EuiKeyboardAccessible>
<div
onClick={() => window.alert('Outer EuiKeyboardAccessible clicked')}>
This EuiKeyboardAccessible contains another
EuiKeyboardAccessible&nbsp;
<EuiKeyboardAccessible>
<a
className="euiLink"
onClick={() =>
window.alert('Inner EuiKeyboardAccessible clicked')
}>
Clicking this inner one should call both onClick handlers
</a>
</EuiKeyboardAccessible>
</div>
</EuiKeyboardAccessible>
</EuiText>
</div>
);
6 changes: 6 additions & 0 deletions src-docs/src/views/accessibility/props.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
import React, { FunctionComponent } from 'react';
import { EuiScreenReaderOnlyProps } from '../../../../src/components/accessibility/screen_reader';

export const ScreenReaderOnlyDocsComponent: FunctionComponent<
EuiScreenReaderOnlyProps
> = () => <div />;
47 changes: 41 additions & 6 deletions src-docs/src/views/accessibility/screen_reader.tsx
Original file line number Diff line number Diff line change
@@ -1,16 +1,51 @@
import React from 'react';

import { EuiScreenReaderOnly } from '../../../../src/components/accessibility/screen_reader';
import { EuiCallOut } from '../../../../src/components/call_out';
import { EuiText } from '../../../../src/components/text';
import { EuiTitle } from '../../../../src/components/title';
import { EuiLink } from '../../../../src/components/link';

export default () => (
<div>
<p>This is the first paragraph. It is visible to all.</p>
<EuiScreenReaderOnly>
<EuiText>
<EuiTitle size="xxs">
<h4>Visually hide content</h4>
</EuiTitle>
<p>
This is the second paragraph. It is hidden for sighted users but visible
to screen readers.
<em>
Use a screenreader to verify that there is a second paragraph in this
example:
</em>
</p>
</EuiScreenReaderOnly>
<p>This is the third paragraph. It is visible to all.</p>
<p>This is the first paragraph. It is visible to all.</p>
<EuiScreenReaderOnly>
<p>
This is the second paragraph. It is hidden for sighted users but
visible to screen readers.
</p>
</EuiScreenReaderOnly>
<p>This is the third paragraph. It is visible to all.</p>
<EuiTitle size="xxs">
<h4>Show on focus</h4>
</EuiTitle>
<p>
<em>
Tab through this section with your keyboard to display a &lsquo;Skip
navigation&rsquo; link:
</em>
</p>
<p>
This link is visible to all on focus:{' '}
<EuiScreenReaderOnly showOnFocus>
<EuiLink href="#">Skip navigation</EuiLink>
</EuiScreenReaderOnly>
</p>
<EuiCallOut
size="s"
title="For a fully styled &lsquo;Skip to main content&rsquo; solution, see the EuiSkipLink component in the next section."
iconType="iInCircle"
/>
</EuiText>
</div>
);
61 changes: 61 additions & 0 deletions src-docs/src/views/accessibility/skip_link.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
import React, { Fragment, useState } from 'react';

import { EuiSkipLink } from '../../../../src/components/accessibility/skip_link';
import { EuiCallOut } from '../../../../src/components/call_out';
import { EuiText } from '../../../../src/components/text';
import { EuiSpacer } from '../../../../src/components/spacer';
import { EuiSwitch } from '../../../../src/components/form/switch';

export default () => {
const [isFixed, setFixed] = useState(false);

return (
<Fragment>
<EuiText>
{isFixed ? (
<p>
<em>
Tab through this section and a fixed{' '}
<strong>Skip to main content </strong> link will appear atop this
page.
</em>
</p>
) : (
<p>
<em>
Tab through this section and a <strong>Skip to content</strong>{' '}
link will appear below.
</em>
</p>
)}
</EuiText>
<EuiSpacer />
<EuiSwitch
label="Fix link to top of screen"
checked={isFixed}
onChange={e => setFixed(e.target.checked)}
/>
<EuiSpacer />
{isFixed ? (
<Fragment>
<EuiSkipLink
destinationId="/utilities/accessibility"
position="fixed">
Skip to main content
</EuiSkipLink>
<EuiCallOut
size="s"
title="A functional &lsquo;Skip to main content&rsquo; link will be added to the EUI docs site once our URL format is updated."
iconType="iInCircle"
/>
</Fragment>
) : (
<EuiSkipLink
destinationId="/utilities/accessibility"
data-test-subj="skip-link-demo-subj">
Skip to content
</EuiSkipLink>
)}
</Fragment>
);
};
Original file line number Diff line number Diff line change
Expand Up @@ -15,3 +15,12 @@ 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.
</p>
`;

exports[`EuiScreenReaderOnly will show on focus 1`] = `
<a
class="euiScreenReaderOnly--showOnFocus"
href="#"
>
Link
</a>
`;
Loading