Skip to content
This repository has been archived by the owner on May 24, 2024. It is now read-only.

[Terra-Hyper-link] A11y Updates for Hyperlink #3747

Merged
merged 4 commits into from
Mar 17, 2023
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
12 changes: 5 additions & 7 deletions packages/terra-core-docs/CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,19 +3,17 @@
## Unreleased

* Added
* Added accessibility guide for `terra-hyperlink`
* Added Accessibility guideline for `terra-heading`
* Added examples for for `terra-list`

* Changed
* Added tests for `terra-list`.
* Fix second example on default Paginator doc page

* Added
* Added Accessibility Guide for `terra-section-header`
* Added accessibility guide for `terra-progress-bar`
* Added accessibility guide for `terra-avatar`

* Changed
* Added tests for `terra-list`.
* Fix second example on default Paginator doc page
* Updated example for `terra-hyperlink`
* Updated example for `terra-progress-bar`

## 1.23.0 - (March 1, 2023)
Expand Down
Original file line number Diff line number Diff line change
@@ -1,12 +1,11 @@
import { Badge } from 'terra-hyperlink/package.json?dev-site-package';

import DefaultHyperlink from './example/DefaultHyperlink?dev-site-example';
import DefaultHyperlinkButton from './example/DefaultHyperlinkButton?dev-site-example';
import Audio from './example/AudioHyperlink?dev-site-example';
import Disabled from './example/DisabledHyperlink?dev-site-example';
import Document from './example/DocumentHyperlink?dev-site-example';
import External from './example/ExternalHyperlink?dev-site-example';
import Image from './example/ImageHyperlink?dev-site-example';
import UnderlineHidden from './example/UnderlineHiddenHyperlink?dev-site-example';
import Video from './example/VideoHyperlink?dev-site-example';

import HyperlinkPropsTable from 'terra-hyperlink/src/Hyperlink?dev-site-props-table';
Expand All @@ -17,6 +16,13 @@ import HyperlinkPropsTable from 'terra-hyperlink/src/Hyperlink?dev-site-props-ta

The terra hyperlink component allows linking to other web pages, files, locations within the same page, email addresses, or any other URL.


## Terra Hyperlink Button

Similar to the standard hyperlinks, there are times when applications may need to use a button element and add a onClick function to navigate the user, instead of a traditional anchor `<a>` element with an `href` attribute for URL routing.

Terra Hyperlink Button can be created by providing callback / handler to `onClick` prop. Hyperlink Button is intended to communicate both visually to sighted users and to accessible users relying on assistive technology, that the interactive element is still a link, with the intention of navigating a user somewhere (contrasted with standard buttons which communicate that user can take an action).

## Getting Started

