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

Commit

Permalink
[terra-clinical-item-view] Accessibility guide (#916)
Browse files Browse the repository at this point in the history
Co-authored-by: ry061521 <[email protected]>
  • Loading branch information
RayGunY and ry061521 authored Sep 27, 2023
1 parent e8a7a3a commit 8d7c085
Show file tree
Hide file tree
Showing 6 changed files with 249 additions and 1 deletion.
1 change: 1 addition & 0 deletions packages/terra-clinical-item-view/CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@

* Added
* Added `trueColumn` prop to toggle between displaying in a two column layout by row or by column.
* Added accessibility guide.

## 4.11.0 - (September 21, 2023)

Expand Down
1 change: 1 addition & 0 deletions packages/terra-clinical-item-view/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@
"classnames": "^2.2.5",
"prop-types": "^15.5.8",
"terra-clinical-item-display": "^4.10.0",
"terra-heading": "^4.52.0",
"terra-icon": "^3.0.0",
"terra-mixins": "^1.0.0",
"terra-theme-context": "^1.0.0"
Expand Down
4 changes: 3 additions & 1 deletion packages/terra-clinical-item-view/src/ItemView.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ const AccessoryAlignments = {
const propTypes = {
/**
* The visual column layout in which to present the displays. One of `oneColumn`, `twoColumn`.
* When using the `twoColumn` layout, the displays are split between the columns by placing every other display into the second column.
*/
layout: PropTypes.oneOf(['oneColumn', 'twoColumns']),
/**
Expand Down Expand Up @@ -65,7 +66,8 @@ const propTypes = {
*/
endAccessory: PropTypes.node,
/**
* An array of terra-clinical-item-display's to be presented.
* An array of terra-clinical-item-displays to be presented.
* The Item View can only have 8 displays at a time, any additional displays passed in will be ignored.
*/
displays: PropTypes.arrayOf(PropTypes.element),
/**
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,205 @@
import { Badge } from 'terra-clinical-item-view/package.json?dev-site-package';
import { Notice } from "@cerner/terra-docs";
import ItemViewWithHeader from '../example/ItemViewWithHeader?dev-site-example';
import ItemViewTwoColumnWithHeader from '../example/ItemViewTwoColumnWithHeader?dev-site-example';

<Badge />

# Accessibility Guide for Terra Clinical Item View

## Why is this important?

Terra Clinical Item View allows you to create a view filled with information in the form of Clinical Item Displays. Improper usage of this component may prevent end users from understanding content and necessary context to interact with the page.

## Accessibility Considerations

#### General notes
- **Related information should be presented as close to each other as possible.** It is best practice to keep related information above or below its related counterparts.
- For example - presenting related information across from each other in the two column view can make it more difficult for users to understand that the information is related.
Reading by column from top to bottom is the more common way information is consumed visually, so when presenting this information by row between the two columns it might be confusing for assistive technology users and users in general.
- When passing in Clinical Item Displays, keep in mind that only 8 can be used within a view at a time. Any additional displays passed in will be ignored.
- When using the two column layout, the displays are split between the columns with every other display being moved to the right hand column.

----

### Code Considerations

#### Headings

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

It is **strongly** recommended to add a heading element above the implementation of the Clinical Item View component.
**A header not only acts as a label for the information being communicated to the end users, but also helps with visual and screenreader navigation throughout a page.**
The recommended way to implement this header is to utilize [Terra Heading](https://engineering.cerner.com/terra-ui/components/cerner-terra-core-docs/heading/about)
or the [Terra Clincial Header](https://engineering.cerner.com/terra-clinical/components/terra-clinical-header/clinical-header/clinical-header).

</Notice>

The Clinical Item View structure consists of an unordered list `<ul>` filled with list items. It is vital to include a header to ensure that the list of displays have proper context within the webpage.
For example - if an Item View contains contact information for a patient, a header should be added above the Item View with a label such as 'Contact Information' or 'Patient Contact Information'.

Best practices for implementing headers are as follows:
- Use one unique `<h1>` per page, above the main content it describes.
- Use lower headings to describe the content below. Do not use an HTML heading just to make the text appear bigger or stand out.
- Use heading levels like the index of a book: hierarchical.
- Do not choose a heading by its size, but by its level in the context of the content.
- Do not skip a heading level from the top down.

More information on heading standards can be found [here](https://www.a11yproject.com/posts/how-to-accessible-heading-structure/).

Here are some examples of implementing a Terra Heading element above an Item View.

##### Code Examples

<ItemViewWithHeader
title="ItemView - With Header"
/>
<ItemViewTwoColumnWithHeader
title="ItemView - Two Column Layout With Header"
/>

#### True Columns vs By Row

The two column layout for Clinical Item View has been updated to include an option for true columns instead of rows formatted to look like columns. This affects not only the programmatic layout but also the screenreader's behavior in how these displays are read.
The implementation of this is accomplished behind the `trueColumn` prop, which defaults to `false`, but should be set to `true` for accessibility purposes.

When `trueColumn` is `true`, screenreaders now read through the first column, top to bottom, before moving on to the second column and reading its displays from top to bottom.
This way of handling readout is better, as it is more natural for us to organize and read information in columns by reading them one at a time, top to bottom before reading through the next column.

It is strongly recommended to utilize the true two column layout mentioned above, but if needed you can keep the `trueColumn` prop as `false` which will use the previous 'by row' logic.

Some potential reasons to do this include:
- When `trueColumn` is `true`, the spacing and truncation of elements are slightly different due to the fact that we are now splitting the displays into actual programmatic columns.
Since the two columns are separate, they can't be resized on a row by row basis. Therefore, truncation may start a little earlier than it did before.
- When there is text wrapping/overflow for a display on one side - the 'by row' behavior adds blank newlines to the corresponding display in the opposite column.
Alternatively, when the true column layout is used and there is a display on one side with overflow, no blank lines are added below the display in the opposite column. The next display is rendered directly under the previous one with no blank lines.

All of that being said, the screenreader readout for the 'by row' formatting announces the first display from the first column and then jumps over to the first display in the second column.
It then jumps back to the first column and reads out the next display before moving back over to the second column and reading the next display. This pattern of reading displays by row continues until the last display is read.

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

The primary reason this 'by row' formatting is not recommended is because when information is displayed in columns, it is natural to read all of the information in the first column before moving on to the next one.
Assistive technology users should also have the opportunity to take in information this way.

</Notice>

How these views are used, what kind of information is being communicated, and how far apart the columns are - all of these contribute to how understandable the information is.
**It is always best practice in general to keep closely related information in the same column.**

#### Styling Override

Clincial Item View takes in Clinical Item Displays and by default the Item View has its own styling for these display elements.
However, the Item Displays have several different types of styling that can be applied to each individual display. Sometimes this styling conveys important information, like a display with a strikethrough.

To allow the usage of custom styling we have the `overrideDefaultStyling` prop.

This prop allows the user to override the Item View default styling and instead use the styling directly applied to the Item Displays.
If the override prop is set to `true` but the displays have no specific styling set, the displays will end up with the default Item Display styling.
More information on these styling types can be found on the Clincial Item Display [**page**](https://engineering.cerner.com/terra-clinical/components/terra-clinical-item-display/clinical-item-display/clinical-item-display).

#### Truncation Handling

There is an `isTruncated` prop for Clinical Item View, when this is set to `true` all displays and comments in the Item View can be truncated. Otherwise, the content wraps to a newline when isTruncated is `false`.
The actual Item Displays themselves also have an `isTruncated` prop. If the Item View has isTruncated set to `false` but some of the Item Displays have it set to `true`, only those specific displays will be truncated. The rest will have the word wrap behavior.

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

##### Truncated Text

Truncation of text can pose an accessibility concern if no method of disclosing the full text is available to end users.
When using `isTruncated`, consumers are responsible for providing a progressive disclosure pattern to disclose the full Item Display text in order to ensure that it is accessible for keyboard navigation users.

**There should always be a method of accessing the truncated information. If there is no way to progressively disclose the full content of the truncated information, then truncation should not be used.**

Some examples of progressive disclosure patterns that may be used to disclose truncated information include:
- Accordions
- Dialogs
- Popovers
- Show/Hide
- Split Views
- Toasts

The method of disclosure **must** be accessible via keyboard interactions.

Truncation should be avoided where it is not necessary. Certain content should **never** be truncated (i.e. medication names and dosages in menus where the user is selecting from a list of choices).

</Notice>

### Other Considerations

#### Clinical Item View Unordered List Structure

Displays in the Item View are rendered as list items inside a primary unordered list.
The structure is different for the different types of layouts - one column, two columns, and two columns by row. For an Item View with 8 displays, the structures are as follows:

<table>
<th>One Column</th><th>Two Columns</th><th>Two Columns By Row</th>
<tr>
<td valign="top">

Primary Unordered List
- List Item 1: Display 1
- List Item 2: Display 2
- List Item 3: Display 3
- List Item 4: Display 4
- List Item 5: Display 5
- List Item 6: Display 6
- List Item 7: Display 7
- List Item 8: Display 8

</td><td valign="top">

Primary Unordered List
- List Item 1: Column 1 as an unordered list
- List Item 1: Display 1
- List Item 2: Display 3
- List Item 3: Display 5
- List Item 4: Display 7
- List Item 2: Column 2 as an unordered List
- List Item 1: Display 2
- List Item 2: Display 4
- List Item 3: Display 6
- List Item 4: Display 8

</td><td valign="top">

Primary Unordered List
- List Item 1: Row 1 as an unordered list
- List Item 1: Display 1
- List Item 2: Display 2
- List Item 2: Row 2 as an unordered list
- List Item 1: Display 3
- List Item 2: Display 4
- List Item 3: Row 3 as an unordered list
- List Item 1: Display 5
- List Item 2: Display 6
- List Item 4: Row 4 as an unordered list
- List Item 1: Display 7
- List Item 2: Display 8

</td>
</tr>
</table>

## Support Compliance

Terra is committed to ensuring its components provide maximum possible accessibility. However, simply 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

- [**1.1.1 Non-text Content**](https://www.w3.org/WAI/WCAG21/Understanding/non-text-content) - All non-text content that is presented to the user has a text alternative that serves the equivalent purpose.
- [**1.3.1 Info and Relationships**](https://www.w3.org/WAI/WCAG21/Understanding/info-and-relationships) - Information, structure, and relationships conveyed through presentation can be programmatically determined or are available in text. (Level A)
- [**3.2.4 Consistent Identification**](https://www.w3.org/WAI/WCAG21/Understanding/consistent-identification) - Components that have the same functionality within a set of Web pages are identified consistently.
- [**4.1.2 Name, Role, Value**](https://www.w3.org/WAI/WCAG21/Understanding/name-role-value) - For all user interface components (including but not limited to: form elements, links and components generated by scripts), the name and role can be programmatically determined; states, properties, and values that can be set by the user can be programmatically set; and notification of changes to these items is available to user agents, including assistive technologies.

### Partial Support & Requiring Further Enhancement

- None identified
- [Report a problem with this component on **GitHub**](https://github.com/cerner/terra-clinical/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)._
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
import React from 'react';
import Heading from 'terra-heading';
import IconBriefcase from 'terra-icon/lib/icon/IconBriefcase';
import IconPerson from 'terra-icon/lib/icon/IconPerson';
import ItemView from 'terra-clinical-item-view';

const display1 = <ItemView.Display icon={<IconPerson />} iconAlignment="inline" text="Asif Khan" />;
const display2 = <ItemView.Display icon={<IconBriefcase />} iconAlignment="inline" text="Care Position: Primary" />;
const display3 = <ItemView.Display text="Room 100A" />;
const display4 = <ItemView.Display text="Acuity: 5" />;
const display5 = <ItemView.Display text="Start Time: 08-05-2016 12:00:00" />;
const display6 = <ItemView.Display text="End Time: 08-05-2016 16:00:00" />;
const displays = [display1, display2, display3, display4, display5, display6];

export default () => (
<div>
<Heading id="heading" level={5}>Patient Information</Heading>
<ItemView displays={displays} layout="twoColumns" />
</div>
);
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
import React from 'react';
import Heading from 'terra-heading';
import IconPerson from 'terra-icon/lib/icon/IconPerson';
import ItemView from 'terra-clinical-item-view';

const display1 = <ItemView.Display icon={<IconPerson />} iconAlignment="inline" text="Asif Khan" />;
const display2 = <ItemView.Display text="Care Position: Primary" />;
const display3 = <ItemView.Display text="Room 100A" />;
const display4 = <ItemView.Display text="Acuity: 5" />;
const display5 = <ItemView.Display text="Start Time: 08-05-2016 12:00:00" />;
const display6 = <ItemView.Display text="End Time: 08-05-2016 16:00:00" />;
const displays = [display1, display2, display3, display4, display5, display6];

export default () => (
<div>
<Heading id="heading" level={5}>Patient Information</Heading>
<ItemView displays={displays} />
</div>
);

0 comments on commit 8d7c085

Please sign in to comment.