Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
25 commits
Select commit Hold shift + click to select a range
0edac78
Fix Rollup duplicate `'use client'` directives
colinrotherham Oct 9, 2025
cbf3136
Remove unnecessary log suppression
colinrotherham Oct 9, 2025
8f9ad2d
Sync changelog entries with release notes
colinrotherham Oct 9, 2025
4b7c3df
Add changelog entry
colinrotherham Oct 9, 2025
dbc22c2
Add missing `'use client'` directives
colinrotherham Oct 13, 2025
9e1cafd
Export all multipart namespace components separately
colinrotherham Oct 13, 2025
f1871ab
Allow NHS.UK frontend errors to be caught
colinrotherham Oct 13, 2025
8f998c9
Remove unnnecessary header context
colinrotherham Oct 10, 2025
ee6a085
Make type guards compatible with server components
colinrotherham Oct 13, 2025
bfb5a67
Update migration guide
colinrotherham Oct 13, 2025
9737c3c
Update package version to v6.0.0-beta.2
colinrotherham Oct 13, 2025
a00d653
Add the Notification Banner introduced in NHS Frontend v10 (#283)
robkerrybjss Oct 9, 2025
161cb57
Fix circular dependency
robkerrybjss Oct 9, 2025
737c284
Address review comments
robkerrybjss Oct 10, 2025
5c38de7
Address review comments (sonar)
robkerrybjss Oct 10, 2025
4808877
Move notification banner header bar to main component
colinrotherham Oct 13, 2025
dcbd029
Export notification banner child components
colinrotherham Oct 13, 2025
8f12383
Allow NHS.UK frontend errors to be caught
colinrotherham Oct 13, 2025
e0ae00f
Add fallback `className` to component guards
colinrotherham Oct 13, 2025
1c43ecd
Reduce component filters
colinrotherham Oct 13, 2025
6ebc628
Address further review comments
robkerrybjss Oct 13, 2025
081b895
Address further review comments
robkerrybjss Oct 13, 2025
7eb6bf4
Address further review comments
robkerrybjss Oct 13, 2025
abc9b8f
Formatting
colinrotherham Oct 13, 2025
37641b4
Merge pull request #284 from robkerrybjss/add-notification-banner-com…
colinrotherham Oct 13, 2025
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
10 changes: 2 additions & 8 deletions .storybook/main.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import { type StorybookConfig } from '@storybook/react-vite';
import preserveDirectives from 'rollup-preserve-directives';
import { mergeConfig, type InlineConfig } from 'vite';
import tsConfigPaths from 'vite-tsconfig-paths';
import { isLogIgnored } from '../rollup.config.js';

const config: StorybookConfig = {
stories: ['../stories/**/*.stories.@(ts|tsx)', '../stories/**/*.mdx'],
Expand All @@ -19,13 +19,7 @@ const config: StorybookConfig = {
return mergeConfig(config, {
build: {
rollupOptions: {
onwarn(warning, handler) {
if (isLogIgnored(warning)) {
return;
}

handler(warning);
},
plugins: [preserveDirectives()],
},
},
css: {
Expand Down
12 changes: 9 additions & 3 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,20 +1,26 @@
# NHS.UK React components

## 6.0.0-beta.2 - 13 October 2025

This version provides support for NHS.UK frontend v10.x, React Server Components (RSC) and fixes a Rollup `'use client'` directive issue.

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).

## 6.0.0-beta.1 - 8 October 2025

This version adds the panel component from NHS.UK frontend v9.3.0 and supports React v19.
This version provides support for NHS.UK frontend v10.x and adds the [panel component](https://service-manual.nhs.uk/design-system/components/panel) from the NHS.UK design system. Support for React v19 is also included.

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).

## 6.0.0-beta.0 - 30 September 2025

This version provides support for nhsuk-frontend version 10.
This version provides support for NHS.UK frontend v10.x.

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).

## 5.0.0 - 4 November 2024

This version provides support for nhsuk-frontend version 9.
This version provides support for NHS.UK frontend v9.x.

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-5.0.md).

Expand Down
45 changes: 40 additions & 5 deletions docs/upgrade-to-6.0.md
Original file line number Diff line number Diff line change
Expand Up @@ -31,15 +31,45 @@ The [panel](https://service-manual.nhs.uk/design-system/components/panel) compon

This replaces the [list panel component](#list-panel) which was removed in NHS.UK frontend v6.0.0.

### Notification banner component

The [notification banner](https://service-manual.nhs.uk/design-system/components/notification-banner) component from NHS.UK frontend v10 has been added:

```jsx
<NotificationBanner>
<NotificationBanner.Heading>Upcoming maintenance</NotificationBanner.Heading>
<p>The service will be unavailable from 8pm to 9pm on Thursday 1 January 2025.</p>
</NotificationBanner>
```

### Support for React Server Components (RSC)

All components have been tested as React Server Components (RSC) but due to [multipart namespace component limitations](https://ivicabatinic.from.hr/posts/multipart-namespace-components-addressing-rsc-and-dot-notation-issues) an alternative syntax (without dot notation) can be used as a workaround:

```patch
<Pagination>
- <Pagination.Link href="/section/treatments" previous>
+ <PaginationLink href="/section/treatments" previous>
Treatments
- </Pagination.Link>
+ </PaginationLink>
- <Pagination.Link href="/section/symptoms" next>
+ <PaginationLink href="/section/symptoms" next>
Symptoms
- </Pagination.Link>
+ </PaginationLink>
</Pagination>
```

## Breaking changes

### Update the JavaScript supported script snippet

You must now use the NHS.UK frontend v10.x feature detection snippet to check for `<script type="module">`. This change enables styling for JavaScript only features in [supported browsers]() only:
You must now use the NHS.UK frontend v10.x feature detection snippet to check for `<script type="module">`. This change enables styling for JavaScript features in [supported browsers]() only:

```patch
- <body class="js-enabled">
+ <body>
+ <body suppressHydrationWarning>
+ <script>document.body.className += ' js-enabled' + ('noModule' in HTMLScriptElement.prototype ? ' nhsuk-frontend-supported' : '');</script>
```

Expand Down Expand Up @@ -239,22 +269,26 @@ The custom `autoSelectNext` prop is no longer supported.

The updated header component from NHS.UK frontend v10.x has been added. You will need to make the following changes:

- move `Header.Logo` props to `<Header logo={{ href: '/' }}>`
- move `Header.ServiceName` props to `<Header service={{ text: "Manage patients" }}>`
- remove the wrapping `Header.Container` component
- remove the wrapping `Header.Content` component
- remove the automatically created `Header.Logo` component
- remove the automatically created `Header.ServiceName` component
- remove the automatically created `Header.NavDropdownMenu` component
- rename the `Header.Nav` component to `Header.Navigation`
- rename the `Header.NavItem` component to `Header.NavigationItem`

```patch
<Header>
- <Header>
+ <Header service={{ text: "Manage patients", href: '/' }}>
- <Header.Container>
- <Header.Logo href="/" />
- <Header.ServiceName href="/">Manage patients</Header.ServiceName>
- <Header.Content>
- <Header.Search />
- </Header.Content>
- </Header.Container>
+ <Header.Logo href="/" />
+ <Header.Search />
- <Header.Nav>
- <Header.NavItem href="#">Example 1</Header.NavItem>
Expand Down Expand Up @@ -417,8 +451,9 @@ You must rename the `Select` prop `selectRef` to `ref` for consistency with othe
To align with NHS.UK frontend, the skip link component focuses the main content rather than the first heading on the page:

```html
<main class="nhsuk-main-wrapper id="maincontent">
<main class="nhsuk-main-wrapper" id="maincontent">
<!-- // ... -->
</main>
```

For accessibility reasons, you must make the following changes:
Expand Down
4 changes: 2 additions & 2 deletions package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "nhsuk-react-components",
"version": "6.0.0-beta.1",
"version": "6.0.0-beta.2",
"license": "MIT",
"author": {
"name": "NHS England"
Expand Down Expand Up @@ -113,7 +113,7 @@
"react": "^19.2.0",
"react-dom": "^19.2.0",
"rollup": "^4.52.4",
"rollup-plugin-preserve-directives": "^0.4.0",
"rollup-preserve-directives": "^1.1.3",
"sass-embedded": "^1.93.2",
"storybook": "^9.1.10",
"tslib": "^2.8.1",
Expand Down
26 changes: 4 additions & 22 deletions rollup.config.js
Original file line number Diff line number Diff line change
@@ -1,9 +1,10 @@
import { join } from 'node:path';
import { DEFAULT_EXTENSIONS as extensions } from '@babel/core';
import { babel } from '@rollup/plugin-babel';
import commonjs from '@rollup/plugin-commonjs';
import { nodeResolve } from '@rollup/plugin-node-resolve';
import typescript from '@rollup/plugin-typescript';
import preserveDirectives from 'rollup-plugin-preserve-directives';
import preserveDirectives from 'rollup-preserve-directives';
import { defineConfig } from 'rollup';
import packageJson from './package.json' with { type: 'json' };
import tsBuildConfig from './tsconfig.build.json' with { type: 'json' };
Expand Down Expand Up @@ -58,37 +59,18 @@ export default defineConfig(
babel({
babelHelpers: 'bundled',
exclude: 'node_modules/**',
extensions: [...extensions, '.ts', '.tsx'],
}),
],

// Handle warnings as errors
onwarn(warning) {
if (isLogIgnored(warning)) {
return;
}

throw new Error(warning.message, { cause: warning });
},
}),
),
);

/**
* Whether to ignore Rollup log messages
*
* @param {RollupLog} warning
*/
export function isLogIgnored(warning) {
const { code, message } = warning;

// Skip warnings related to "use client" directives including
// source map issues when directives are bundled by Storybook
return (
code === 'SOURCEMAP_ERROR' ||
(code === 'MODULE_LEVEL_DIRECTIVE' && message.includes('"use client"'))
);
}

/**
* @import { OutputOptions, RollupLog, RollupOptions } from 'rollup'
* @import { OutputOptions, RollupOptions } from 'rollup'
*/
65 changes: 65 additions & 0 deletions src/__tests__/index.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,36 +13,74 @@ describe('Index', () => {
'BackLink',
'BodyText',
'Breadcrumb',
'BreadcrumbBack',
'BreadcrumbItem',
'Button',
'Card',
'CardContent',
'CardContext',
'CardDescription',
'CardGroup',
'CardGroupItem',
'CardHeading',
'CardImage',
'CardLink',
'cardTypeIsCareCard',
'CharacterCount',
'Checkboxes',
'CheckboxesContext',
'CheckboxesDivider',
'CheckboxesItem',
'ChevronRightCircleIcon',
'childIsOfComponentType',
'Clearfix',
'Col',
'Container',
'ContentsList',
'ContentsListItem',
'CrossIcon',
'DateInput',
'DateInputContext',
'DateInputDay',
'DateInputMonth',
'DateInputYear',
'Details',
'DetailsExpanderGroup',
'DetailsSummary',
'DetailsText',
'DoAndDontList',
'DoAndDontListContext',
'DoAndDontListItem',
'ErrorMessage',
'ErrorSummary',
'ErrorSummaryList',
'ErrorSummaryListItem',
'ErrorSummaryTitle',
'Fieldset',
'Footer',
'FooterCopyright',
'FooterList',
'FooterListItem',
'FooterMeta',
'Form',
'FormContext',
'FormGroup',
'FormGroupContext',
'Header',
'HeaderAccount',
'HeaderAccountItem',
'HeaderContext',
'HeaderLogo',
'HeaderMenuToggle',
'HeaderNavigation',
'HeaderNavigationItem',
'HeaderSearch',
'HeaderServiceName',
'HeadingLevel',
'Hero',
'HeroContent',
'HeroHeading',
'HeroText',
'HintText',
'Icon',
'Images',
Expand All @@ -51,29 +89,56 @@ describe('Index', () => {
'LedeText',
'Legend',
'NavAZ',
'NavAZDisabledItem',
'NavAZLinkItem',
'NotificationBanner',
'NotificationBannerHeading',
'NotificationBannerLink',
'NotificationBannerTitle',
'Pagination',
'PaginationLink',
'Panel',
'PanelTitle',
'Radios',
'RadiosContext',
'RadiosDivider',
'RadiosItem',
'ReadingWidth',
'ReviewDate',
'Row',
'SearchIcon',
'Select',
'SelectOption',
'SkipLink',
'SummaryList',
'SummaryListActions',
'SummaryListKey',
'SummaryListRow',
'SummaryListValue',
'Table',
'TableBody',
'TableCaption',
'TableCell',
'TableContainer',
'TableContext',
'TableHead',
'TablePanel',
'TableRow',
'TableSection',
'TableSectionContext',
'Tabs',
'TabsContents',
'TabsList',
'TabsListItem',
'TabsTitle',
'Tag',
'Textarea',
'TextInput',
'TickIcon',
'useFormContext',
'UserIcon',
'WarningCallout',
'WarningCalloutHeading',
]);
});
});
15 changes: 8 additions & 7 deletions src/components/content-presentation/details/Details.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ const DetailsComponent = forwardRef<HTMLDetailsElement, DetailsProps>(
),
);

const DetailsSummary = forwardRef<HTMLElement, ComponentPropsWithoutRef<'div'>>(
export const DetailsSummary = forwardRef<HTMLElement, ComponentPropsWithoutRef<'div'>>(
({ children, className, ...rest }, forwardedRef) => (
<summary
className={classNames('nhsuk-details__summary', className)}
Expand All @@ -27,21 +27,22 @@ const DetailsSummary = forwardRef<HTMLElement, ComponentPropsWithoutRef<'div'>>(
),
);

const DetailsText: FC<ComponentPropsWithoutRef<'div'>> = ({ className, ...rest }) => (
export const DetailsText: FC<ComponentPropsWithoutRef<'div'>> = ({ className, ...rest }) => (
<div className={classNames('nhsuk-details__text', className)} {...rest} />
);

const ExpanderGroup: FC<ComponentPropsWithoutRef<'div'>> = ({ className, ...rest }) => (
<div className={classNames('nhsuk-expander-group', className)} {...rest} />
);
export const DetailsExpanderGroup: FC<ComponentPropsWithoutRef<'div'>> = ({
className,
...rest
}) => <div className={classNames('nhsuk-expander-group', className)} {...rest} />;

DetailsComponent.displayName = 'Details';
DetailsSummary.displayName = 'Details.Summary';
DetailsText.displayName = 'Details.Text';
ExpanderGroup.displayName = 'Details.ExpanderGroup';
DetailsExpanderGroup.displayName = 'Details.ExpanderGroup';

export const Details = Object.assign(DetailsComponent, {
Summary: DetailsSummary,
Text: DetailsText,
ExpanderGroup,
ExpanderGroup: DetailsExpanderGroup,
});
Loading