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

[terra-hyperlink] Implement Accessibility changes (Part-1) #3605

Merged
merged 9 commits into from
Apr 11, 2022
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
8 changes: 8 additions & 0 deletions packages/terra-core-docs/CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,14 @@
## Unreleased

* Changed
* Updated hyperlink tests and examples.

## 1.13.4 - (March 15, 2022)

* Changed
* Minor dependency version bump

## 1.13.3 - (March 8, 2022)
* linter fixes.
* Spelling fixes for Image accessibility guide.

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,11 +2,9 @@ import { Badge } from 'terra-hyperlink/package.json?dev-site-package';

import DefaultHyperlink from './example/DefaultHyperlink?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 Down Expand Up @@ -46,13 +44,11 @@ import Hyperlink from 'terra-hyperlink';

## Examples
<DefaultHyperlink />
<Disabled />
<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
Expand Up @@ -4,6 +4,22 @@ import { Badge } from 'terra-hyperlink/package.json?dev-site-package';

# Terra Hyperlink Upgrade Guide

## Changes from version 2 to version 3

### Changes to Props

* `isDisabled` prop has been marked as **private**, allowing it to be used, but for very special circumstances or higher-order components.
* `isUnderlineHidden` prop has been marked as **private**, allowing it to be used, but for very special circumstances such as higher-order components that use hyperlink in approved ways without an underline.

#### Breaking Changes

* `children` prop has been replaced with the `text` prop which is of `string` type and is a `required` prop.

```diff
- <Hyperlink href="https://www.cerner.com">Default hyperlink</Hyperlink>
+ <Hyperlink href="https://www.cerner.com" text="Default hyperlink" />
```

## Changes from version 1 to version 2

### Changes to CSS Custom Properties
Expand Down
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
@@ -1,4 +1,4 @@
import React from 'react';
import Hyperlink from 'terra-hyperlink';

export default () => <Hyperlink href="https://www.cerner.com" isDisabled>Disabled hyperlink</Hyperlink>;
export default () => <Hyperlink text="Disabled hyperlink" href="https://www.cerner.com" isDisabled />;
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 text="Document hyperlink" href="https://www.cerner.com" variant="document" />;
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 text="External hyperlink" href="https://www.cerner.com" variant="external" />;
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 text="Image hyperlink" href="https://www.cerner.com" variant="image" />;
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" isUnderlineHidden>Underline hidden hyperlink</Hyperlink>;
export default () => <Hyperlink text="Underline hidden hyperlink" href="https://www.cerner.com" isUnderlineHidden />;
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 text="Video hyperlink" href="https://www.cerner.com" variant="video" />;
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 text="Audio hyperlink" id="link" href="https://www.cerner.com" variant="audio" />
</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 text="Default hyperlink" id="link" href="https://www.cerner.com" />
</div>
);

This file was deleted.

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 text="Document hyperlink" id="link" href="https://www.cerner.com" variant="document" />
</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 text="External hyperlink" id="link" href="https://www.cerner.com" variant="external" />
</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 text="Document hyperlink" href="https://www.cerner.com" variant="document" />
{' '}
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 text="Image hyperlink" id="link" href="https://www.cerner.com" variant="image" />
</div>
);
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
import React from 'react';
import Hyperlink from 'terra-hyperlink';

