Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add badge component #85

Merged
merged 5 commits into from
Jun 12, 2024
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
60 changes: 60 additions & 0 deletions docs/components/badge.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
---
layout: layouts/component.njk
title: Badge
description: Use badges to alert users to unread information. Badges can include a number count.
backlogID: 0
tags:
- component
---

## When to use

Badges can be placed:

- on the edge of an icon
- on a card

Badges help to notify users about unread information that needs their attention. This could include new messages or new documents.

## How to use

Badges should be dynamic and temporary. After users have viewed the relevant information, badges should either:

- disappear
- remain if there are still unread items (but with an adjusted number count, if one is used)

There are different size and colour variations of badges.

### Large badges

{% example "badges/badge-large.njk" %}

Large badges always include a number count. This tells users how many items need their attention.

Above the count of 9, large badges always display 9+. This allows the width of the badge to be restricted to two characters.

### Small badges

Small badges are simple circles. They can be placed:

- on the edge of icons, such as on the bottom navigation
- on cards, alongside text, such as “Document attached” on appointment cards

{% example "badges/badge-small.njk" %}

The colour of small badges can be:

- red for important notifications that needs to stand out on a page
- blue for secondary notifications that can afford to be less prominent

{% example "badges/badge-small-red.njk" %}

For example, users will see a red badge on the bottom navigation to indicate unread messages. When they then navigate to their messages inbox to view those messages, unread message headings are indicated by blue badges.

## Accessibility

