diff --git a/packages/terra-badge/CHANGELOG.md b/packages/terra-badge/CHANGELOG.md index 7f99c277b82..4c6894590c8 100644 --- a/packages/terra-badge/CHANGELOG.md +++ b/packages/terra-badge/CHANGELOG.md @@ -2,6 +2,10 @@ ## Unreleased +* Changed + * Update props description in props table. + * Removed hidden text to announce the intent of the badge. + ## 3.58.0 - (October 16, 2023) * Added diff --git a/packages/terra-badge/src/Badge.jsx b/packages/terra-badge/src/Badge.jsx index 00177f3fec0..dcd991b10c7 100644 --- a/packages/terra-badge/src/Badge.jsx +++ b/packages/terra-badge/src/Badge.jsx @@ -38,6 +38,9 @@ const propTypes = { icon: PropTypes.element, /** * Sets the badge color scheme. One of `default`, `primary`, `secondary`, `positive`, `negative`, `warning`, `info`. + * + * ![IMPORTANT](https://badgen.net/badge/UX/Accessibility/blue) + * Follow the accessibility guidance for color to ensure color is not the only method used to convey information. */ intent: PropTypes.oneOf(['default', 'primary', 'secondary', 'info', 'warning', 'positive', 'negative']), /** @@ -55,11 +58,16 @@ const propTypes = { size: PropTypes.oneOf(['tiny', 'small', 'medium', 'large', 'huge']), /** * Sets the badge text. + * + * ![IMPORTANT](https://badgen.net/badge/UX/Accessibility/blue) + * It is best practice to always use text. Use text that conveys the meaning or purpose of the badge. */ text: PropTypes.string, /** - * Text that describes the badge to a screen reader. Use this - * for creating an accessible badge. + * Additional text that can be visually hidden but supports people that use assistive technologies like screen readers. + * + * ![IMPORTANT](https://badgen.net/badge/UX/Accessibility/blue) + * Follow the Accessibility Guidance for visually hidden text above to better understand when to use this prop. */ visuallyHiddenText: PropTypes.string, }; @@ -98,9 +106,8 @@ const Badge = ({ ); const textContent = text ? {text} : null; - const intentText = intent !== BadgeIntent.DEFAULT ? : null; const visuallyHiddenTextContent = visuallyHiddenText ? : null; - const content = isReversed ? [intentText, textContent, visuallyHiddenTextContent, icon, customProps.children] : [icon, intentText, textContent, visuallyHiddenTextContent, customProps.children]; + const content = isReversed ? [textContent, visuallyHiddenTextContent, icon, customProps.children] : [icon, textContent, visuallyHiddenTextContent, customProps.children]; return React.createElement('span', { ...customProps, className: badgeClassNames }, ...content); }; diff --git a/packages/terra-badge/tests/jest/__snapshots__/Badge.test.jsx.snap b/packages/terra-badge/tests/jest/__snapshots__/Badge.test.jsx.snap index 711dfedc743..0bfb97435b2 100644 --- a/packages/terra-badge/tests/jest/__snapshots__/Badge.test.jsx.snap +++ b/packages/terra-badge/tests/jest/__snapshots__/Badge.test.jsx.snap @@ -97,9 +97,6 @@ exports[`should render a badge component in the order, text and icon with info i - @@ -128,9 +125,6 @@ exports[`should render a badge component with icon and warning intent 1`] = ` Test icon - `; @@ -150,9 +144,6 @@ exports[`should render a badge component with text and secondary intent 1`] = ` - diff --git a/packages/terra-core-docs/CHANGELOG.md b/packages/terra-core-docs/CHANGELOG.md index 43cae330acf..cc303601335 100644 --- a/packages/terra-core-docs/CHANGELOG.md +++ b/packages/terra-core-docs/CHANGELOG.md @@ -4,6 +4,7 @@ * Added * Added about page for `TagList`. + * Updated doc examples for `terra-badge`. ## 1.49.0 - (November 3, 2023) diff --git a/packages/terra-core-docs/src/terra-dev-site/doc/badge/About.1.doc.mdx b/packages/terra-core-docs/src/terra-dev-site/doc/badge/About.1.doc.mdx index a9b45c3b4fb..6446812600a 100644 --- a/packages/terra-core-docs/src/terra-dev-site/doc/badge/About.1.doc.mdx +++ b/packages/terra-core-docs/src/terra-dev-site/doc/badge/About.1.doc.mdx @@ -1,5 +1,6 @@ import { Badge } from 'terra-badge/package.json?dev-site-package'; +import { Notice } from "@cerner/terra-docs"; import BadgeIntent from './example/BadgeIntent?dev-site-example'; import BadgeSize from './example/BadgeSize?dev-site-example'; import BadgeIcon from './example/BadgeIcon?dev-site-example'; @@ -8,11 +9,12 @@ import BadgeInTable from './example/BadgeInTable?dev-site-example'; import BadgePropsTable from 'terra-badge/lib/Badge?dev-site-props-table'; +import BadgeInDoc from './example/BadgeInDoc'; # Terra Badge -The badge component displays content classification. +The badge component displays content classification. Badges are used to represent counts (e.g., number of unread items) or to represent a status. If you need a selectable annotation consider using [`Terra Popup`](https://engineering.cerner.com/terra-ui/components/cerner-terra-framework-docs/popup/popup) or another control instead. ## Getting Started @@ -43,6 +45,60 @@ The Badge component must be composed inside the [Base][1] component with a local import Badge from 'terra-badge'; ``` + + +### Accessibility Guidance: Badge Color +To implement an accessible terra badge: + +- Ensure the words used within the badge (the text provided as text prop) or the icon conveys the purpose of the badge. Badge color must always be used as a secondary or supportive method to understand meaning. + - Color must never be the only method used to convey badge meaning. + - A good example where words convey the meaning and color is supportive: + - Heart Rate: + - Blood Pressure: + - A bad example where color alone is used to convey meaning: + - + - +- When using the intent prop to set badge colors, choose the appropriate intent prop type value that matches the purpose and intent of the badge(s). And, be consistent in the use of color per the meaning of the words. + - Do not use one color with different meanings. For example, do not have 2 or more badges using the same color each with a different meaning. + +### Accessibility Guidance: Visually Hidden Text +Because Badges should always use text that provides the proper context and meaning of the badge, badges should generally make sense on their own. Additionally, Badges are usually placed next to or in very close proximity to the text they are referring to. However, there may be times we want to provide a little extra context for people that use Assistive Technologies (AT), like screen readers. + +Use visually-hidden-text when: + +- **Ensure Programmatic Context**: The visible relationship of the Badge is not also semantically connected or represented in code. + - For example, a Badge placed visibly next to one word within a string of words but the one word and Badge pairing is not coded as a semantic group and would not easily be associated together. See the good example underneath the Accessibility Guidance: Badge Color section above. + +```jsx +import Badge from 'terra-badge'; + +
+ Heart Rate:
+ Blood Pressure: +
+``` + +- **Add Additional Context**: The visible presentation provides visible context but we want to ensure more meaningful text for a screen reader user. + - For example, a mailbox icon with a Badge count of 20 can easily be interpreted by sighted users a 20 unread messages. It would best to provide more context for AT users. In this instance we could have the Badge include the count and visually hidden text “unread messages” so a screen reader would read “20 unread messages” instead of just “20.” + +Other helpful hints in using visually-hidden-text: + +- Avoid using visually-hidden-text in a way that creates redundancy of words. For example, a badge titled “High” with visually hidden text “High Risk Factor” – in this example the word High would be read twice. It is unnecessary and the redundancy could cause confusion. +- Keep visually-hidden-text to a minimum in length. It should be short, simple, and to the point. +- Do not use visually-hidden-text when the text is sufficient to convey information of badge. + +**Remember the point of accessibility is to provide an equitable experience to all.** We do not want to give any user more information than another regardless of abilities. + +### Accessibility Guidance: Icons + +For icons to be effective within user interfaces, the icon used must make sense, be consistent and predictable, have an accessible name, and users must understand their purpose. If not implemented correctly, icons may prevent some of your users from understanding the UI. Refer to the [Terra Icon Accessibility Guide](https://engineering.cerner.com/terra-ui/components/cerner-terra-core-docs/icon/accessibility-guide) for proper guidance when using icons. + +
+ +- When using Badges inside a larger group (e.g., inside a table or list of items), do not mix and match Badge sizes. Use one only one size of Badge per grouping of content. + +- Use only one Badge per item. Multiple Badges should not be used to pair with a singular item, instead use a [`Pill`](https://engineering.cerner.com/terra-ui/components/cerner-terra-framework-docs/pills/filter-pills) or [`Tag`](https://engineering.cerner.com/terra-ui/components/cerner-terra-core-docs/tag/about) but be sure to use the component that matches the intent of use case. Pills and Tags, while similar, are not the same thing. + ## Component Features * [Cross-Browser Support](https://engineering.cerner.com/terra-ui/about/terra-ui/component-standards#cross-browser-support) * [Responsive Support](https://engineering.cerner.com/terra-ui/about/terra-ui/component-standards#responsive-support) diff --git a/packages/terra-core-docs/src/terra-dev-site/doc/badge/example/Badge.module.scss b/packages/terra-core-docs/src/terra-dev-site/doc/badge/example/Badge.module.scss index 1188aeaf589..2cfa31110dd 100644 --- a/packages/terra-core-docs/src/terra-dev-site/doc/badge/example/Badge.module.scss +++ b/packages/terra-core-docs/src/terra-dev-site/doc/badge/example/Badge.module.scss @@ -13,4 +13,25 @@ max-width: 100%; overflow-x: auto; } + + .profile-name { + font-weight: bold; + } + + .profile-container { + border: 1px solid #c8cacb; + border-radius: 10px; + display: flex; + flex-wrap: wrap; + padding: 5px; + } + + .profile-name-container { + padding-left: 10px; + padding-top: 2px; + } + + .profile-badge { + margin: 5px; + } } diff --git a/packages/terra-core-docs/src/terra-dev-site/doc/badge/example/BadgeIcon.jsx b/packages/terra-core-docs/src/terra-dev-site/doc/badge/example/BadgeIcon.jsx index d2ffff51637..945b2171295 100644 --- a/packages/terra-core-docs/src/terra-dev-site/doc/badge/example/BadgeIcon.jsx +++ b/packages/terra-core-docs/src/terra-dev-site/doc/badge/example/BadgeIcon.jsx @@ -8,17 +8,24 @@ const cx = classNames.bind(styles); const Icon = ; const BadgeIcon = () => ( -
-
- + +

+ Icon Usage Inside Badges: The following Badge example only illustrates icons inside of Badges. When Icons are used inside of Badges, be sure to follow the guidance prescribed in the + Icon Accessibility Guide + to ensure proper use of icons. Icons within icon-only Badges must be meaningful and have a meaningful label applied via the a11yLabel prop. +

+
+
+ +
+
+ +
+
+ +
-
- -
-
- -
-
+ ); export default BadgeIcon; diff --git a/packages/terra-core-docs/src/terra-dev-site/doc/badge/example/BadgeInDoc.jsx b/packages/terra-core-docs/src/terra-dev-site/doc/badge/example/BadgeInDoc.jsx new file mode 100644 index 00000000000..bc17cc73ed3 --- /dev/null +++ b/packages/terra-core-docs/src/terra-dev-site/doc/badge/example/BadgeInDoc.jsx @@ -0,0 +1,14 @@ +import React from 'react'; +import PropTypes from 'prop-types'; +import Badge from 'terra-badge'; + +const propTypes = { text: PropTypes.string, intent: PropTypes.string, visuallyHiddenText: PropTypes.string }; + +const BadgeInDoc = ({ + ...props +}) => ( + +); + +BadgeInDoc.propTypes = propTypes; +export default BadgeInDoc; diff --git a/packages/terra-core-docs/src/terra-dev-site/doc/badge/example/BadgeInTable.jsx b/packages/terra-core-docs/src/terra-dev-site/doc/badge/example/BadgeInTable.jsx index 19f69b6d8b9..a844ccc143c 100644 --- a/packages/terra-core-docs/src/terra-dev-site/doc/badge/example/BadgeInTable.jsx +++ b/packages/terra-core-docs/src/terra-dev-site/doc/badge/example/BadgeInTable.jsx @@ -1,6 +1,5 @@ import React from 'react'; import Badge from 'terra-badge'; -import IconHelpInverse from 'terra-icon/lib/icon/IconHelpInverse'; import Table, { Header, HeaderCell, @@ -13,7 +12,6 @@ import classNames from 'classnames/bind'; import styles from './Badge.module.scss'; const cx = classNames.bind(styles); -const Icon = ; const BadgeInTable = () => (
@@ -31,7 +29,7 @@ const BadgeInTable = () => (
- +
@@ -42,10 +40,7 @@ const BadgeInTable = () => (
- -
-
- +
@@ -56,10 +51,7 @@ const BadgeInTable = () => (
- -
-
- +
diff --git a/packages/terra-core-docs/src/terra-dev-site/doc/badge/example/BadgeIntent.jsx b/packages/terra-core-docs/src/terra-dev-site/doc/badge/example/BadgeIntent.jsx index 4537a7a5290..797992ec203 100644 --- a/packages/terra-core-docs/src/terra-dev-site/doc/badge/example/BadgeIntent.jsx +++ b/packages/terra-core-docs/src/terra-dev-site/doc/badge/example/BadgeIntent.jsx @@ -1,34 +1,54 @@ import React from 'react'; import Badge from 'terra-badge'; +import Avatar from 'terra-avatar'; import classNames from 'classnames/bind'; import styles from './Badge.module.scss'; const cx = classNames.bind(styles); const BadgeIntent = () => ( -
-
- + +

+ The Intent prop can be used to apply colors to badges. Please refer to the + VisuallyHiddenText prop examples further below + to ensure proper + context is provided for assistive technology users to understand the purpose of the badge. +

+

+ Intent Badge Colors: The following Badge example only illustrates badge colors. This example is not intended to illustrate how Badges should be used. As noted above, multiple badges should not be used together. Instead, see Pills or Tag. +

+
+
+ +
+
+ +
+
+ +
+
+ +
+
+ +
-
- +

+ Example usage of the Intent Badge. Please note that this use case does not require the VisuallyHiddenText prop because the badge is visually and programmatically grouped in a semantic container. Other use cases will require the VisuallyHiddenText prop. To effectively communicate context to assistive technology users. +

+
+ +
+ Segun Adebayo +
+ UI Engineer +
+
+ +
-
- -
-
- -
-
- -
-
- -
-
- -
-
+
); export default BadgeIntent; diff --git a/packages/terra-core-docs/src/terra-dev-site/doc/badge/example/BadgeSize.jsx b/packages/terra-core-docs/src/terra-dev-site/doc/badge/example/BadgeSize.jsx index 1dad6b0159a..62c0e5149fe 100644 --- a/packages/terra-core-docs/src/terra-dev-site/doc/badge/example/BadgeSize.jsx +++ b/packages/terra-core-docs/src/terra-dev-site/doc/badge/example/BadgeSize.jsx @@ -6,23 +6,28 @@ import styles from './Badge.module.scss'; const cx = classNames.bind(styles); const BadgeSize = () => ( -
-
- + +

+ The size prop can be used to change the size of Badges. The following is not an example of how to use Badges. It is only intended to illustrate the sizes that can be set. Never use size as a method to communicate meaning. +

+
+
+ +
+
+ +
+
+ +
+
+ +
+
+ +
-
- -
-
- -
-
- -
-
- -
-
+ ); export default BadgeSize; diff --git a/packages/terra-core-docs/src/terra-dev-site/doc/badge/example/BadgeVisuallyHiddenText.jsx b/packages/terra-core-docs/src/terra-dev-site/doc/badge/example/BadgeVisuallyHiddenText.jsx index dcf2e01b4a5..bcf47a505c5 100644 --- a/packages/terra-core-docs/src/terra-dev-site/doc/badge/example/BadgeVisuallyHiddenText.jsx +++ b/packages/terra-core-docs/src/terra-dev-site/doc/badge/example/BadgeVisuallyHiddenText.jsx @@ -1,25 +1,41 @@ import React from 'react'; import Badge from 'terra-badge'; +import Button from 'terra-button'; import classNames from 'classnames/bind'; import styles from './Badge.module.scss'; const cx = classNames.bind(styles); const BadgeVisuallyHiddenText = () => ( -
-
- + +

+ Ensuring Programmatic Context Badge Example: + When a Badge is paired with a word or item but not semantically understood as grouped with that word, add use the word or words as the visually hidden text string as illustrated in the following example. +

+
+ + Heart Rate + +
+ +
-
- +
+ + Blood Pressure + +
+ +
-
- +

+ Add Additional Context to a Badge Example: + Use the VisuallyHiddenText prop to provide additional context that sighted users can see but may make the content more meaningful and better understood by screen reader users. +

+
+
-
- -
-
+ ); export default BadgeVisuallyHiddenText;