export default () => (
<div role="main">
<Hyperlink text="Disabled hyperlink" href="https://www.cerner.com" isDisabled />
<br />
<Hyperlink text="Disabled icon hyperlink" href="https://www.cerner.com" isDisabled variant="document" />
</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" isUnderlineHidden>Underline hidden hyperlink</Hyperlink>
<Hyperlink text="Underline hidden hyperlink" id="link" href="https://www.cerner.com" isUnderlineHidden />
</div>
);
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 text="Audio hyperlink" href="https://www.cerner.com" variant="audio" />
<br />
<Hyperlink href="https://www.cerner.com" variant="document">Document hyperlink</Hyperlink>
<Hyperlink text="Document hyperlink" href="https://www.cerner.com" variant="document" />
<br />
<Hyperlink href="https://www.cerner.com" variant="external">External hyperlink</Hyperlink>
<Hyperlink text="External hyperlink" href="https://www.cerner.com" variant="external" />
<br />
<Hyperlink href="https://www.cerner.com" variant="image">Image hyperlink</Hyperlink>
<Hyperlink text="Image hyperlink" href="https://www.cerner.com" variant="image" />
<br />
<Hyperlink href="https://www.cerner.com" variant="video">Video hyperlink</Hyperlink>
<Hyperlink text="Video hyperlink" href="https://www.cerner.com" variant="video" />
</div>
);

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,34 +7,34 @@ const cx = classNames.bind(styles);

const HyperlinkStates = () => (
<div role="main" className={cx('hyperlink-states')} id="link-example">
<Hyperlink href="https://my.cerner.com/?">hyperlink</Hyperlink>
<Hyperlink text="hyperlink" href="https://my.cerner.com/?" />
<br />
<br />
<Hyperlink href="https://my.cerner.com/?" className={cx('is-visited')}>visited hyperlink</Hyperlink>
<Hyperlink text="visited hyperlink" href="https://my.cerner.com/?" className={cx('is-visited')} />
<br />
<br />
<Hyperlink href="https://my.cerner.com/?" className={cx('is-hovered')}>hovered hyperlink</Hyperlink>
<Hyperlink text="hovered hyperlink" href="https://my.cerner.com/?" className={cx('is-hovered')} />
<br />
<br />
<Hyperlink href="https://my.cerner.com/?" className={cx('is-focused')}>focused hyperlink</Hyperlink>
<Hyperlink text="focused hyperlink" href="https://my.cerner.com/?" className={cx('is-focused')} />
<br />
<br />
<Hyperlink href="https://my.cerner.com/?" className={cx('is-active')}>active hyperlink</Hyperlink>
<Hyperlink text="active hyperlink" href="https://my.cerner.com/?" className={cx('is-active')} />
<br />
<br />
<Hyperlink href="https://my.cerner.com/?" variant="document">icon hyperlink</Hyperlink>
<Hyperlink text="icon hyperlink" href="https://my.cerner.com/?" variant="document" />
<br />
<br />
<Hyperlink href="https://my.cerner.com/?" className={cx('is-visited')} variant="document">icon visited hyperlink</Hyperlink>
<Hyperlink text="icon visited hyperlink" href="https://my.cerner.com/?" className={cx('is-visited')} variant="document" />
<br />
<br />
<Hyperlink href="https://my.cerner.com/?" className={cx('is-hovered')} variant="document">icon hovered hyperlink</Hyperlink>
<Hyperlink text="icon hovered hyperlink" href="https://my.cerner.com/?" className={cx('is-hovered')} variant="document" />
<br />
<br />
<Hyperlink href="https://my.cerner.com/?" className={cx('is-focused')} variant="document">icon focused hyperlink</Hyperlink>
<Hyperlink text="icon focused hyperlink" href="https://my.cerner.com/?" className={cx('is-focused')} variant="document" />
<br />
<br />
<Hyperlink href="https://my.cerner.com/?" className={cx('is-active')} variant="document">icon active hyperlink</Hyperlink>
<Hyperlink text="icon active hyperlink" href="https://my.cerner.com/?" className={cx('is-active')} variant="document" />
</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="video">Video hyperlink</Hyperlink>
<Hyperlink text="Video hyperlink" id="link" href="https://www.cerner.com" variant="video" />
</div>
);
4 changes: 4 additions & 0 deletions packages/terra-hyperlink/CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,12 @@
## Unreleased

* Changed
* `isDisabled` and `isUnderlineHidden` props have been marked as private.
* Updated jest snapshots.

* Breaking Changes
* `children` prop has been replaced by `text` prop.

