Skip to content

Commit

Permalink
add EuiSkipLink component
Browse files Browse the repository at this point in the history
  • Loading branch information
ryankeairns committed Mar 3, 2020
1 parent 06fe023 commit 7d8929f
Show file tree
Hide file tree
Showing 9 changed files with 155 additions and 20 deletions.
2 changes: 2 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
## [`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))
- `EuiButton` now has a single return statement ([#2954](https://github.com/elastic/eui/pull/2954))
- Added `isSortable` props to `EuiDataGridColumn` and `EuiDataGridSchemaDetector` to mark them as un-sortable ([#2952](https://github.com/elastic/eui/pull/2952))
- Converted `EuiForm` to TypeScript, added many missing `/form` Prop types ([#2896](https://github.com/elastic/eui/pull/2896))
Expand Down
65 changes: 51 additions & 14 deletions src-docs/src/views/accessibility/accessibility_example.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,27 +5,33 @@ import { renderToHtml } from '../../services';
import { GuideSectionTypes } from '../../components';

import {
EuiCallOut,
EuiCode,
EuiLink,
EuiKeyboardAccessible,
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 screenReaderOnlyHtml = renderToHtml(ScreenReaderOnly);
const screenReaderOnlySource = require('!!raw-loader!./screen_reader');

const skipLinkHtml = renderToHtml(SkipLink);
const skipLinkSource = require('!!raw-loader!./skip_link');

import { ScreenReaderOnlyDocsComponent } from './props';

export const AccessibilityExample = {
title: 'Accessibility',
sections: [
{
title: 'KeyboardAccessible',
title: 'Keyboard accessible',
source: [
{
type: GuideSectionTypes.JS,
Expand All @@ -38,17 +44,17 @@ 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 },
demo: <KeyboardAccessible />,
},
{
title: 'ScreenReaderOnly',
title: 'Screen reader only',
source: [
{
type: GuideSectionTypes.JS,
Expand All @@ -62,20 +68,51 @@ 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{' '}
{
Use the <EuiCode>EuiScreenReaderOnly</EuiCode> component to visually
hide elements while still allowing them to be read by screen
readers.
</p>
<EuiCallOut
color="warning"
iconType="accessibility"
title="WebAIM recommendation for screen reader-only content">
<p>
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.{' '}
<EuiLink href="http://webaim.org/techniques/css/invisiblecontent/">
http://webaim.org/techniques/css/invisiblecontent/
Learn more
</EuiLink>
}{' '}
for more information.
</p>
</p>
</EuiCallOut>
</div>
),
props: { EuiScreenReaderOnly: ScreenReaderOnlyDocsComponent },
props: {
EuiScreenReaderOnly: ScreenReaderOnlyDocsComponent,
},
demo: <ScreenReaderOnly />,
},
{
title: 'Skip to main content',
source: [
{
type: GuideSectionTypes.JS,
code: skipLinkSource,
},
{
type: GuideSectionTypes.HTML,
code: skipLinkHtml,
},
],
text: (
<p>
The <EuiCode>EuiSkipLink</EuiCode> component allows users to bypass
navigation and quickly reach the main content of the page.
</p>
),
props: { EuiSkipLink },
demo: <SkipLink />,
},
],
};
14 changes: 9 additions & 5 deletions src-docs/src/views/accessibility/screen_reader.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,9 @@ import { EuiTitle } from '../../../../src/components/title';
export default () => (
<div>
<EuiText>
<EuiTitle size="xxs">
<h4>Visually hide content</h4>
</EuiTitle>
<p>
<em>
Use a screenreader to verify that there is a second paragraph in this
Expand All @@ -27,16 +30,17 @@ export default () => (
</EuiTitle>
<p>
<em>
In certain cases, such as a <strong>Skip to content</strong> link, you
can use the <EuiCode>showOnFocus</EuiCode> prop to display
screenreader content upon focus. For example, tabbing to this section
with your keyboard will display a link.
In certain cases, you may want to display screen reader-only content
when it is in focus. This can be accoplished by adding the{' '}
<EuiCode>showOnFocus</EuiCode> prop. For example, tabbing through this
section with your keyboard will display a &lsquo;Skip to content
&rsquo; link:
</em>
</p>
<p>
This link is visible to all on focus:{' '}
<EuiScreenReaderOnly showOnFocus>
<a href="#">Skip content</a>
<a href="#">Skip to content</a>
</EuiScreenReaderOnly>
</p>
</EuiText>
Expand Down
34 changes: 34 additions & 0 deletions src-docs/src/views/accessibility/skip_link.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
import React from 'react';

import { EuiSkipLink } from '../../../../src/components/accessibility/skip_link';
import { EuiCallOut } from '../../../../src/components/call_out';
import { EuiText } from '../../../../src/components/text';
import { EuiPortal } from '../../../../src/components/portal';

export default () => (
<div>
<EuiText>
<p>
<em>
Tab out of the browser&apos;s address bar and a{' '}
<strong>Skip to main content</strong> link will appear on this page.
</em>
</p>
<EuiCallOut
size="s"
title="A functional &lsquo;Skip to main content&rsquo; link will be added to the EUI docs site once the URL format is updated."
iconType="iInCircle"
/>
</EuiText>
<EuiPortal>
<EuiSkipLink
destination="/#/utilities/accessibility"
label="Skip to content"
// TODO this tabIndex value won't be necessary once a real skip to content link is added to the EUI docs site.
// Adding the link is blocked until the new static site system (and non-hashed URL) is in place.
// eslint-disable-next-line jsx-a11y/tabindex-no-positive
tabIndex={1}
/>
</EuiPortal>
</div>
);
1 change: 1 addition & 0 deletions src/components/accessibility/_index.scss
Original file line number Diff line number Diff line change
@@ -1 +1,2 @@
@import 'screen_reader';
@import 'skip_link';
18 changes: 18 additions & 0 deletions src/components/accessibility/_skip_link.scss
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
.euiSkipLink {
@include euiSlightShadow;
display: block;
z-index: $euiZHeader + 1;
background-color: $euiColorPrimary;
color: $euiColorGhost;
font-size: $euiFontSizeS;
padding: $euiSizeM $euiSize;

&:focus,
&:hover {
position: fixed;
top: 0;
left: $euiSizeS;
border-radius: 0 0 $euiBorderRadius $euiBorderRadius;
text-decoration: underline;
}
}
1 change: 1 addition & 0 deletions src/components/accessibility/index.ts
Original file line number Diff line number Diff line change
@@ -1,2 +1,3 @@
export { EuiKeyboardAccessible } from './keyboard_accessible';
export { EuiScreenReaderOnly } from './screen_reader';
export { EuiSkipLink } from './skip_link';
34 changes: 34 additions & 0 deletions src/components/accessibility/skip_link.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
import React, { FunctionComponent } from 'react';
import classNames from 'classnames';
import { EuiScreenReaderOnly } from '../accessibility/screen_reader';

export interface EuiSkipLinkProps {
/**
* Typically an anchor id (e.g. `#a11yMainContent`), the value provided here
* equates to the href for the link.
*/
destination: string;

/**
* The text to be displayed as a link.
*/
label: string;

tabIndex?: number;
}

export const EuiSkipLink: FunctionComponent<EuiSkipLinkProps> = ({
destination,
label,
tabIndex = 0,
}) => {
const classes = classNames('euiSkipLink');

return (
<EuiScreenReaderOnly showOnFocus>
<a className={classes} href={destination} tabIndex={tabIndex}>
{label}
</a>
</EuiScreenReaderOnly>
);
};
6 changes: 5 additions & 1 deletion src/components/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,11 @@ export { EuiAspectRatio } from './aspect_ratio';

export { EuiAvatar } from './avatar';

export { EuiKeyboardAccessible, EuiScreenReaderOnly } from './accessibility';
export {
EuiKeyboardAccessible,
EuiScreenReaderOnly,
EuiSkipLink,
} from './accessibility';

export { EuiBadge, EuiBetaBadge, EuiNotificationBadge } from './badge';

Expand Down

0 comments on commit 7d8929f

Please sign in to comment.