-
Notifications
You must be signed in to change notification settings - Fork 36
Expand file tree
/
Copy pathNotificationBanner.tsx
More file actions
101 lines (84 loc) · 3.02 KB
/
NotificationBanner.tsx
File metadata and controls
101 lines (84 loc) · 3.02 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
'use client';
import classNames from 'classnames';
import { type NotificationBanner as NotificationBannerModule } from 'nhsuk-frontend';
import {
Children,
type ComponentPropsWithoutRef,
forwardRef,
useEffect,
useImperativeHandle,
useRef,
useState,
} from 'react';
import { childIsOfComponentType } from '#util/types/TypeGuards.js';
import {
NotificationBannerHeading,
NotificationBannerLink,
NotificationBannerTitle,
} from './components/index.js';
export interface NotificationBannerProps extends ComponentPropsWithoutRef<'div'> {
success?: boolean;
disableAutoFocus?: boolean;
titleId?: string;
}
const NotificationBannerComponent = forwardRef<HTMLDivElement, NotificationBannerProps>(
(props, forwardedRef) => {
const { children, className, title, titleId, success, role, disableAutoFocus, ...rest } = props;
const moduleRef = useRef<HTMLDivElement>(null);
const importRef = useRef<Promise<NotificationBannerModule | void>>(null);
const [instanceError, setInstanceError] = useState<Error>();
const [instance, setInstance] = useState<NotificationBannerModule>();
useImperativeHandle(forwardedRef, () => moduleRef.current!, [moduleRef]);
useEffect(() => {
if (!moduleRef.current || importRef.current || instance) {
return;
}
importRef.current = import('nhsuk-frontend')
.then(({ NotificationBanner }) => setInstance(new NotificationBanner(moduleRef.current)))
.catch(setInstanceError);
}, [moduleRef, importRef, instance]);
const items = Children.toArray(children);
const titleElement = items.find((child) =>
childIsOfComponentType(child, NotificationBannerTitle, {
className: 'nhsuk-notification-banner__title',
}),
);
const titleElementId = titleElement?.props.id || titleId || 'nhsuk-notification-banner-title';
const contentItems = items.filter((child) => child !== titleElement);
if (instanceError) {
throw instanceError;
}
return (
<div
className={classNames(
'nhsuk-notification-banner',
{ 'nhsuk-notification-banner--success': success },
className,
)}
aria-labelledby={titleElementId}
data-module="nhsuk-notification-banner"
data-disable-auto-focus={disableAutoFocus}
ref={moduleRef}
role={role || (success ? 'alert' : 'region')}
{...rest}
>
<div className="nhsuk-notification-banner__header">
{titleElement ? (
<>{titleElement}</>
) : (
<NotificationBannerTitle id={titleElementId} success={success}>
{title}
</NotificationBannerTitle>
)}
</div>
<div className="nhsuk-notification-banner__content">{contentItems}</div>
</div>
);
},
);
NotificationBannerComponent.displayName = 'NotificationBanner';
export const NotificationBanner = Object.assign(NotificationBannerComponent, {
Title: NotificationBannerTitle,
Heading: NotificationBannerHeading,
Link: NotificationBannerLink,
});