- Install with [npmjs](https://www.npmjs.com):
Expand All @@ -31,6 +37,7 @@ This component requires the following peer dependencies be installed in your app
|-|-|
| react | ^16.8.5 |
| react-dom | ^16.8.5 |
| react-intl | ^2.8.0 |

<!-- AUTO-GENERATED-CONTENT:END -->

Expand All @@ -46,13 +53,12 @@ import Hyperlink from 'terra-hyperlink';

## Examples
<DefaultHyperlink />
<Disabled />
<DefaultHyperlinkButton />
<External description="An external variant adds a custom icon to indicate the destination is external to the source." />
<Audio description="An audio variant adds a custom icon to indicate the content linked is audio." />
<Video description="A video variant adds a custom icon to indicate the content linked is a video." />
<Image description="An image variant adds a custom icon to indicate the content linked is an image." />
<Document description="A document variant adds a custom icon to indicate the content linked is document (.pdf, .doc, .xls, etc.)." />
<UnderlineHidden description="Option to hide the default underline when applied with theme-specific styling. Reserve for use when terra-hyperlink is applied in special situations within lists, other controls, or other components." />

## Hyperlink Props
<HyperlinkPropsTable />
Original file line number Diff line number Diff line change
@@ -0,0 +1,124 @@
import { Badge } from 'terra-hyperlink/package.json?dev-site-package';
import { Notice } from '@cerner/terra-docs';
import Whitespace from "../../common/layout-helpers/Whitespace";

<Badge />

# Accessibility Guide for Terra Hyperlink

<Notice variant="important" ariaLevel="2">

1. For each use of Terra Hyperlink, special care needs to be taken to ensure **the link text alone should convey the function and purpose of the link**.
2. Hyperlinks **must have a non-empty href** in order to be considered true links and to be accessible to keyboard users.

</Notice>

<Whitespace />

### Why is this important?

Hyperlinks are one of HTML's foundational elements, so making links accessible is essential. Hyperlinks are a vital tool for creating an intuitive user experience. However, because links are so fundamental to the functionality of web content, inaccessible or improperly implemented links can be a severe barrier to overall accessibility.

Accessible hyperlinks are critical to ensure all users can effectively understand and use them. For example:

- **Blind screen reader users** do not necessarily interact with pages in a linear fashion and can use hyperlinks out of context. They need the words within the link to be descriptive of purpose.
- **People using speech input software** require unique links to effectively activate the link they would like to follow.
- **Keyboard only users** navigate the page using only a keyboard. A visible keyboard focus is crucial to see where they are on the page.
- **People unable to perceive colors** need links to be perceivably distinct from the surrounding text. The use of underlines or other non-colored indicators will help users who may not see color.

<Whitespace newline={2} />

## Accessibility Considerations:

### Code Considerations

Terra Hyperlink can be used as: _Hyperlink_ and _Hyperlink Button_. The table below explains the difference between the two.

| Variant | Purpose | Example import |
| --- | --- | --- |
| Hyperlink | Represents a basic HTML hyperlink (a hypertext anchor) labeled by its contents. This variant must have an `href` prop. |
| Hyperlink Button | Represents a basic HTML button that triggers hyperlink navigation via the required `onClick` event handler prop. |

#### Developers must ensure the following code considerations:

- Do not override `role=link`.
- Use the component variant that best matches the intended usage.
- If non-unique link text must be used, e.g. `Learn more`, ensure the link is programmatically associated with other content that describes its purpose.
- Ensure that action is not taken on a hyperlink when it receives focus or when the focus leaves a hyperlink.
- Action on a hyperlink always occurs on the `onmouseup` or `onkeyup` event.
- Links must have a non-empty `href` to be considered proper links and accessible to keyboard users.
- Link Buttons must have an callback provided for `onClick` and must ignore `href` to be considered proper link buttons and accessible to keyboard users.
- Ensure that links with icons follow meaningful or decorative use guidelines.
- Meaningful icons must have appropriate alternative text in the `alt` attribute.
- Decorative icons must be marked as decorative.

<Whitespace />

### Content Considerations:

> It is most important for link text to make sense without the surrounding sentences or content. The link text alone should convey the function and purpose of the link. Link text should also be unique and easy to speak out loud.
>
> Consider these guidelines when writing link text:
>
> - Use text that is unique and descriptive of the link's purpose.
> - Avoid link text like “Click Here,” “More,” and “Read More.” These kinds of links can be confusing when a screen reader reads them out of context. These types of non-unique links prevent speech input users may from accurately activating them.
> - It is OK to link a full sentence, but avoid longer.
> - Use judgment when linking full URLs. When linking a URL, consider screen reader users that must listen to their device announcing the linked URL.
>
> _&nbsp;&nbsp;&mdash; excerpt from ["Usability & Web Accessibility Articles: Links"](https://usability.yale.edu/web-accessibility/articles/links)_[<sup>[1]</sup>](/components/cerner-terra-core-docs/hyperlink/accessibility-guide#linked-references)

<Whitespace newline={4} />

## Usability Expectations:

Users expect links to open a new page, take them somewhere on the page, or to download a file.

### Interaction Details

Mouse users expect the cursor to change to a hand with pointing finger when the link is hovered. Keyboard only users expect to see a visible keyboard focus indicator when the link is in focus.

### Keyboard Navigation

Hyperlinks have the following keyboard navigation expectations:

| Key/Sequence | Description |
|---|---|
|**Tab**| Puts Focus on the hyperlink. |
|**Enter**| Executes the link and moves focus to the link target. |

## Support Compliance

Terra is committed to ensuring its components provide maximum possible accessibility. However, using Terra components will not automatically make a product accessible.

Final responsibility lies with the consumers of Terra components &mdash; ensuring proper usage, engineers following correct implementation patterns, and authors crafting content that follows best practice guidance &mdash; to make a product fully accessible.

### WCAG Resources

#### Success Criteria

_Terra Hyperlink **must** meet the following success criteria:_

- [**1.1.1 Non-text Content**](https://www.w3.org/WAI/WCAG21/quickref/#non-text-content) - All non-text content that is presented to the user has a text alternative that serves the equivalent purpose, except for the situations listed\[...\]. (Level A)
- [**1.3.1 Info and Relationships**](https://www.w3.org/WAI/WCAG21/Understanding/info-and-relationships.html) - The intent of this Success Criterion is to ensure that information and relationships that are implied by visual or auditory formatting are preserved when the presentation format changes. For example, the presentation format changes when the content is read by a screen reader.
- [**2.4.4 Link Purpose**](https://www.w3.org/WAI/WCAG21/Understanding/link-purpose-in-context.html) - The purpose of each link can be determined from the link text alone or from the link text together with its programmatically determined link context, except where the purpose of the link would be ambiguous to users in general.
- [**2.5.3 Label in Name**](https://www.w3.org/WAI/WCAG21/Understanding/label-in-name.html) — For user interface components with labels that include text or images of text, the name contains the text that is presented visually.
- [**3.2.4 Consistent Identification**](https://www.w3.org/WAI/WCAG21/Understanding/consistent-identification.html) — Content creators must ensure icons used within hyperlinks are used consistently for the same function.

### Supported Features & Technology

- JAWS Support with Chrome (PC)
- NVDA Support with Chrome (PC)
- VoiceOver Support with Chrome, Safari (MAC)
- Mobile Touch Interactions with Screen Reader assistive technology
- Speech Input Interactions with assistive technology

### Partial Support & Requiring Further Enhancement

- None identified
- [Report a problem with this component on **GitHub**](https://github.com/cerner/terra-core/issues/new/choose)

_For more information about Accessibility Support with Terra — go to [Component Standards: Accessibility (A11y)](https://engineering.cerner.com/terra-ui/about/terra-ui/component-standards#accessibility-a11y)._

## Linked References:

1. Yale staff (2022) ["Usability & Web Accessibility Articles: Links"](https://usability.yale.edu/web-accessibility/articles/links). Yale. Retrieved 21 April 2022.
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import React from 'react';
import Hyperlink from 'terra-hyperlink';

export default () => <Hyperlink href="https://www.cerner.com" variant="audio">Audio hyperlink</Hyperlink>;
export default () => <Hyperlink href="https://www.cerner.com" variant="audio" text="Audio hyperlink" />;
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import React from 'react';
import Hyperlink from 'terra-hyperlink';

export default () => <Hyperlink href="https://www.cerner.com">Default hyperlink</Hyperlink>;
export default () => <Hyperlink href="https://www.cerner.com" text="Default hyperlink" />;
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
import React from 'react';
import HyperlinkButton from 'terra-hyperlink';

export default () => <HyperlinkButton onClick={() => {}} text="Default hyperlink button" />;

This file was deleted.

Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import React from 'react';
import Hyperlink from 'terra-hyperlink';

export default () => <Hyperlink href="https://www.cerner.com" variant="document">Document hyperlink</Hyperlink>;
export default () => <Hyperlink href="https://www.cerner.com" variant="document" text="Document hyperlink" />;
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import React from 'react';
import Hyperlink from 'terra-hyperlink';

export default () => <Hyperlink href="https://www.cerner.com" variant="external">External hyperlink</Hyperlink>;
export default () => <Hyperlink href="https://www.cerner.com" variant="external" text="External hyperlink" />;
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import React from 'react';
import Hyperlink from 'terra-hyperlink';

export default () => <Hyperlink href="https://www.cerner.com" variant="image">Image hyperlink</Hyperlink>;
export default () => <Hyperlink href="https://www.cerner.com" variant="image" text="Image hyperlink" />;

This file was deleted.

Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import React from 'react';
import Hyperlink from 'terra-hyperlink';

export default () => <Hyperlink href="https://www.cerner.com" variant="video">Video hyperlink</Hyperlink>;
export default () => <Hyperlink href="https://www.cerner.com" variant="video" text="Video hyperlink" />;
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,6 @@ import Hyperlink from 'terra-hyperlink';

export default () => (
<div role="main">
<Hyperlink id="link" href="https://www.cerner.com" variant="audio">Audio hyperlink</Hyperlink>
<Hyperlink id="link" href="https://www.cerner.com" variant="audio" text="Audio hyperlink" />
</div>
);
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,6 @@ import Hyperlink from 'terra-hyperlink';

export default () => (
<div role="main">
<Hyperlink id="link" href="https://www.cerner.com">Default hyperlink</Hyperlink>
<Hyperlink id="link" href="https://www.cerner.com" text="Default hyperlink" />
</div>
);
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,8 @@ import Hyperlink from 'terra-hyperlink';

export default () => (
<div role="main">
<Hyperlink href="https://www.cerner.com" isDisabled>Disabled hyperlink</Hyperlink>
<Hyperlink href="https://www.cerner.com" isDisabled text="Disabled hyperlink" />
<br />
<Hyperlink href="https://www.cerner.com" isDisabled variant="document">Disabled icon hyperlink</Hyperlink>
<Hyperlink href="https://www.cerner.com" isDisabled variant="document" text="Disabled icon hyperlink" />
</div>
);
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,6 @@ import Hyperlink from 'terra-hyperlink';

export default () => (
<div role="main">
<Hyperlink id="link" href="https://www.cerner.com" variant="document">Document hyperlink</Hyperlink>
<Hyperlink id="link" href="https://www.cerner.com" variant="document" text="Document hyperlink" />
</div>
);
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,6 @@ import Hyperlink from 'terra-hyperlink';

export default () => (
<div role="main">
<Hyperlink id="link" href="https://www.cerner.com" variant="external">External hyperlink</Hyperlink>
<Hyperlink id="link" href="https://www.cerner.com" variant="external" text="External hyperlink" />
</div>
);
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ import Hyperlink from 'terra-hyperlink';
export default () => (
<div role="main" id="link-example">
Example of a hyperlink inside some content that will wrap. With this, the icon should not wrap onto a separate line without the link text. I am a
<Hyperlink href="https://www.cerner.com" variant="document">Document hyperlink</Hyperlink>
<Hyperlink href="https://www.cerner.com" variant="document" text="Document hyperlink" />
{' '}
that is forced to wrap due to space constraints. My icon wraps with me.
</div>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,6 @@ import Hyperlink from 'terra-hyperlink';

export default () => (
<div role="main">
<Hyperlink id="link" href="https://www.cerner.com" variant="image">Image hyperlink</Hyperlink>
<Hyperlink id="link" href="https://www.cerner.com" variant="image" text="Image hyperlink" />
</div>
);
Original file line number Diff line number Diff line change
Expand Up @@ -4,13 +4,21 @@ import Hyperlink from 'terra-hyperlink';

export default () => (
<>
<Hyperlink id="link" href="https://www.cerner.com">Hyperlink</Hyperlink>
<Hyperlink id="link" href="https://www.cerner.com" text="Hyperlink" />
<br />
<br />
<Hyperlink id="link-button" onClick={() => {}} text="Hyperlink Button" />
<br />
<br />
<Button
text="Button 1 (Press to focus Hyperlink)"
onClick={() => { document.getElementById('link').focus(); }}
id="button1"
/>
<Button
text="Button 2 (Press to focus Hyperlink Button)"
onClick={() => { document.getElementById('link-button').focus(); }}
id="button2"
/>
</>
);
Original file line number Diff line number Diff line change
Expand Up @@ -7,15 +7,15 @@ const cx = classNames.bind(styles);

const ScaledHyperlink = () => (
<div role="main" className={cx('scaled-hyperlink')} id="link-example">
<Hyperlink href="https://www.cerner.com" variant="audio">Audio hyperlink</Hyperlink>
<Hyperlink href="https://www.cerner.com" variant="audio" text="Audio hyperlink" />
<br />
<Hyperlink href="https://www.cerner.com" variant="document">Document hyperlink</Hyperlink>
<Hyperlink href="https://www.cerner.com" variant="document" text="Document hyperlink" />
<br />
<Hyperlink href="https://www.cerner.com" variant="external">External hyperlink</Hyperlink>
<Hyperlink href="https://www.cerner.com" variant="external" text="External hyperlink" />
<br />
<Hyperlink href="https://www.cerner.com" variant="image">Image hyperlink</Hyperlink>
<Hyperlink href="https://www.cerner.com" variant="image" text="Image hyperlink" />
<br />
<Hyperlink href="https://www.cerner.com" variant="video">Video hyperlink</Hyperlink>
<Hyperlink href="https://www.cerner.com" variant="video" text="Video hyperlink" />
</div>
);

Expand Down
Loading