Skip to content

Commit

Permalink
Add showOnFocus prop to EuiScreenReader Only & Add EuiSkipLink (elast…
Browse files Browse the repository at this point in the history
…ic#2976)

* adds showOnFocus prop

* add EuiSkipLink component

* address feedback, add fixedToTop prop

* addressing feedback

* use EuiButton

* Updated some props to be enums and extended EuiButton type and added tests

* add snippets, as one does

* remove tabIndex from fixed example

* remove portal from docs example

Co-authored-by: Caroline Horn <[email protected]>
  • Loading branch information
ryankeairns and cchaos authored Mar 5, 2020
1 parent 8c3ca5f commit 4a27d09
Show file tree
Hide file tree
Showing 17 changed files with 455 additions and 55 deletions.
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

0 comments on commit 4a27d09

Please sign in to comment.