Skip to content
Draft
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
2 changes: 0 additions & 2 deletions .storybook/preview.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,6 @@ import { type Preview } from '@storybook/react-vite';

import { Col, Container, Row } from '#components/layout/index.js';

import './storybook.scss';

const preview: Preview = {
decorators: (Story, { parameters }) =>
parameters.width === false ? (
Expand Down
1 change: 0 additions & 1 deletion .storybook/storybook.d.ts

This file was deleted.

12 changes: 0 additions & 12 deletions .storybook/storybook.scss

This file was deleted.

20 changes: 15 additions & 5 deletions docs/upgrade-to-6.0.md
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,7 @@ You can now use smaller versions of [buttons](https://service-manual.nhs.uk/desi

By default, the secondary button is transparent and has no colour.

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.
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 setting the `variant` prop to `'secondary-solid'`.

#### Add inline buttons to text inputs and select menus

Expand All @@ -58,7 +58,7 @@ You can now add inline buttons to text inputs and select menus using the `formGr
<TextInput
formGroupProps={{
afterInput: (
<Button secondary small>
<Button variant="secondary" small>
Search
</Button>
),
Expand Down Expand Up @@ -333,10 +333,11 @@ To align with NHS.UK frontend, icons unused by components have been removed:
- `ChevronLeftIcon`
- `ChevronRightIcon`
- `ChevronDownIcon`
- `CloseIcon`
- `EmdashIcon` and `SmallEmdashIcon`
- `MinusIcon`
- `PlusIcon`

With the following icons renamed:

- `CloseIcon` renamed to `CrossIcon`

### Back link

Expand Down Expand Up @@ -719,6 +720,15 @@ If you are using the `Table.Panel` child component, you must migrate to the feat
+ <Card.Heading>Other conditions like impetigo</Card.Heading>
```

### Tags

To align with NHS.UK frontend, you must rename the `Tag` prop `color` to `colour`:

```patch
- <Tag color="white">In progress</Tag>
+ <Tag colour="white">In progress</Tag>
```

### Textarea

You must rename the `Textarea` prop `textareaRef` to `ref` for consistency with other components:
Expand Down
1 change: 1 addition & 0 deletions eslint.config.js
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@ export default defineConfig([
'no-redeclare': 'off',
'no-undef': 'off',
'no-unused-vars': 'off',
'@typescript-eslint/no-deprecated': 'warn',
'@typescript-eslint/no-redeclare': 'error',
'@typescript-eslint/no-unused-vars': [
'error',
Expand Down
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -104,7 +104,7 @@
"jest": "^30.4.2",
"jest-axe": "^10.0.0",
"jest-environment-jsdom": "^30.4.1",
"nhsuk-frontend": "^10.3.1",
"nhsuk-frontend": "^10.5.2",
"outdent": "^0.8.0",
"prettier": "^3.8.3",
"react": "^19.2.7",
Expand Down
12 changes: 10 additions & 2 deletions src/components/content-presentation/details/Details.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,12 +3,20 @@ import { type ComponentPropsWithoutRef, type FC, forwardRef } from 'react';

export interface DetailsProps extends ComponentPropsWithoutRef<'details'> {
expander?: boolean;
variant?: 'reverse';
}

const DetailsComponent = forwardRef<HTMLDetailsElement, DetailsProps>(
({ className, expander, ...rest }, forwardedRef) => (
({ className, expander, variant, ...rest }, forwardedRef) => (
<details
className={classNames('nhsuk-details', { 'nhsuk-expander': expander }, className)}
className={classNames(
'nhsuk-details',
{
'nhsuk-expander': expander,
'nhsuk-details--reverse': variant === 'reverse',
},
className,
)}
ref={forwardedRef}
{...rest}
/>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,15 @@ describe('Details', () => {
expect(detailsEl).toHaveClass('nhsuk-expander');
});

it('adds reverse variant', async () => {
const { modules } = await renderClient(<Details variant="reverse" />, {
className: 'nhsuk-details',
});

const [detailsEl] = modules;
expect(detailsEl).toHaveClass('nhsuk-details--reverse');
});

it('forwards refs', async () => {
const ref = createRef<HTMLDetailsElement>();

Expand Down
20 changes: 14 additions & 6 deletions src/components/content-presentation/icons/Icon.tsx
Original file line number Diff line number Diff line change
@@ -1,9 +1,10 @@
/* eslint-disable @typescript-eslint/no-deprecated */
import classNames from 'classnames';
import { type ComponentPropsWithoutRef, type FC } from 'react';

export interface IconProps extends ComponentPropsWithoutRef<'svg'> {
title?: string;
modifier?:
name?:
| 'arrow-left'
| 'arrow-right'
| 'arrow-right-circle'
Expand All @@ -14,18 +15,25 @@
| 'user';

/**
* @deprecated Use `modifier` instead.
* @deprecated Use `name` instead.
*/
iconType?: IconProps['modifier'];
iconType?: IconProps['name'];

/**
* @deprecated Use `name` instead.
*/
modifier?: IconProps['name'];
}

export const Icon: FC<IconProps> = ({
className,
children,
name,
iconType,
modifier = iconType
?.replace('nhsuk-icon__', '') // NHS.UK frontend v9.x
.replace('nhsuk-icon--', ''), // NHS.UK frontend v10.x
modifier = name ??

Check warning on line 33 in src/components/content-presentation/icons/Icon.tsx

View check run for this annotation

SonarQubeCloud / SonarCloud Code Analysis

'modifier' is deprecated.

See more on https://sonarcloud.io/project/issues?id=NHSDigital_nhsuk-react-components&issues=AZ7Ln_sClBkZ12ex1qAG&open=AZ7Ln_sClBkZ12ex1qAG&pullRequest=391
iconType
?.replace('nhsuk-icon__', '') // NHS.UK frontend v9.x
.replace('nhsuk-icon--', ''), // NHS.UK frontend v10.x
title,
...rest
}) => (
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ import { type FC } from 'react';
import { Icon, type IconProps } from '../Icon.js';

export const ArrowLeftIcon: FC<IconProps> = (props) => (
<Icon modifier="arrow-left" {...props}>
<Icon name="arrow-left" {...props}>
<path d="M10.7 6.3c.4.4.4 1 0 1.4L7.4 11H19a1 1 0 0 1 0 2H7.4l3.3 3.3c.4.4.4 1 0 1.4a1 1 0 0 1-1.4 0l-5-5A1 1 0 0 1 4 12c0-.3.1-.5.3-.7l5-5a1 1 0 0 1 1.4 0Z" />
</Icon>
);
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ import { type FC } from 'react';
import { Icon, type IconProps } from '../Icon.js';

export const ArrowRightCircleIcon: FC<IconProps> = (props) => (
<Icon modifier="arrow-right-circle" {...props}>
<Icon name="arrow-right-circle" {...props}>
<path d="M12 2a10 10 0 0 0-10 9h11.7l-4-4a1 1 0 0 1 1.5-1.4l5.6 5.7a1 1 0 0 1 0 1.4l-5.6 5.7a1 1 0 0 1-1.5 0 1 1 0 0 1 0-1.4l4-4H2A10 10 0 1 0 12 2z" />
</Icon>
);
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ import { type FC } from 'react';
import { Icon, type IconProps } from '../Icon.js';

export const ArrowRightIcon: FC<IconProps> = (props) => (
<Icon modifier="arrow-right" {...props}>
<Icon name="arrow-right" {...props}>
<path d="m14.7 6.3 5 5c.2.2.3.4.3.7 0 .3-.1.5-.3.7l-5 5a1 1 0 0 1-1.4-1.4l3.3-3.3H5a1 1 0 0 1 0-2h11.6l-3.3-3.3a1 1 0 1 1 1.4-1.4Z" />
</Icon>
);
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ import { type FC } from 'react';
import { Icon, type IconProps } from '../Icon.js';

export const ChevronRightCircleIcon: FC<IconProps> = (props) => (
<Icon modifier="chevron-right-circle" {...props}>
<Icon name="chevron-right-circle" {...props}>
<path d="M12 2a10 10 0 1 1 0 20 10 10 0 0 1 0-20Zm-.3 5.8a1 1 0 1 0-1.5 1.4l2.9 2.8-2.9 2.8a1 1 0 0 0 1.5 1.4l3.5-3.5c.4-.4.4-1 0-1.4Z" />
</Icon>
);
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ import { type FC } from 'react';
import { Icon, type IconProps } from '../Icon.js';

export const CrossIcon: FC<IconProps> = (props) => (
<Icon modifier="cross" {...props}>
<Icon name="cross" {...props}>
<path d="M17 18.5c-.4 0-.8-.1-1.1-.4l-10-10c-.6-.6-.6-1.6 0-2.1.6-.6 1.5-.6 2.1 0l10 10c.6.6.6 1.5 0 2.1-.3.3-.6.4-1 .4z M7 18.5c-.4 0-.8-.1-1.1-.4-.6-.6-.6-1.5 0-2.1l10-10c.6-.6 1.5-.6 2.1 0 .6.6.6 1.5 0 2.1l-10 10c-.3.3-.6.4-1 .4z" />
</Icon>
);
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ import { type FC } from 'react';
import { Icon, type IconProps } from '../Icon.js';

export const SearchIcon: FC<IconProps> = (props) => (
<Icon modifier="search" {...props}>
<Icon name="search" {...props}>
<path d="m20.7 19.3-4.1-4.1a7 7 0 1 0-1.4 1.4l4 4.1a1 1 0 0 0 1.5 0c.4-.4.4-1 0-1.4ZM6 11a5 5 0 1 1 10 0 5 5 0 0 1-10 0Z" />
</Icon>
);
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ import { type FC } from 'react';
import { Icon, type IconProps } from '../Icon.js';

export const TickIcon: FC<IconProps> = (props) => (
<Icon modifier="tick" {...props}>
<Icon name="tick" {...props}>
<path d="M11.4 18.8a2 2 0 0 1-2.7.1h-.1L4 14.1a1.5 1.5 0 0 1 2.1-2L10 16l8.1-8.1a1.5 1.5 0 1 1 2.2 2l-8.9 9Z" />
</Icon>
);
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ import { type FC } from 'react';
import { Icon, type IconProps } from '../Icon.js';

export const UserIcon: FC<IconProps> = (props) => (
<Icon modifier="user" {...props}>
<Icon name="user" {...props}>
<path d="M12 1a11 11 0 1 1 0 22 11 11 0 0 1 0-22Zm0 2a9 9 0 0 0-5 16.5V18a4 4 0 0 1 4-4h2a4 4 0 0 1 4 4v1.5A9 9 0 0 0 12 3Zm0 3a3.5 3.5 0 1 1-3.5 3.5A3.4 3.4 0 0 1 12 6Z" />
</Icon>
);
34 changes: 29 additions & 5 deletions src/components/content-presentation/tag/Tag.tsx
Original file line number Diff line number Diff line change
@@ -1,8 +1,9 @@
/* eslint-disable @typescript-eslint/no-deprecated */
import classNames from 'classnames';
import { type ComponentPropsWithoutRef, type FC } from 'react';

export interface TagProps extends ComponentPropsWithoutRef<'strong'> {
modifier?:
colour?:
| 'white'
| 'grey'
| 'green'
Expand All @@ -15,14 +16,37 @@
| 'yellow';

/**
* @deprecated Use `modifier` instead.
* @deprecated Use `colour` instead.
*/
color?: TagProps['modifier'];
color?: TagProps['colour'];

/**
* @deprecated Use `colour` instead.
*/
modifier?: TagProps['colour'];

border?: boolean;
noBorder?: boolean;
}

export const Tag: FC<TagProps> = ({ className, color, modifier = color, ...rest }) => (
export const Tag: FC<TagProps> = ({
className,
modifier,

Check warning on line 34 in src/components/content-presentation/tag/Tag.tsx

View check run for this annotation

SonarQubeCloud / SonarCloud Code Analysis

'modifier' is deprecated.

See more on https://sonarcloud.io/project/issues?id=NHSDigital_nhsuk-react-components&issues=AZ7Ln_ojlBkZ12ex1qAE&open=AZ7Ln_ojlBkZ12ex1qAE&pullRequest=391
color,

Check warning on line 35 in src/components/content-presentation/tag/Tag.tsx

View check run for this annotation

SonarQubeCloud / SonarCloud Code Analysis

'color' is deprecated.

See more on https://sonarcloud.io/project/issues?id=NHSDigital_nhsuk-react-components&issues=AZ7Ln_ojlBkZ12ex1qAF&open=AZ7Ln_ojlBkZ12ex1qAF&pullRequest=391
colour = color ?? modifier,
border = true,
noBorder = false,
...rest
}) => (
<strong
className={classNames('nhsuk-tag', { [`nhsuk-tag--${modifier}`]: modifier }, className)}
className={classNames(
'nhsuk-tag',
{
[`nhsuk-tag--${colour}`]: colour,
'nhsuk-tag--no-border': noBorder || !border,
},
className,
)}
{...rest}
/>
);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ describe('Tag', () => {
expect(container.querySelector('strong.nhsuk-tag')).toBeTruthy();
});

it.each<ComponentPropsWithoutRef<typeof Tag>['modifier']>([
it.each<ComponentPropsWithoutRef<typeof Tag>['colour']>([
'white',
'grey',
'green',
Expand All @@ -28,7 +28,7 @@ describe('Tag', () => {
'orange',
'yellow',
])('adds colour class %s ', (colour) => {
const { container } = render(<Tag modifier={colour} />);
const { container } = render(<Tag colour={colour} />);

expect(container.querySelector(`strong.nhsuk-tag.nhsuk-tag--${colour}`)).toBeTruthy();
});
Expand Down
43 changes: 35 additions & 8 deletions src/components/form-elements/button/Button.tsx
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
/* eslint-disable @typescript-eslint/no-deprecated */
'use client';

import classNames from 'classnames';
Expand Down Expand Up @@ -26,24 +27,48 @@
}

interface ButtonBaseProps {
small?: boolean;
variant?: 'brand' | 'login' | 'reverse' | 'secondary' | 'secondary-solid' | 'warning';
preventDoubleClick?: boolean;

/**
* @deprecated Use `variant` instead.
*/
secondary?: boolean;

/**
* @deprecated Use `variant` instead.
*/
secondarySolid?: boolean;

/**
* @deprecated Use `variant` instead.
*/
reverse?: boolean;

/**
* @deprecated Use `variant` instead.
*/
warning?: boolean;

/**
* @deprecated Use `variant` instead.
*/
login?: boolean;
small?: boolean;
preventDoubleClick?: boolean;
}

function getButtonClassNames(props: ButtonProps | ButtonLinkProps) {
return classNames(
'nhsuk-button',
{ 'nhsuk-button--secondary': props.secondary },
{ 'nhsuk-button--secondary-solid': props.secondarySolid },
{ 'nhsuk-button--reverse': props.reverse },
{ 'nhsuk-button--warning': props.warning },
{ 'nhsuk-button--login': props.login },
{ 'nhsuk-button--small': props.small },
{
'nhsuk-button--secondary': props.variant === 'secondary' || props.secondary,

Check warning on line 64 in src/components/form-elements/button/Button.tsx

View check run for this annotation

SonarQubeCloud / SonarCloud Code Analysis

'secondary' is deprecated.

See more on https://sonarcloud.io/project/issues?id=NHSDigital_nhsuk-react-components&issues=AZ7Ln_silBkZ12ex1qAH&open=AZ7Ln_silBkZ12ex1qAH&pullRequest=391
'nhsuk-button--secondary-solid': props.variant === 'secondary-solid' || props.secondarySolid,

Check warning on line 65 in src/components/form-elements/button/Button.tsx

View check run for this annotation

SonarQubeCloud / SonarCloud Code Analysis

'secondarySolid' is deprecated.

See more on https://sonarcloud.io/project/issues?id=NHSDigital_nhsuk-react-components&issues=AZ7Ln_silBkZ12ex1qAI&open=AZ7Ln_silBkZ12ex1qAI&pullRequest=391
'nhsuk-button--reverse': props.variant === 'reverse' || props.reverse,

Check warning on line 66 in src/components/form-elements/button/Button.tsx

View check run for this annotation

SonarQubeCloud / SonarCloud Code Analysis

'reverse' is deprecated.

See more on https://sonarcloud.io/project/issues?id=NHSDigital_nhsuk-react-components&issues=AZ7Ln_silBkZ12ex1qAJ&open=AZ7Ln_silBkZ12ex1qAJ&pullRequest=391
'nhsuk-button--warning': props.variant === 'warning' || props.warning,

Check warning on line 67 in src/components/form-elements/button/Button.tsx

View check run for this annotation

SonarQubeCloud / SonarCloud Code Analysis

'warning' is deprecated.

See more on https://sonarcloud.io/project/issues?id=NHSDigital_nhsuk-react-components&issues=AZ7Ln_silBkZ12ex1qAK&open=AZ7Ln_silBkZ12ex1qAK&pullRequest=391
'nhsuk-button--login': props.variant === 'login' || props.login,

Check warning on line 68 in src/components/form-elements/button/Button.tsx

View check run for this annotation

SonarQubeCloud / SonarCloud Code Analysis

'login' is deprecated.

See more on https://sonarcloud.io/project/issues?id=NHSDigital_nhsuk-react-components&issues=AZ7Ln_silBkZ12ex1qAL&open=AZ7Ln_silBkZ12ex1qAL&pullRequest=391
'nhsuk-button--brand': props.variant === 'brand',
'nhsuk-button--small': props.small,
},
props.className,
);
}
Expand All @@ -53,12 +78,13 @@
className,
asElement: Element = 'button',
disabled,
secondary,

Check warning on line 81 in src/components/form-elements/button/Button.tsx

View check run for this annotation

SonarQubeCloud / SonarCloud Code Analysis

'secondary' is deprecated.

See more on https://sonarcloud.io/project/issues?id=NHSDigital_nhsuk-react-components&issues=AZ7Ln_silBkZ12ex1qAM&open=AZ7Ln_silBkZ12ex1qAM&pullRequest=391
secondarySolid,

Check warning on line 82 in src/components/form-elements/button/Button.tsx

View check run for this annotation

SonarQubeCloud / SonarCloud Code Analysis

'secondarySolid' is deprecated.

See more on https://sonarcloud.io/project/issues?id=NHSDigital_nhsuk-react-components&issues=AZ7Ln_silBkZ12ex1qAN&open=AZ7Ln_silBkZ12ex1qAN&pullRequest=391
reverse,

Check warning on line 83 in src/components/form-elements/button/Button.tsx

View check run for this annotation

SonarQubeCloud / SonarCloud Code Analysis

'reverse' is deprecated.

See more on https://sonarcloud.io/project/issues?id=NHSDigital_nhsuk-react-components&issues=AZ7Ln_silBkZ12ex1qAO&open=AZ7Ln_silBkZ12ex1qAO&pullRequest=391
warning,

Check warning on line 84 in src/components/form-elements/button/Button.tsx

View check run for this annotation

SonarQubeCloud / SonarCloud Code Analysis

'warning' is deprecated.

See more on https://sonarcloud.io/project/issues?id=NHSDigital_nhsuk-react-components&issues=AZ7Ln_silBkZ12ex1qAP&open=AZ7Ln_silBkZ12ex1qAP&pullRequest=391
login,

Check warning on line 85 in src/components/form-elements/button/Button.tsx

View check run for this annotation

SonarQubeCloud / SonarCloud Code Analysis

'login' is deprecated.

See more on https://sonarcloud.io/project/issues?id=NHSDigital_nhsuk-react-components&issues=AZ7Ln_silBkZ12ex1qAQ&open=AZ7Ln_silBkZ12ex1qAQ&pullRequest=391
small,
variant,
type = 'submit',
preventDoubleClick,
onClick,
Expand Down Expand Up @@ -113,12 +139,13 @@
const {
className,
asElement: Element = 'a',
secondary,

Check warning on line 142 in src/components/form-elements/button/Button.tsx

View check run for this annotation

SonarQubeCloud / SonarCloud Code Analysis

'secondary' is deprecated.

See more on https://sonarcloud.io/project/issues?id=NHSDigital_nhsuk-react-components&issues=AZ7Ln_silBkZ12ex1qAR&open=AZ7Ln_silBkZ12ex1qAR&pullRequest=391
secondarySolid,

Check warning on line 143 in src/components/form-elements/button/Button.tsx

View check run for this annotation

SonarQubeCloud / SonarCloud Code Analysis

'secondarySolid' is deprecated.

See more on https://sonarcloud.io/project/issues?id=NHSDigital_nhsuk-react-components&issues=AZ7Ln_silBkZ12ex1qAS&open=AZ7Ln_silBkZ12ex1qAS&pullRequest=391
reverse,

Check warning on line 144 in src/components/form-elements/button/Button.tsx

View check run for this annotation

SonarQubeCloud / SonarCloud Code Analysis

'reverse' is deprecated.

See more on https://sonarcloud.io/project/issues?id=NHSDigital_nhsuk-react-components&issues=AZ7Ln_silBkZ12ex1qAT&open=AZ7Ln_silBkZ12ex1qAT&pullRequest=391
warning,

Check warning on line 145 in src/components/form-elements/button/Button.tsx

View check run for this annotation

SonarQubeCloud / SonarCloud Code Analysis

'warning' is deprecated.

See more on https://sonarcloud.io/project/issues?id=NHSDigital_nhsuk-react-components&issues=AZ7Ln_silBkZ12ex1qAU&open=AZ7Ln_silBkZ12ex1qAU&pullRequest=391
login,

Check warning on line 146 in src/components/form-elements/button/Button.tsx

View check run for this annotation

SonarQubeCloud / SonarCloud Code Analysis

'login' is deprecated.

See more on https://sonarcloud.io/project/issues?id=NHSDigital_nhsuk-react-components&issues=AZ7Ln_silBkZ12ex1qAV&open=AZ7Ln_silBkZ12ex1qAV&pullRequest=391
small,
variant,
preventDoubleClick,
onClick,
...rest
Expand Down
Loading