Skip to content

Commit 8530a5b

Browse files
Upgrade to NHS.UK frontend v10.2 (#316)
* Update to NHS.UK frontend v10.2.2 * Update text input examples * Add text input `code` support (for codes and sequences) * Update select examples * Update button examples * Add login button support * Add small button support * Simplify form group `aria-describedby` handling * Add support for form group `beforeInput` and `afterInput` * Add text input with button examples * Add select with button examples * Add password input component * Update tabs examples * Update card examples * Remove unnecessary card classes * Add select divider support * Update changelog * Update upgrade guide * Reduce duplicate button code * Fix character count `undefined` hint text ID in `aria-describedby` * Add support for button `secondarySolid` prop * Add missing `role="list"` to Do and Don't list component
1 parent 84a3e92 commit 8530a5b

42 files changed

Lines changed: 1369 additions & 432 deletions

File tree

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

CHANGELOG.md

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,16 @@
11
# NHS.UK React components
22

3+
## Unreleased
4+
5+
This version provides support for NHS.UK frontend v10.2 and includes:
6+
7+
- [Password input component](https://service-manual.nhs.uk/design-system/components/password-input)
8+
- [Smaller and inline buttons](https://service-manual.nhs.uk/design-system/components/buttons#smaller-buttons)
9+
- [Text input styles for codes and sequences](https://service-manual.nhs.uk/design-system/components/text-input#codes-and-sequences)
10+
- [Select](https://service-manual.nhs.uk/design-system/components/select) dividers using `<Select.Divider />`
11+
12+
For a full list of changes in this release please refer to the [migration doc](https://github.com/NHSDigital/nhsuk-react-components/blob/main/docs/upgrade-to-6.0.md).
13+
314
## 6.0.0-beta.4 - 5 November 2025
415

516
This version provides support for NHS.UK frontend v10.1 and includes:

docs/upgrade-to-6.0.md

Lines changed: 66 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,10 +18,76 @@ The updated [header](https://service-manual.nhs.uk/design-system/components/head
1818
- update NHS logo in the header to have higher contrast when focused
1919
- refactor CSS classes and BEM naming, use hidden attributes instead of modifier classes, use generic search element
2020

21+
#### Use the password input component to help users accessibly enter passwords
22+
23+
The [password input](https://service-manual.nhs.uk/design-system/components/password-input) component from NHS.UK frontend v10.2 allows users to choose:
24+
25+
- whether their passwords are visible or not
26+
- to enter their passwords in plain text
27+
28+
This helps users use longer and more complex passwords without needing to remember what they've already typed.
29+
2130
#### Smaller versions of radio buttons and checkboxes
2231

2332
You can now use smaller versions of the [radios](https://service-manual.nhs.uk/design-system/components/radios) and [checkboxes](https://service-manual.nhs.uk/design-system/components/checkboxes) components by adding the `small` prop.
2433

34+
#### Smaller versions of buttons
35+
36+
You can now use smaller versions of [buttons](https://service-manual.nhs.uk/design-system/components/buttons) by adding the `small` prop.
37+
38+
#### Secondary buttons with solid white background
39+
40+
By default, the secondary button is transparent and has no colour.
41+
42+
You can now make the [button](https://service-manual.nhs.uk/design-system/components/button) component white when you use it on darker backgrounds by adding the `secondarySolid` prop.
43+
44+
#### Add inline buttons to text inputs and select menus
45+
46+
You can now add inline buttons to text inputs and select menus using the `formGroupProps.afterInput` prop.
47+
48+
```jsx
49+
<TextInput
50+
formGroupProps={{
51+
afterInput: () => (
52+
<Button secondary small>
53+
Search
54+
</Button>
55+
),
56+
}},
57+
/>
58+
```
59+
60+
#### Add a 'code' prop for text inputs that accept codes and sequences
61+
62+
We've added a new `code` prop for the [text input](https://service-manual.nhs.uk/design-system/components/text-input) component. This improves readability of text inputs that receive codes and sequences (like NHS numbers, security codes or booking references).
63+
64+
```patch
65+
<TextInput
66+
label="What is your NHS number?"
67+
labelProps={{ isPageHeading: true, size: 'l' }}
68+
inputMode="numeric"
69+
spellCheck="false"
70+
width="10"
71+
+ code
72+
/>
73+
```
74+
75+
#### Add a 'divider' between select options
76+
77+
Newer browsers support [using `<hr>` (horizontal rule) elements inside a `<select>` element](https://developer.chrome.com/blog/hr-in-select/) to help visually break up options for better readability.
78+
79+
We've added a new `<Select.Divider />` child component for select menus to support this feature. For example:
80+
81+
```patch
82+
<Select>
83+
<Select.Option value="first-name-ascending">First name (A to Z)</Select.Option>
84+
<Select.Option value="first-name-descending">First name (Z to A)</Select.Option>
85+
+ <Select.Divider />
86+
<Select.Option value="last-name-ascending">Last name (A to Z)</Select.Option>
87+
<Select.Option value="last-name-descending">Last name (Z to A)</Select.Option>
88+
</Select>
89+
```
90+
2591
### Numbered pagination component
2692

2793
The [pagination](https://service-manual.nhs.uk/design-system/components/pagination) component from NHS.UK frontend v10.1 has been updated to support numbered pagination:

package.json

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -99,7 +99,7 @@
9999
"jest-axe": "^10.0.0",
100100
"jest-environment-jsdom": "^30.2.0",
101101
"lodash": "^4.17.21",
102-
"nhsuk-frontend": "^10.1.0",
102+
"nhsuk-frontend": "^10.2.2",
103103
"outdent": "^0.8.0",
104104
"prettier": "^3.7.4",
105105
"react": "^19.2.3",
@@ -116,7 +116,7 @@
116116
},
117117
"peerDependencies": {
118118
"classnames": ">=2.5.0",
119-
"nhsuk-frontend": ">=10.1.0 <11.0.0",
119+
"nhsuk-frontend": ">=10.2.0 <11.0.0",
120120
"react": ">=18.2.0",
121121
"react-dom": ">=18.2.0",
122122
"tslib": ">=2.8.0"

src/__tests__/index.test.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -101,6 +101,7 @@ describe('Index', () => {
101101
'PaginationLinkText',
102102
'Panel',
103103
'PanelTitle',
104+
'PasswordInput',
104105
'Radios',
105106
'RadiosContext',
106107
'RadiosDivider',
@@ -110,6 +111,7 @@ describe('Index', () => {
110111
'Row',
111112
'SearchIcon',
112113
'Select',
114+
'SelectDivider',
113115
'SelectOption',
114116
'SkipLink',
115117
'SummaryList',

src/components/content-presentation/do-and-dont-list/DoAndDontList.tsx

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,12 +20,14 @@ const DoAndDontListComponent = forwardRef<HTMLDivElement, DoAndDontListProps>(
2020
<HeadingLevel className="nhsuk-do-dont-list__label" headingLevel={headingLevel}>
2121
{heading || (listType === 'do' ? 'Do' : "Don't")}
2222
</HeadingLevel>
23+
{/* eslint-disable-next-line jsx-a11y/no-redundant-roles */}
2324
<ul
2425
className={classNames(
2526
'nhsuk-list',
2627
{ 'nhsuk-list--tick': listType === 'do' },
2728
{ 'nhsuk-list--cross': listType === 'dont' },
2829
)}
30+
role="list"
2931
>
3032
<DoAndDontListContext.Provider value={listType}>{children}</DoAndDontListContext.Provider>
3133
</ul>

src/components/content-presentation/do-and-dont-list/__tests__/__snapshots__/DoAndDontList.test.tsx.snap

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,7 @@ exports[`DoAndDontList list type "do" matches snapshot (via server): client 1`]
3333
</h3>
3434
<ul
3535
class="nhsuk-list nhsuk-list--tick"
36+
role="list"
3637
/>
3738
</div>
3839
</div>
@@ -50,6 +51,7 @@ exports[`DoAndDontList list type "do" matches snapshot (via server): server 1`]
5051
</h3>
5152
<ul
5253
class="nhsuk-list nhsuk-list--tick"
54+
role="list"
5355
/>
5456
</div>
5557
</div>
@@ -67,6 +69,7 @@ exports[`DoAndDontList list type "do" matches snapshot: DoDontList-Do 1`] = `
6769
</h3>
6870
<ul
6971
class="nhsuk-list nhsuk-list--tick"
72+
role="list"
7073
/>
7174
</div>
7275
</div>
@@ -84,6 +87,7 @@ exports[`DoAndDontList list type "dont" matches snapshot (via server): client 1`
8487
</h3>
8588
<ul
8689
class="nhsuk-list nhsuk-list--cross"
90+
role="list"
8791
/>
8892
</div>
8993
</div>
@@ -101,6 +105,7 @@ exports[`DoAndDontList list type "dont" matches snapshot (via server): server 1`
101105
</h3>
102106
<ul
103107
class="nhsuk-list nhsuk-list--cross"
108+
role="list"
104109
/>
105110
</div>
106111
</div>
@@ -118,6 +123,7 @@ exports[`DoAndDontList list type "dont" matches snapshot: DoDontList-Dont 1`] =
118123
</h3>
119124
<ul
120125
class="nhsuk-list nhsuk-list--cross"
126+
role="list"
121127
/>
122128
</div>
123129
</div>

src/components/form-elements/button/Button.tsx

Lines changed: 30 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -14,33 +14,51 @@ import {
1414

1515
import { type AsElementLink } from '#util/types/LinkTypes.js';
1616

17-
export interface ButtonProps extends AsElementLink<HTMLButtonElement> {
17+
export interface ButtonProps extends ButtonBaseProps, AsElementLink<HTMLButtonElement> {
1818
href?: never;
19-
secondary?: boolean;
20-
reverse?: boolean;
21-
warning?: boolean;
2219
as?: 'button';
23-
preventDoubleClick?: boolean;
2420
}
2521

26-
export interface ButtonLinkProps extends AsElementLink<HTMLAnchorElement> {
22+
export interface ButtonLinkProps extends ButtonBaseProps, AsElementLink<HTMLAnchorElement> {
2723
href: string;
2824
type?: never;
25+
as?: 'a';
26+
}
27+
28+
interface ButtonBaseProps {
2929
secondary?: boolean;
30+
secondarySolid?: boolean;
3031
reverse?: boolean;
3132
warning?: boolean;
32-
as?: 'a';
33+
login?: boolean;
34+
small?: boolean;
3335
preventDoubleClick?: boolean;
3436
}
3537

38+
function getButtonClassNames(props: ButtonProps | ButtonLinkProps) {
39+
return classNames(
40+
'nhsuk-button',
41+
{ 'nhsuk-button--secondary': props.secondary },
42+
{ 'nhsuk-button--secondary-solid': props.secondarySolid },
43+
{ 'nhsuk-button--reverse': props.reverse },
44+
{ 'nhsuk-button--warning': props.warning },
45+
{ 'nhsuk-button--login': props.login },
46+
{ 'nhsuk-button--small': props.small },
47+
props.className,
48+
);
49+
}
50+
3651
const ButtonComponent = forwardRef<HTMLButtonElement, ButtonProps>((props, forwardedRef) => {
3752
const {
3853
className,
3954
asElement: Element = 'button',
4055
disabled,
4156
secondary,
57+
secondarySolid,
4258
reverse,
4359
warning,
60+
login,
61+
small,
4462
type = 'submit',
4563
preventDoubleClick,
4664
onClick,
@@ -70,13 +88,7 @@ const ButtonComponent = forwardRef<HTMLButtonElement, ButtonProps>((props, forwa
7088

7189
return (
7290
<Element
73-
className={classNames(
74-
'nhsuk-button',
75-
{ 'nhsuk-button--secondary': secondary },
76-
{ 'nhsuk-button--reverse': reverse },
77-
{ 'nhsuk-button--warning': warning },
78-
className,
79-
)}
91+
className={getButtonClassNames(props)}
8092
data-module="nhsuk-button"
8193
data-prevent-double-click={preventDoubleClick === true ? 'true' : undefined}
8294
disabled={disabled}
@@ -102,8 +114,11 @@ const ButtonLinkComponent = forwardRef<HTMLAnchorElement, ButtonLinkProps>(
102114
className,
103115
asElement: Element = 'a',
104116
secondary,
117+
secondarySolid,
105118
reverse,
106119
warning,
120+
login,
121+
small,
107122
preventDoubleClick,
108123
onClick,
109124
...rest
@@ -132,13 +147,7 @@ const ButtonLinkComponent = forwardRef<HTMLAnchorElement, ButtonLinkProps>(
132147

133148
return (
134149
<Element
135-
className={classNames(
136-
'nhsuk-button',
137-
{ 'nhsuk-button--secondary': secondary },
138-
{ 'nhsuk-button--reverse': reverse },
139-
{ 'nhsuk-button--warning': warning },
140-
className,
141-
)}
150+
className={getButtonClassNames(props)}
142151
data-module="nhsuk-button"
143152
data-prevent-double-click={preventDoubleClick === true ? 'true' : undefined}
144153
role="button"

0 commit comments

Comments
 (0)