Skip to content

Commit bf27421

Browse files
committed
Address review comments
1 parent e704151 commit bf27421

File tree

9 files changed

+860
-50
lines changed

9 files changed

+860
-50
lines changed

docs/upgrade-to-6.0.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -36,7 +36,7 @@ This replaces the [list panel component](#list-panel) which was removed in NHS.U
3636
The [notification banner](https://service-manual.nhs.uk/design-system/components/notification-banner) component from NHS.UK frontend v10 has been added:
3737

3838
```jsx
39-
<NotificationBanner title="Important Message">
39+
<NotificationBanner>
4040
<NotificationBanner.Heading>Upcoming Maintenance</NotificationBanner.Heading>
4141
<p>The service will be unavailable from 8pm to 9pm on Thursday 1 January 2025.</p>
4242
</NotificationBanner>
@@ -428,7 +428,7 @@ You must rename the `Select` prop `selectRef` to `ref` for consistency with othe
428428
To align with NHS.UK frontend, the skip link component focuses the main content rather than the first heading on the page:
429429

430430
```html
431-
<main class="nhsuk-main-wrapper id="maincontent">
431+
<main class="nhsuk-main-wrapper" id="maincontent">
432432
<!-- // ... -->
433433
```
434434

Lines changed: 56 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -1,44 +1,82 @@
1-
import { type ComponentPropsWithoutRef, forwardRef } from 'react';
1+
import {
2+
Children,
3+
type ComponentPropsWithoutRef,
4+
createRef,
5+
forwardRef,
6+
useEffect,
7+
useState,
8+
} from 'react';
29
import classNames from 'classnames';
3-
import { HeadingLevel } from '#components/utils/HeadingLevel.js';
4-
import { NotificationBannerHeading, NotificationBannerLink } from './components/index.js';
10+
import {
11+
NotificationBannerHeading,
12+
NotificationBannerLink,
13+
NotificationBannerTitle,
14+
} from './components/index.js';
15+
import { type NotificationBanner as NotificationBannerModule } from 'nhsuk-frontend';
16+
import { childIsOfComponentType } from '#util/types/TypeGuards.js';
517

618
export interface NotificationBannerProps extends ComponentPropsWithoutRef<'div'> {
719
success?: boolean;
20+
disableAutoFocus?: boolean;
821
}
922

1023
const NotificationBannerComponent = forwardRef<HTMLDivElement, NotificationBannerProps>(
11-
({ children, className, title, success, ...rest }, forwardedRef) => {
24+
({ children, className, title, success, role, disableAutoFocus, ...rest }, forwardedRef) => {
25+
const [moduleRef] = useState(() => forwardedRef || createRef<HTMLDivElement>());
26+
const [instance, setInstance] = useState<NotificationBannerModule>();
27+
28+
useEffect(() => {
29+
if (!('current' in moduleRef) || !moduleRef.current || instance) {
30+
return;
31+
}
32+
33+
const { current: $root } = moduleRef;
34+
35+
import('nhsuk-frontend').then(({ NotificationBanner }) => {
36+
setInstance(new NotificationBanner($root));
37+
});
38+
}, [moduleRef, instance]);
39+
40+
const items = Children.toArray(children);
41+
const titleElement = items.find((child) =>
42+
childIsOfComponentType(child, NotificationBannerTitle),
43+
) || <NotificationBannerTitle success={success}>{title}</NotificationBannerTitle>;
44+
const nonTitleItems = items.filter(
45+
(child) => !childIsOfComponentType(child, NotificationBannerTitle),
46+
);
47+
const headerElement = nonTitleItems.find((child) =>
48+
childIsOfComponentType(child, NotificationBannerHeading),
49+
);
50+
const bodyItems = nonTitleItems.filter(
51+
(child) => !childIsOfComponentType(child, NotificationBannerHeading),
52+
);
1253
return (
13-
<section
54+
<div
1455
className={classNames(
1556
'nhsuk-notification-banner',
1657
{ 'nhsuk-notification-banner--success': success },
1758
className,
1859
)}
19-
aria-labelledby="nhsuk-notification-banner-title"
60+
aria-labelledby={titleElement.props.id || 'nhsuk-notification-banner-title'}
2061
data-module="nhsuk-notification-banner"
62+
data-disable-auto-focus={disableAutoFocus}
63+
ref={moduleRef}
64+
role={role || (success ? 'alert' : 'region')}
2165
>
22-
<div className="nhsuk-notification-banner__header">
23-
<HeadingLevel
24-
className="nhsuk-notification-banner__title"
25-
headingLevel={'h2'}
26-
id="nhsuk-notification-banner-title"
27-
>
28-
{title || (success ? 'Success' : 'Important')}
29-
</HeadingLevel>
30-
</div>
31-
<div className={'nhsuk-notification-banner__content'} ref={forwardedRef} {...rest}>
32-
{children}
66+
{titleElement}
67+
<div className={'nhsuk-notification-banner__content'} {...rest}>
68+
{headerElement}
69+
{bodyItems}
3370
</div>
34-
</section>
71+
</div>
3572
);
3673
},
3774
);
3875

3976
NotificationBannerComponent.displayName = 'NotificationBanner';
4077

4178
export const NotificationBanner = Object.assign(NotificationBannerComponent, {
79+
Title: NotificationBannerTitle,
4280
Heading: NotificationBannerHeading,
4381
Link: NotificationBannerLink,
4482
});

0 commit comments

Comments
 (0)