Badges are designed to stand out when placed over icons and cards. The contrast ratio is 3:1, meeting [WCAG 2.2. Contrast (Minimum) (Level AA)](https://www.w3.org/WAI/WCAG22/Understanding/contrast-minimum).

We use visually hidden text to convey badges to screen reader users. Large badges announce the number count up to 9. They announce "nine plus" after that to match the visual display of 9+.

Small badges could announce "New notification", "Important" or "You have unread messages" depending on the context.
2 changes: 1 addition & 1 deletion docs/components/card-links.md
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,7 @@ If you are using icons, they should have [aria labels/hidden text?] so that scre

Use badges to alert users to new, important information that sits beyond a card link. This could include unread messages or new appointment details.

[embed badge example]
{% example "cards/card-link-with-badge.njk" %}

## Content guidance

Expand Down
13 changes: 13 additions & 0 deletions docs/examples/badges/badge-large.njk
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
---
layout: layouts/example.njk
title: Badge Large
figmaLink: "https://www.figma.com/design/6f2CbcZ7cnpNrtKEcfQp8X/NHS-App-Design-System?node-id=128-7303&t=UdzCaY5YPtBypveQ-0"
vueLink: "https://nhsappvuecomponentlibraryv1.nonlive.nhsapp.service.nhs.uk/?path=/docs/components-nhsbadge-large--docs"
---

{% from "badge/large/macro.njk" import badgeLarge %}

{{ badgeLarge({
count: 3,
label: 'notifications'
}) }}
15 changes: 15 additions & 0 deletions docs/examples/badges/badge-small-red.njk
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
---
layout: layouts/example.njk
title: Badge Small
figmaLink: "https://www.figma.com/design/6f2CbcZ7cnpNrtKEcfQp8X/NHS-App-Design-System?node-id=128-7303&t=UdzCaY5YPtBypveQ-0"
vueLink: "https://nhsappvuecomponentlibraryv1.nonlive.nhsapp.service.nhs.uk/?path=/docs/components-nhsbadge-small--docs"
---

{% from "badge/small/macro.njk" import badgeSmall %}

{{ badgeSmall({
label: 'New',
color: 'red',
text: 'Document attached',
classes: 'nhsuk-body-m'
}) }}
14 changes: 14 additions & 0 deletions docs/examples/badges/badge-small.njk
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
---
layout: layouts/example.njk
title: Badge Small
figmaLink: "https://www.figma.com/design/6f2CbcZ7cnpNrtKEcfQp8X/NHS-App-Design-System?node-id=128-7303&t=UdzCaY5YPtBypveQ-0"
vueLink: "https://nhsappvuecomponentlibraryv1.nonlive.nhsapp.service.nhs.uk/?path=/docs/components-nhsbadge-small--docs"
---

{% from "badge/small/macro.njk" import badgeSmall %}

{{ badgeSmall({
label: 'New',
text: 'Document attached',
classes: 'nhsuk-body-m'
}) }}
17 changes: 17 additions & 0 deletions docs/examples/cards/card-link-with-badge.njk
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
---
layout: layouts/example.njk
title: Card link with description
figmaLink: "https://www.figma.com/file/6f2CbcZ7cnpNrtKEcfQp8X/NHS-App-Design-System?type=design&node-id=128%3A7303&mode=design&t=DLiyCHcTTAYkEDa0-1"
vueLink: "https://nhsappvuecomponentlibraryv1.nonlive.nhsapp.service.nhs.uk/?path=/docs/components-nhscardlink--docs"
---

{% from "card/macro.njk" import card %}

{{ card({
title: 'Messages',
href: '#',
badgeLarge: {
count: 4,
label: 'unread messages'
}
}) }}
1 change: 1 addition & 0 deletions docs/index.njk
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@

{%- from 'hero/macro.njk' import hero -%}
{%- from 'card/macro.njk' import card -%}
{%- from 'badge/large/macro.njk' import badgeLarge -%}

{% block header %}
{{ super() }}
Expand Down
3 changes: 2 additions & 1 deletion src/all.scss
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
@import "node_modules/nhsuk-frontend/packages/core/tools/all.scss";
@import "node_modules/nhsuk-frontend/packages/core/settings/all.scss";

@import "./components/card/card.scss";
@import "./components/card/card";
@import "./components/badge/badge";
73 changes: 73 additions & 0 deletions src/components/badge/_badge.scss
Original file line number Diff line number Diff line change
@@ -0,0 +1,73 @@
// ==========================================================================
// COMPONENTS / #BADGE
// ==========================================================================

@use "sass:math";

.nhsapp-badge {
@include nhsuk-typography-responsive(19);

display: inline-block;

background-color: $nhsuk-error-color;
border-radius: nhsuk-spacing(1);
color: $color_nhsuk-white;
font-weight: bold;
padding: 0 nhsuk-spacing(2);

@include mq($from: tablet) {
padding: 0 12px;
}
}

.nhsapp-badge-small {
position: relative;

display: inline-flex;
align-items: baseline;
}

/**
* Mixin to position the small badge
* @param {number} $size - The size of the badge
*/
@mixin small-badge-position($size: 8px) {
position: relative;
width: $size;
height: $size;
margin-right: $size;
border-radius: math.div($size, 2);

$font-height: 0.7em; // The height of a capital letter in the specific font we use (Frutiger)
bottom: calc(0.5 * ($font-height - $size));
}

$nhsapp-badge-size-mobile: 8px;
$nhsapp-badge-size-tablet: 12px;

.nhsapp-badge-small__indicator {
@include small-badge-position($nhsapp-badge-size-mobile);

@include mq($from: tablet) {
@include small-badge-position($nhsapp-badge-size-tablet);
}

background-color: $color_nhsuk-blue;
}

.nhsapp-badge-small--red {
.nhsapp-badge-small__indicator {
background-color: $nhsuk-error-color;
}
}

.nhsapp-badge-small--absolute {
.nhsapp-badge-small__indicator {
position: absolute;

left: -2 * $nhsapp-badge-size-mobile;
@include mq($from: tablet) {
left: -2 * $nhsapp-badge-size-tablet;
}
}
}
11 changes: 11 additions & 0 deletions src/components/badge/large/badge-large.njk
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
{%- if params.count -%}
<span class="nhsapp-badge">
<span class="nhsuk-u-visually-hidden">You have</span>
{% if params.count > 9 %}
+9
{% else %}
{{ params.count }}
{% endif %}
<span class="nhsuk-u-visually-hidden">{{ params.label }}</span>
</span>
{%- endif -%}
3 changes: 3 additions & 0 deletions src/components/badge/large/macro.njk
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
{% macro badgeLarge(params) %}
{%- include "./badge-large.njk" -%}
{% endmacro %}
9 changes: 9 additions & 0 deletions src/components/badge/small/badge-small.njk
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
<span class="
nhsapp-badge-small
{{ 'nhsapp-badge-small--red' if params.color === 'red' }}
{{ 'nhsapp-badge-small--absolute' if params.positionAbsolute }}
{{ params.classes if params.classes }}">
<span class="nhsapp-badge-small__indicator" aria-hidden="true"></span>
<span class="nhsuk-u-visually-hidden">{{ params.label }}</span>
<span>{{ params.text }}</span>
</span>
3 changes: 3 additions & 0 deletions src/components/badge/small/macro.njk
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
{% macro badgeSmall(params) %}
{%- include "./badge-small.njk" -%}
{% endmacro %}
10 changes: 10 additions & 0 deletions src/components/card/card.njk
Original file line number Diff line number Diff line change
@@ -1,3 +1,7 @@
{% from "badge/large/macro.njk" import badgeLarge %}

{% set hasBadgeLarge = true if params.badgeLarge.count > 1 %}

<div class="nhsapp-card">
<div class="nhsapp-card__container">
<div class="nhsapp-card__content">
Expand All @@ -10,6 +14,12 @@
</div>
{%- endif -%}
</div>
{% if hasBadgeLarge %}
{{ badgeLarge({
count: params.badgeLarge.count,
label: params.badgeLarge.label
}) }}
{% endif %}
<svg class="nhsapp-icon app-icon--chevron" aria-hidden="true" xmlns="http://www.w3.org/2000/svg" width="25" height="24" viewBox="0 0 25 24" fill="none">
<path d="M8.82264 19.11C8.56264 19.11 8.29264 19.01 8.10264 18.8C7.72264 18.4 7.73264 17.77 8.13264 17.39L13.7426 12.01L8.14264 6.75999C7.74264 6.37999 7.72264 5.74999 8.09264 5.34999C8.47264 4.94999 9.10264 4.92999 9.50264 5.29999L15.8726 11.27C16.0726 11.46 16.1826 11.72 16.1926 11.99C16.2026 12.26 16.0826 12.53 15.8826 12.72L9.51264 18.83C9.32264 19.02 9.07264 19.11 8.82264 19.11Z"></path>
</svg>
Expand Down
Loading