## 2.51.2 - (January 4, 2022)

* Changed
Expand Down
34 changes: 23 additions & 11 deletions packages/terra-hyperlink/src/Hyperlink.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -40,20 +40,24 @@ const getHyperlinkIcon = (variant) => {
};

const propTypes = {
/**
* The content to display inside link.
*/
children: PropTypes.node,
/**
* Sets the href of the link.
*/
href: PropTypes.string,
/**
* @private
* Whether or not the link should be disabled.
*
* Accessibility best practices are to not use hyperlinks that are disabled.
* This prop has been marked as private, allowing it to be used, but for very special circumstances or higher-order components that need it in rare occasions.
*/
isDisabled: PropTypes.bool,
/**
* @private
* Whether or not the link should display an underline by default. Will still display an underline on hover and focus.
*
* Accessibility best practices are to always have hyperlinks display with an underline.
* This prop has been marked as private, allowing it to be used, but for very special circumstances such as higher-order components that use hyperlink in approved ways without an underline because interactive affordance is replaced with an alternate method.
*/
isUnderlineHidden: PropTypes.bool,
/**
Expand All @@ -76,6 +80,10 @@ const propTypes = {
* Callback function triggered when key is released.
*/
onKeyUp: PropTypes.func,
/**
* The content to display inside link.
*/
text: PropTypes.string.isRequired,
/**
* Sets the hyperlink variant. One of `default`, `external`, `image`, `video`, `audio`, `document`.
*/
Expand Down Expand Up @@ -128,7 +136,7 @@ class Hyperlink extends React.Component {

render() {
const {
children,
text,
isDisabled,
isUnderlineHidden,
variant,
Expand Down Expand Up @@ -156,8 +164,6 @@ class Hyperlink extends React.Component {
customProps.className,
);

const ComponentType = isDisabled ? 'span' : 'a';

let { target } = customProps; // Defaults to undefined if not set
let { rel } = customProps; // Defaults to undefined if not set

Expand All @@ -171,11 +177,17 @@ class Hyperlink extends React.Component {
rel = 'noopener noreferrer';
}

const attrsToDisable = {};
if (isDisabled) {
attrsToDisable.role = 'link';
attrsToDisable['aria-disabled'] = true;
}

return (
<ComponentType
<a
{...customProps}
{...attrsToDisable}
className={hyperlinkClasses}
aria-disabled={isDisabled}
onKeyDown={this.handleKeyDown}
onKeyUp={this.handleKeyUp}
onBlur={this.handleOnBlur}
Expand All @@ -185,9 +197,9 @@ class Hyperlink extends React.Component {
target={target}
rel={rel}
>
{children}
{text}
{getHyperlinkIcon(variant)}
</ComponentType>
</a>
);
}
}
Expand Down
2 changes: 1 addition & 1 deletion packages/terra-hyperlink/src/Hyperlink.module.scss
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@
cursor: pointer;
display: inline-block; // prevents variant icon from breaking onto its own line
outline: none;
text-decoration: var(--terra-hyperlink-text-decoration, none);
text-decoration: var(--terra-hyperlink-text-decoration, underline);

&:visited,
&.is-visited {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
:local {
.clinical-lowlight-theme {
--terra-hyperlink-color: #007ee0;
--terra-hyperlink-text-decoration: none;
--terra-hyperlink-text-decoration: underline;
--terra-hyperlink-visited-color: #007ee0;
--terra-hyperlink-visited-focus-color: #007ee0;
--terra-hyperlink-hover-background-color: transparent;
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
:local {
.orion-fusion-theme {
--terra-hyperlink-color: #0065a3;
--terra-hyperlink-text-decoration: none;
--terra-hyperlink-text-decoration: underline;
--terra-hyperlink-visited-color: #0065a3;
--terra-hyperlink-visited-focus-color: #004c76;
--terra-hyperlink-hover-background-color: transparent;
Expand Down
Loading