Skip to content

Commit 8d13ff4

Browse files
Add support for React Server Components (RSC), fix Rollup duplicate 'use client' directives, prepare beta release (#285)
* Fix Rollup duplicate `'use client'` directives * Remove unnecessary log suppression * Sync changelog entries with release notes * Add changelog entry * Add missing `'use client'` directives * Export all multipart namespace components separately * Allow NHS.UK frontend errors to be caught * Remove unnnecessary header context * Make type guards compatible with server components * Update migration guide * Update package version to v6.0.0-beta.2 * Add the Notification Banner introduced in NHS Frontend v10 (#283) * Fix circular dependency * Address review comments * Address review comments (sonar) * Move notification banner header bar to main component * Export notification banner child components * Allow NHS.UK frontend errors to be caught * Add fallback `className` to component guards * Reduce component filters * Address further review comments * Address further review comments * Address further review comments * Formatting --------- Co-authored-by: Rob Kerry <[email protected]>
1 parent 8274f92 commit 8d13ff4

File tree

97 files changed

+2260
-616
lines changed

Some content is hidden

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

97 files changed

+2260
-616
lines changed

.storybook/main.ts

Lines changed: 2 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
import { type StorybookConfig } from '@storybook/react-vite';
2+
import preserveDirectives from 'rollup-preserve-directives';
23
import { mergeConfig, type InlineConfig } from 'vite';
34
import tsConfigPaths from 'vite-tsconfig-paths';
4-
import { isLogIgnored } from '../rollup.config.js';
55

66
const config: StorybookConfig = {
77
stories: ['../stories/**/*.stories.@(ts|tsx)', '../stories/**/*.mdx'],
@@ -19,13 +19,7 @@ const config: StorybookConfig = {
1919
return mergeConfig(config, {
2020
build: {
2121
rollupOptions: {
22-
onwarn(warning, handler) {
23-
if (isLogIgnored(warning)) {
24-
return;
25-
}
26-
27-
handler(warning);
28-
},
22+
plugins: [preserveDirectives()],
2923
},
3024
},
3125
css: {

CHANGELOG.md

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,20 +1,26 @@
11
# NHS.UK React components
22

3+
## 6.0.0-beta.2 - 13 October 2025
4+
5+
This version provides support for NHS.UK frontend v10.x, React Server Components (RSC) and fixes a Rollup `'use client'` directive issue.
6+
7+
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).
8+
39
## 6.0.0-beta.1 - 8 October 2025
410

5-
This version adds the panel component from NHS.UK frontend v9.3.0 and supports React v19.
11+
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.
612

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

915
## 6.0.0-beta.0 - 30 September 2025
1016

11-
This version provides support for nhsuk-frontend version 10.
17+
This version provides support for NHS.UK frontend v10.x.
1218

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

1521
## 5.0.0 - 4 November 2024
1622

17-
This version provides support for nhsuk-frontend version 9.
23+
This version provides support for NHS.UK frontend v9.x.
1824

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

docs/upgrade-to-6.0.md

Lines changed: 40 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -31,15 +31,45 @@ The [panel](https://service-manual.nhs.uk/design-system/components/panel) compon
3131

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

34+
### Notification banner component
35+
36+
The [notification banner](https://service-manual.nhs.uk/design-system/components/notification-banner) component from NHS.UK frontend v10 has been added:
37+
38+
```jsx
39+
<NotificationBanner>
40+
<NotificationBanner.Heading>Upcoming maintenance</NotificationBanner.Heading>
41+
<p>The service will be unavailable from 8pm to 9pm on Thursday 1 January 2025.</p>
42+
</NotificationBanner>
43+
```
44+
45+
### Support for React Server Components (RSC)
46+
47+
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:
48+
49+
```patch
50+
<Pagination>
51+
- <Pagination.Link href="/section/treatments" previous>
52+
+ <PaginationLink href="/section/treatments" previous>
53+
Treatments
54+
- </Pagination.Link>
55+
+ </PaginationLink>
56+
- <Pagination.Link href="/section/symptoms" next>
57+
+ <PaginationLink href="/section/symptoms" next>
58+
Symptoms
59+
- </Pagination.Link>
60+
+ </PaginationLink>
61+
</Pagination>
62+
```
63+
3464
## Breaking changes
3565

3666
### Update the JavaScript supported script snippet
3767

38-
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:
68+
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:
3969

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

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

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

272+
- move `Header.Logo` props to `<Header logo={{ href: '/' }}>`
273+
- move `Header.ServiceName` props to `<Header service={{ text: "Manage patients" }}>`
242274
- remove the wrapping `Header.Container` component
243275
- remove the wrapping `Header.Content` component
276+
- remove the automatically created `Header.Logo` component
244277
- remove the automatically created `Header.ServiceName` component
245278
- remove the automatically created `Header.NavDropdownMenu` component
246279
- rename the `Header.Nav` component to `Header.Navigation`
247280
- rename the `Header.NavItem` component to `Header.NavigationItem`
248281

249282
```patch
250-
<Header>
283+
- <Header>
284+
+ <Header service={{ text: "Manage patients", href: '/' }}>
251285
- <Header.Container>
252286
- <Header.Logo href="/" />
287+
- <Header.ServiceName href="/">Manage patients</Header.ServiceName>
253288
- <Header.Content>
254289
- <Header.Search />
255290
- </Header.Content>
256291
- </Header.Container>
257-
+ <Header.Logo href="/" />
258292
+ <Header.Search />
259293
- <Header.Nav>
260294
- <Header.NavItem href="#">Example 1</Header.NavItem>
@@ -417,8 +451,9 @@ You must rename the `Select` prop `selectRef` to `ref` for consistency with othe
417451
To align with NHS.UK frontend, the skip link component focuses the main content rather than the first heading on the page:
418452

419453
```html
420-
<main class="nhsuk-main-wrapper id="maincontent">
454+
<main class="nhsuk-main-wrapper" id="maincontent">
421455
<!-- // ... -->
456+
</main>
422457
```
423458

424459
For accessibility reasons, you must make the following changes:

package.json

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "nhsuk-react-components",
3-
"version": "6.0.0-beta.1",
3+
"version": "6.0.0-beta.2",
44
"license": "MIT",
55
"author": {
66
"name": "NHS England"
@@ -113,7 +113,7 @@
113113
"react": "^19.2.0",
114114
"react-dom": "^19.2.0",
115115
"rollup": "^4.52.4",
116-
"rollup-plugin-preserve-directives": "^0.4.0",
116+
"rollup-preserve-directives": "^1.1.3",
117117
"sass-embedded": "^1.93.2",
118118
"storybook": "^9.1.10",
119119
"tslib": "^2.8.1",

rollup.config.js

Lines changed: 4 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,10 @@
11
import { join } from 'node:path';
2+
import { DEFAULT_EXTENSIONS as extensions } from '@babel/core';
23
import { babel } from '@rollup/plugin-babel';
34
import commonjs from '@rollup/plugin-commonjs';
45
import { nodeResolve } from '@rollup/plugin-node-resolve';
56
import typescript from '@rollup/plugin-typescript';
6-
import preserveDirectives from 'rollup-plugin-preserve-directives';
7+
import preserveDirectives from 'rollup-preserve-directives';
78
import { defineConfig } from 'rollup';
89
import packageJson from './package.json' with { type: 'json' };
910
import tsBuildConfig from './tsconfig.build.json' with { type: 'json' };
@@ -58,37 +59,18 @@ export default defineConfig(
5859
babel({
5960
babelHelpers: 'bundled',
6061
exclude: 'node_modules/**',
62+
extensions: [...extensions, '.ts', '.tsx'],
6163
}),
6264
],
6365

6466
// Handle warnings as errors
6567
onwarn(warning) {
66-
if (isLogIgnored(warning)) {
67-
return;
68-
}
69-
7068
throw new Error(warning.message, { cause: warning });
7169
},
7270
}),
7371
),
7472
);
7573

7674
/**
77-
* Whether to ignore Rollup log messages
78-
*
79-
* @param {RollupLog} warning
80-
*/
81-
export function isLogIgnored(warning) {
82-
const { code, message } = warning;
83-
84-
// Skip warnings related to "use client" directives including
85-
// source map issues when directives are bundled by Storybook
86-
return (
87-
code === 'SOURCEMAP_ERROR' ||
88-
(code === 'MODULE_LEVEL_DIRECTIVE' && message.includes('"use client"'))
89-
);
90-
}
91-
92-
/**
93-
* @import { OutputOptions, RollupLog, RollupOptions } from 'rollup'
75+
* @import { OutputOptions, RollupOptions } from 'rollup'
9476
*/

src/__tests__/index.test.ts

Lines changed: 65 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,36 +13,74 @@ describe('Index', () => {
1313
'BackLink',
1414
'BodyText',
1515
'Breadcrumb',
16+
'BreadcrumbBack',
17+
'BreadcrumbItem',
1618
'Button',
1719
'Card',
20+
'CardContent',
1821
'CardContext',
22+
'CardDescription',
23+
'CardGroup',
24+
'CardGroupItem',
25+
'CardHeading',
26+
'CardImage',
27+
'CardLink',
1928
'cardTypeIsCareCard',
2029
'CharacterCount',
2130
'Checkboxes',
2231
'CheckboxesContext',
32+
'CheckboxesDivider',
33+
'CheckboxesItem',
2334
'ChevronRightCircleIcon',
2435
'childIsOfComponentType',
2536
'Clearfix',
2637
'Col',
2738
'Container',
2839
'ContentsList',
40+
'ContentsListItem',
2941
'CrossIcon',
3042
'DateInput',
3143
'DateInputContext',
44+
'DateInputDay',
45+
'DateInputMonth',
46+
'DateInputYear',
3247
'Details',
48+
'DetailsExpanderGroup',
49+
'DetailsSummary',
50+
'DetailsText',
3351
'DoAndDontList',
52+
'DoAndDontListContext',
53+
'DoAndDontListItem',
3454
'ErrorMessage',
3555
'ErrorSummary',
56+
'ErrorSummaryList',
57+
'ErrorSummaryListItem',
58+
'ErrorSummaryTitle',
3659
'Fieldset',
3760
'Footer',
61+
'FooterCopyright',
62+
'FooterList',
63+
'FooterListItem',
64+
'FooterMeta',
3865
'Form',
3966
'FormContext',
4067
'FormGroup',
4168
'FormGroupContext',
4269
'Header',
70+
'HeaderAccount',
71+
'HeaderAccountItem',
4372
'HeaderContext',
73+
'HeaderLogo',
74+
'HeaderMenuToggle',
75+
'HeaderNavigation',
76+
'HeaderNavigationItem',
77+
'HeaderSearch',
78+
'HeaderServiceName',
4479
'HeadingLevel',
4580
'Hero',
81+
'HeroContent',
82+
'HeroHeading',
83+
'HeroText',
4684
'HintText',
4785
'Icon',
4886
'Images',
@@ -51,29 +89,56 @@ describe('Index', () => {
5189
'LedeText',
5290
'Legend',
5391
'NavAZ',
92+
'NavAZDisabledItem',
93+
'NavAZLinkItem',
94+
'NotificationBanner',
95+
'NotificationBannerHeading',
96+
'NotificationBannerLink',
97+
'NotificationBannerTitle',
5498
'Pagination',
99+
'PaginationLink',
55100
'Panel',
101+
'PanelTitle',
56102
'Radios',
57103
'RadiosContext',
104+
'RadiosDivider',
105+
'RadiosItem',
58106
'ReadingWidth',
59107
'ReviewDate',
60108
'Row',
61109
'SearchIcon',
62110
'Select',
111+
'SelectOption',
63112
'SkipLink',
64113
'SummaryList',
114+
'SummaryListActions',
115+
'SummaryListKey',
116+
'SummaryListRow',
117+
'SummaryListValue',
65118
'Table',
119+
'TableBody',
120+
'TableCaption',
121+
'TableCell',
122+
'TableContainer',
66123
'TableContext',
124+
'TableHead',
125+
'TablePanel',
126+
'TableRow',
67127
'TableSection',
68128
'TableSectionContext',
69129
'Tabs',
130+
'TabsContents',
131+
'TabsList',
132+
'TabsListItem',
133+
'TabsTitle',
70134
'Tag',
71135
'Textarea',
72136
'TextInput',
73137
'TickIcon',
74138
'useFormContext',
75139
'UserIcon',
76140
'WarningCallout',
141+
'WarningCalloutHeading',
77142
]);
78143
});
79144
});

src/components/content-presentation/details/Details.tsx

Lines changed: 8 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ const DetailsComponent = forwardRef<HTMLDetailsElement, DetailsProps>(
1515
),
1616
);
1717

18-
const DetailsSummary = forwardRef<HTMLElement, ComponentPropsWithoutRef<'div'>>(
18+
export const DetailsSummary = forwardRef<HTMLElement, ComponentPropsWithoutRef<'div'>>(
1919
({ children, className, ...rest }, forwardedRef) => (
2020
<summary
2121
className={classNames('nhsuk-details__summary', className)}
@@ -27,21 +27,22 @@ const DetailsSummary = forwardRef<HTMLElement, ComponentPropsWithoutRef<'div'>>(
2727
),
2828
);
2929

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

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

3839
DetailsComponent.displayName = 'Details';
3940
DetailsSummary.displayName = 'Details.Summary';
4041
DetailsText.displayName = 'Details.Text';
41-
ExpanderGroup.displayName = 'Details.ExpanderGroup';
42+
DetailsExpanderGroup.displayName = 'Details.ExpanderGroup';
4243

4344
export const Details = Object.assign(DetailsComponent, {
4445
Summary: DetailsSummary,
4546
Text: DetailsText,
46-
ExpanderGroup,
47+
ExpanderGroup: DetailsExpanderGroup,
4748
});

0 commit comments

Comments
 (0)