@i-dot-ai-npm/component-library-react 0.0.2 → 0.0.4

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (40) hide show
  1. package/package.json +1 -1
  2. package/src/breadcrumbs/BreadcrumbItem.tsx +8 -0
  3. package/src/button/Button.tsx +22 -3
  4. package/src/character-count/CharacterCount.tsx +5 -2
  5. package/src/checkboxes/CheckboxConditional.tsx +24 -0
  6. package/src/date-input/DateInputField.tsx +2 -2
  7. package/src/error-message/ErrorMessage.tsx +5 -4
  8. package/src/error-summary/ErrorSummaryItem.tsx +6 -3
  9. package/src/exit-this-page/ExitThisPage.tsx +40 -0
  10. package/src/feedback/Feedback.tsx +27 -0
  11. package/src/fieldset/FieldsetLegend.tsx +5 -2
  12. package/src/footer/Footer.tsx +203 -0
  13. package/src/govuk-header/GovukHeader.tsx +61 -0
  14. package/src/header/Header.tsx +4 -2
  15. package/src/index.ts +21 -0
  16. package/src/label/Label.tsx +31 -0
  17. package/src/language-navigation/LanguageNavigation.tsx +27 -0
  18. package/src/language-navigation/LanguageNavigationItem.tsx +56 -0
  19. package/src/pagination/PaginationItem.tsx +25 -12
  20. package/src/pagination/PaginationNext.tsx +31 -9
  21. package/src/pagination/PaginationPrev.tsx +30 -9
  22. package/src/panel/Panel.tsx +24 -0
  23. package/src/panel/PanelActions.tsx +17 -0
  24. package/src/panel/PanelBody.tsx +17 -0
  25. package/src/panel/PanelTitle.tsx +17 -0
  26. package/src/phase-banner/PhaseBanner.tsx +1 -1
  27. package/src/phase-banner/PhaseBannerText.tsx +17 -0
  28. package/src/radios/RadioConditional.tsx +24 -0
  29. package/src/radios/RadioLabel.tsx +17 -0
  30. package/src/service-navigation/ServiceNavigation.tsx +84 -8
  31. package/src/service-navigation/ServiceNavigationItem.tsx +28 -6
  32. package/src/summary-card/SummaryCard.tsx +17 -0
  33. package/src/summary-card/SummaryCardAction.tsx +17 -0
  34. package/src/summary-card/SummaryCardActions.tsx +28 -0
  35. package/src/summary-card/SummaryCardContent.tsx +17 -0
  36. package/src/summary-card/SummaryCardTitle.tsx +17 -0
  37. package/src/summary-card/SummaryCardTitleWrapper.tsx +17 -0
  38. package/src/table/TableHeader.tsx +3 -2
  39. package/src/tag/Tag.tsx +2 -2
  40. package/src/textarea/Textarea.tsx +3 -2
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@i-dot-ai-npm/component-library-react",
3
- "version": "0.0.2",
3
+ "version": "0.0.4",
4
4
  "description": "React components for i.AI GOV.UK (auto-generated from HTML specs).",
5
5
  "type": "module",
6
6
  "exports": {
@@ -10,6 +10,14 @@ type BreadcrumbItemProps = {
10
10
  export default function BreadcrumbItem({ href, class: className, children, ...rest }: BreadcrumbItemProps) {
11
11
  const classes = ["govuk-breadcrumbs__list-item", className ?? ""].filter(Boolean).join(" ");
12
12
 
13
+ if (href === undefined) {
14
+ return (
15
+ <li className={classes} aria-current="page" {...rest}>
16
+ {children ?? ""}
17
+ </li>
18
+ );
19
+ }
20
+
13
21
  return (
14
22
  <li className={classes} {...rest}>
15
23
  <a className="govuk-breadcrumbs__link" href={href}>
@@ -6,22 +6,41 @@ type ButtonProps = {
6
6
  warning?: boolean;
7
7
  inverse?: boolean;
8
8
  small?: boolean;
9
+ startButton?: boolean;
9
10
  href?: string;
11
+ type?: "button" | "reset" | "submit";
10
12
  class?: string;
11
13
  children?: ReactNode;
12
14
  [key: string]: unknown;
13
15
  };
14
16
 
15
- export default function Button({ secondary, tertiary, warning, inverse, small, href, class: className, children, ...rest }: ButtonProps) {
17
+ const StartIcon = () => (
18
+ <svg
19
+ className="govuk-button__start-icon"
20
+ xmlns="http://www.w3.org/2000/svg"
21
+ width="17.5"
22
+ height="19"
23
+ viewBox="0 0 33 40"
24
+ aria-hidden="true"
25
+ focusable="false"
26
+ >
27
+ <path fill="currentColor" d="M0 0h13l20 20-20 20H0l20-20z" />
28
+ </svg>
29
+ );
30
+
31
+ export default function Button({ secondary, tertiary, warning, inverse, small, startButton, href, type, class: className, children, ...rest }: ButtonProps) {
32
+ const classes = ["govuk-button", secondary ? "govuk-button--secondary" : "", warning ? "govuk-button--warning" : "", inverse ? "govuk-button--inverse" : "", tertiary ? "govuk-button--tertiary" : "", small ? "govuk-button--small" : "", startButton ? "govuk-button--start" : "", className ?? ""].filter(Boolean).join(" ");
16
33
 
17
34
  return (
18
35
  href ? (
19
- <a href={href} role="button" className={["govuk-button", secondary ? "govuk-button--secondary" : "", warning ? "govuk-button--warning" : "", inverse ? "govuk-button--inverse" : "", tertiary ? "govuk-button--tertiary" : "", small ? "govuk-button--small" : "", className ?? ""].filter(Boolean).join(" ")} {...rest}>
36
+ <a href={href} role="button" draggable="false" className={classes} data-module="govuk-button" {...rest}>
20
37
  {children ?? ""}
38
+ {startButton ? <StartIcon /> : null}
21
39
  </a>
22
40
  ) : (
23
- <button className={["govuk-button", secondary ? "govuk-button--secondary" : "", warning ? "govuk-button--warning" : "", inverse ? "govuk-button--inverse" : "", tertiary ? "govuk-button--tertiary" : "", small ? "govuk-button--small" : "", className ?? ""].filter(Boolean).join(" ")} data-module="govuk-button" {...rest}>
41
+ <button type={type ?? "submit"} className={classes} data-module="govuk-button" {...rest}>
24
42
  {children ?? ""}
43
+ {startButton ? <StartIcon /> : null}
25
44
  </button>
26
45
  )
27
46
  );
@@ -1,12 +1,15 @@
1
+ import { ReactNode } from 'react';
2
+
1
3
  type CharacterCountProps = {
2
4
  class?: string;
5
+ children?: ReactNode;
3
6
  [key: string]: unknown;
4
7
  };
5
8
 
6
- export default function CharacterCount({ class: className, ...rest }: CharacterCountProps) {
9
+ export default function CharacterCount({ class: className, children, ...rest }: CharacterCountProps) {
7
10
  const classes = ["govuk-textarea govuk-js-character-count", className ?? ""].filter(Boolean).join(" ");
8
11
 
9
12
  return (
10
- <textarea className={classes} {...rest}></textarea>
13
+ <textarea className={classes} {...rest}>{children ?? ""}</textarea>
11
14
  );
12
15
  }
@@ -0,0 +1,24 @@
1
+ import { ReactNode } from 'react';
2
+
3
+ type CheckboxConditionalProps = {
4
+ hidden?: boolean;
5
+ class?: string;
6
+ children?: ReactNode;
7
+ [key: string]: unknown;
8
+ };
9
+
10
+ export default function CheckboxConditional({ hidden = true, class: className, children, ...rest }: CheckboxConditionalProps) {
11
+ const classes = [
12
+ "govuk-checkboxes__conditional",
13
+ hidden ? "govuk-checkboxes__conditional--hidden" : "",
14
+ className ?? "",
15
+ ]
16
+ .filter(Boolean)
17
+ .join(" ");
18
+
19
+ return (
20
+ <div className={classes} {...rest}>
21
+ {children ?? ""}
22
+ </div>
23
+ );
24
+ }
@@ -4,10 +4,10 @@ type DateInputFieldProps = {
4
4
  [key: string]: unknown;
5
5
  };
6
6
 
7
- export default function DateInputField({ width = "2", class: className, ...rest }: DateInputFieldProps) {
7
+ export default function DateInputField({ width, class: className, ...rest }: DateInputFieldProps) {
8
8
  const classes = [
9
9
  "govuk-input govuk-date-input__input",
10
- ({ "2": "govuk-input--width-2", "3": "govuk-input--width-3", "4": "govuk-input--width-4" }[width] ?? ""),
10
+ ({ "2": "govuk-input--width-2", "3": "govuk-input--width-3", "4": "govuk-input--width-4" }[width ?? ""] ?? ""),
11
11
  className ?? "",
12
12
  ]
13
13
  .filter(Boolean)
@@ -1,19 +1,20 @@
1
1
  import { ReactNode } from 'react';
2
2
 
3
3
  type ErrorMessageProps = {
4
+ visuallyHiddenText?: string;
4
5
  class?: string;
5
6
  children?: ReactNode;
6
7
  [key: string]: unknown;
7
8
  };
8
9
 
9
- export default function ErrorMessage({ class: className, children, ...rest }: ErrorMessageProps) {
10
+ export default function ErrorMessage({ visuallyHiddenText = "Error", class: className, children, ...rest }: ErrorMessageProps) {
10
11
  const classes = ["govuk-error-message", className ?? ""].filter(Boolean).join(" ");
11
12
 
12
13
  return (
13
14
  <p className={classes} {...rest}>
14
- <span className="govuk-visually-hidden">
15
- Error:
16
- </span>
15
+ {visuallyHiddenText ? (
16
+ <span className="govuk-visually-hidden">{visuallyHiddenText}:</span>
17
+ ) : null}{" "}
17
18
  {children ?? ""}
18
19
  </p>
19
20
  );
@@ -1,17 +1,20 @@
1
1
  import { ReactNode } from 'react';
2
2
 
3
3
  type ErrorSummaryItemProps = {
4
+ href?: string;
4
5
  class?: string;
5
6
  children?: ReactNode;
6
7
  [key: string]: unknown;
7
8
  };
8
9
 
9
- export default function ErrorSummaryItem({ class: className, children, ...rest }: ErrorSummaryItemProps) {
10
- const classes = ["", className ?? ""].filter(Boolean).join(" ");
10
+ export default function ErrorSummaryItem({ href, class: className, children, ...rest }: ErrorSummaryItemProps) {
11
+ if (href === undefined) {
12
+ return <li>{children ?? ""}</li>;
13
+ }
11
14
 
12
15
  return (
13
16
  <li>
14
- <a className={classes} {...rest}>
17
+ <a href={href} className={className} {...rest}>
15
18
  {children ?? ""}
16
19
  </a>
17
20
  </li>
@@ -0,0 +1,40 @@
1
+ import { ReactNode } from 'react';
2
+
3
+ type ExitThisPageProps = {
4
+ redirectUrl?: string;
5
+ id?: string;
6
+ class?: string;
7
+ children?: ReactNode;
8
+ [key: string]: unknown;
9
+ };
10
+
11
+ export default function ExitThisPage({
12
+ redirectUrl = 'https://www.bbc.co.uk/weather',
13
+ id,
14
+ class: className,
15
+ children,
16
+ ...rest
17
+ }: ExitThisPageProps) {
18
+ const classes = ['govuk-exit-this-page', className ?? ''].filter(Boolean).join(' ');
19
+
20
+ return (
21
+ <div id={id} className={classes} data-module="govuk-exit-this-page" {...rest}>
22
+ <a
23
+ href={redirectUrl}
24
+ role="button"
25
+ draggable="false"
26
+ className="govuk-button govuk-button--warning govuk-exit-this-page__button govuk-js-exit-this-page-button"
27
+ data-module="govuk-button"
28
+ rel="nofollow noreferrer"
29
+ >
30
+ {children ? (
31
+ children
32
+ ) : (
33
+ <>
34
+ <span className="govuk-visually-hidden">Emergency</span> Exit this page
35
+ </>
36
+ )}
37
+ </a>
38
+ </div>
39
+ );
40
+ }
@@ -0,0 +1,27 @@
1
+ import { ReactNode } from 'react';
2
+
3
+ type FeedbackProps = {
4
+ title?: string;
5
+ class?: string;
6
+ children?: ReactNode;
7
+ [key: string]: unknown;
8
+ };
9
+
10
+ export default function Feedback({ title, class: className, children, ...rest }: FeedbackProps) {
11
+ const classes = ["govuk-feedback govuk-width-container", className ?? ""]
12
+ .filter(Boolean)
13
+ .join(" ");
14
+
15
+ return (
16
+ <div className={classes} {...rest}>
17
+ <div className="govuk-grid-row">
18
+ <div className="govuk-grid-column-two-thirds">
19
+ <h2 className="govuk-feedback__title">{title}</h2>
20
+ {children != null && children !== "" ? (
21
+ <div className="govuk-feedback__body">{children}</div>
22
+ ) : null}
23
+ </div>
24
+ </div>
25
+ </div>
26
+ );
27
+ }
@@ -2,12 +2,13 @@ import { ReactNode } from 'react';
2
2
 
3
3
  type FieldsetLegendProps = {
4
4
  size?: "small" | "medium" | "large" | "xl";
5
+ isPageHeading?: boolean;
5
6
  class?: string;
6
7
  children?: ReactNode;
7
8
  [key: string]: unknown;
8
9
  };
9
10
 
10
- export default function FieldsetLegend({ size, class: className, children, ...rest }: FieldsetLegendProps) {
11
+ export default function FieldsetLegend({ size, isPageHeading, class: className, children, ...rest }: FieldsetLegendProps) {
11
12
  const classes = [
12
13
  "govuk-fieldset__legend",
13
14
  ({ "small": "govuk-fieldset__legend--s", "medium": "govuk-fieldset__legend--m", "large": "govuk-fieldset__legend--l", "xl": "govuk-fieldset__legend--xl" }[size] ?? ""),
@@ -18,7 +19,9 @@ export default function FieldsetLegend({ size, class: className, children, ...re
18
19
 
19
20
  return (
20
21
  <legend className={classes} {...rest}>
21
- {children ?? ""}
22
+ {isPageHeading
23
+ ? <h1 className="govuk-fieldset__heading">{children ?? ""}</h1>
24
+ : children ?? ""}
22
25
  </legend>
23
26
  );
24
27
  }
@@ -0,0 +1,203 @@
1
+ import { ReactNode } from 'react';
2
+
3
+ function FooterCrown() {
4
+ return (
5
+ <svg
6
+ focusable="false"
7
+ role="presentation"
8
+ xmlns="http://www.w3.org/2000/svg"
9
+ viewBox="0 0 64 60"
10
+ height="30"
11
+ width="32"
12
+ fill="currentcolor"
13
+ className="govuk-footer__crown"
14
+ >
15
+ <g>
16
+ <circle cx="20" cy="17.6" r="3.7" />
17
+ <circle cx="10.2" cy="23.5" r="3.7" />
18
+ <circle cx="3.7" cy="33.2" r="3.7" />
19
+ <circle cx="31.7" cy="30.6" r="3.7" />
20
+ <circle cx="43.3" cy="17.6" r="3.7" />
21
+ <circle cx="53.2" cy="23.5" r="3.7" />
22
+ <circle cx="59.7" cy="33.2" r="3.7" />
23
+ <circle cx="31.7" cy="30.6" r="3.7" />
24
+ <path d="M33.1,9.8c.2-.1.3-.3.5-.5l4.6,2.4v-6.8l-4.6,1.5c-.1-.2-.3-.3-.5-.5l1.9-5.9h-6.7l1.9,5.9c-.2.1-.3.3-.5.5l-4.6-1.5v6.8l4.6-2.4c.1.2.3.3.5.5l-2.6,8c-.9,2.8,1.2,5.7,4.1,5.7h0c3,0,5.1-2.9,4.1-5.7l-2.6-8ZM37,37.9s-3.4,3.8-4.1,6.1c2.2,0,4.2-.5,6.4-2.8l-.7,8.5c-2-2.8-4.4-4.1-5.7-3.8.1,3.1.5,6.7,5.8,7.2,3.7.3,6.7-1.5,7-3.8.4-2.6-2-4.3-3.7-1.6-1.4-4.5,2.4-6.1,4.9-3.2-1.9-4.5-1.8-7.7,2.4-10.9,3,4,2.6,7.3-1.2,11.1,2.4-1.3,6.2,0,4,4.6-1.2-2.8-3.7-2.2-4.2.2-.3,1.7.7,3.7,3,4.2,1.9.3,4.7-.9,7-5.9-1.3,0-2.4.7-3.9,1.7l2.4-8c.6,2.3,1.4,3.7,2.2,4.5.6-1.6.5-2.8,0-5.3l5,1.8c-2.6,3.6-5.2,8.7-7.3,17.5-7.4-1.1-15.7-1.7-24.5-1.7h0c-8.8,0-17.1.6-24.5,1.7-2.1-8.9-4.7-13.9-7.3-17.5l5-1.8c-.5,2.5-.6,3.7,0,5.3.8-.8,1.6-2.3,2.2-4.5l2.4,8c-1.5-1-2.6-1.7-3.9-1.7,2.3,5,5.2,6.2,7,5.9,2.3-.4,3.3-2.4,3-4.2-.5-2.4-3-3.1-4.2-.2-2.2-4.6,1.6-6,4-4.6-3.7-3.7-4.2-7.1-1.2-11.1,4.2,3.2,4.3,6.4,2.4,10.9,2.5-2.8,6.3-1.3,4.9,3.2-1.8-2.7-4.1-1-3.7,1.6.3,2.3,3.3,4.1,7,3.8,5.4-.5,5.7-4.2,5.8-7.2-1.3-.2-3.7,1-5.7,3.8l-.7-8.5c2.2,2.3,4.2,2.7,6.4,2.8-.7-2.3-4.1-6.1-4.1-6.1h10.6,0Z" />
25
+ </g>
26
+ </svg>
27
+ );
28
+ }
29
+
30
+ function FooterLicenceLogo() {
31
+ return (
32
+ <svg
33
+ aria-hidden="true"
34
+ focusable="false"
35
+ className="govuk-footer__licence-logo"
36
+ xmlns="http://www.w3.org/2000/svg"
37
+ viewBox="0 0 483.2 195.7"
38
+ height="17"
39
+ width="41"
40
+ >
41
+ <path
42
+ fill="currentColor"
43
+ d="M421.5 142.8V.1l-50.7 32.3v161.1h112.4v-50.7zm-122.3-9.6A47.12 47.12 0 0 1 221 97.8c0-26 21.1-47.1 47.1-47.1 16.7 0 31.4 8.7 39.7 21.8l42.7-27.2A97.63 97.63 0 0 0 268.1 0c-36.5 0-68.3 20.1-85.1 49.7A98 98 0 0 0 97.8 0C43.9 0 0 43.9 0 97.8s43.9 97.8 97.8 97.8c36.5 0 68.3-20.1 85.1-49.7a97.76 97.76 0 0 0 149.6 25.4l19.4 22.2h3v-87.8h-80l24.3 27.5zM97.8 145c-26 0-47.1-21.1-47.1-47.1s21.1-47.1 47.1-47.1 47.2 21 47.2 47S123.8 145 97.8 145"
44
+ />
45
+ </svg>
46
+ );
47
+ }
48
+
49
+ type FooterNavItem = { href?: string; text?: string; attributes?: Record<string, string> };
50
+ type FooterNav = { title?: string; columns?: number; width?: string; items?: FooterNavItem[] };
51
+ type FooterMetaItem = { href?: string; text?: string; attributes?: Record<string, string> };
52
+ type FooterMeta = {
53
+ visuallyHiddenTitle?: string;
54
+ items?: FooterMetaItem[];
55
+ text?: string;
56
+ /** Re-authored meta content (raw govuk `meta.html`). */
57
+ content?: ReactNode;
58
+ };
59
+ type FooterLicence = {
60
+ text?: string;
61
+ /** Re-authored licence content (raw govuk `contentLicence.html`). */
62
+ content?: ReactNode;
63
+ } | null;
64
+ type FooterCopyright = {
65
+ text?: string;
66
+ /** Re-authored copyright content (raw govuk `copyright.html`). */
67
+ content?: ReactNode;
68
+ };
69
+
70
+ type FooterProps = {
71
+ navigation?: FooterNav[];
72
+ meta?: FooterMeta;
73
+ contentLicence?: FooterLicence;
74
+ copyright?: FooterCopyright;
75
+ containerClasses?: string;
76
+ class?: string;
77
+ [key: string]: unknown;
78
+ };
79
+
80
+ export default function Footer({
81
+ navigation,
82
+ meta,
83
+ contentLicence,
84
+ copyright,
85
+ containerClasses,
86
+ class: className,
87
+ ...rest
88
+ }: FooterProps) {
89
+ const classes = ['govuk-footer', className ?? ''].filter(Boolean).join(' ');
90
+ const containerClass = ['govuk-width-container', containerClasses ?? '']
91
+ .filter(Boolean)
92
+ .join(' ');
93
+
94
+ return (
95
+ <div className={classes} {...rest}>
96
+ <div className={containerClass}>
97
+ <FooterCrown />
98
+ {navigation && navigation.length > 0 && (
99
+ <>
100
+ <div className="govuk-footer__navigation">
101
+ {navigation.map((nav, i) => (
102
+ <div
103
+ key={i}
104
+ className={`govuk-footer__section govuk-grid-column-${nav.width ?? 'full'}`}
105
+ >
106
+ <h2 className="govuk-footer__heading govuk-heading-m">{nav.title}</h2>
107
+ {nav.items && nav.items.length > 0 && (
108
+ <ul
109
+ className={[
110
+ 'govuk-footer__list',
111
+ nav.columns ? `govuk-footer__list--columns-${nav.columns}` : '',
112
+ ]
113
+ .filter(Boolean)
114
+ .join(' ')}
115
+ >
116
+ {nav.items
117
+ .filter((item) => item.href && item.text)
118
+ .map((item, j) => (
119
+ <li key={j} className="govuk-footer__list-item">
120
+ <a
121
+ className="govuk-footer__link"
122
+ href={item.href}
123
+ {...(item.attributes ?? {})}
124
+ >
125
+ {item.text}
126
+ </a>
127
+ </li>
128
+ ))}
129
+ </ul>
130
+ )}
131
+ </div>
132
+ ))}
133
+ </div>
134
+ <hr className="govuk-footer__section-break" />
135
+ </>
136
+ )}
137
+ <div className="govuk-footer__meta">
138
+ <div className="govuk-footer__meta-item govuk-footer__meta-item--grow">
139
+ {meta && (
140
+ <>
141
+ <h2 className="govuk-visually-hidden">
142
+ {meta.visuallyHiddenTitle ?? 'Support links'}
143
+ </h2>
144
+ {meta.items && meta.items.length > 0 && (
145
+ <ul className="govuk-footer__inline-list">
146
+ {meta.items.map((item, i) => (
147
+ <li key={i} className="govuk-footer__inline-list-item">
148
+ <a
149
+ className="govuk-footer__link"
150
+ href={item.href}
151
+ {...(item.attributes ?? {})}
152
+ >
153
+ {item.text}
154
+ </a>
155
+ </li>
156
+ ))}
157
+ </ul>
158
+ )}
159
+ {(meta.content || meta.text) && (
160
+ <div className="govuk-footer__meta-custom">
161
+ {meta.content ?? meta.text}
162
+ </div>
163
+ )}
164
+ </>
165
+ )}
166
+ {contentLicence !== null && (
167
+ <>
168
+ <FooterLicenceLogo />
169
+ <span className="govuk-footer__licence-description">
170
+ {contentLicence && (contentLicence.content || contentLicence.text) ? (
171
+ contentLicence.content ?? contentLicence.text
172
+ ) : (
173
+ <>
174
+ All content is available under the{' '}
175
+ <a
176
+ className="govuk-footer__link"
177
+ href="https://www.nationalarchives.gov.uk/doc/open-government-licence/version/3/"
178
+ rel="license"
179
+ >
180
+ Open Government Licence v3.0
181
+ </a>
182
+ , except where otherwise stated
183
+ </>
184
+ )}
185
+ </span>
186
+ </>
187
+ )}
188
+ </div>
189
+ <div className="govuk-footer__meta-item">
190
+ <a
191
+ className="govuk-footer__link govuk-footer__copyright-logo"
192
+ href="https://www.nationalarchives.gov.uk/information-management/re-using-public-sector-information/uk-government-licensing-framework/crown-copyright/"
193
+ >
194
+ {copyright && (copyright.content || copyright.text)
195
+ ? (copyright.content ?? copyright.text)
196
+ : '© Crown copyright'}
197
+ </a>
198
+ </div>
199
+ </div>
200
+ </div>
201
+ </div>
202
+ );
203
+ }
@@ -0,0 +1,61 @@
1
+ const CROWN_LOGO = `<svg
2
+ focusable="false"
3
+ role="img"
4
+ xmlns="http://www.w3.org/2000/svg"
5
+ viewBox="0 0 324 60"
6
+ height="30"
7
+ width="162"
8
+ fill="currentcolor" class="govuk-header__logotype" aria-label="GOV.UK"
9
+ ><title>GOV.UK</title> <g>
10
+ <circle cx="20" cy="17.6" r="3.7"/>
11
+ <circle cx="10.2" cy="23.5" r="3.7"/>
12
+ <circle cx="3.7" cy="33.2" r="3.7"/>
13
+ <circle cx="31.7" cy="30.6" r="3.7"/>
14
+ <circle cx="43.3" cy="17.6" r="3.7"/>
15
+ <circle cx="53.2" cy="23.5" r="3.7"/>
16
+ <circle cx="59.7" cy="33.2" r="3.7"/>
17
+ <circle cx="31.7" cy="30.6" r="3.7"/>
18
+ <path d="M33.1,9.8c.2-.1.3-.3.5-.5l4.6,2.4v-6.8l-4.6,1.5c-.1-.2-.3-.3-.5-.5l1.9-5.9h-6.7l1.9,5.9c-.2.1-.3.3-.5.5l-4.6-1.5v6.8l4.6-2.4c.1.2.3.3.5.5l-2.6,8c-.9,2.8,1.2,5.7,4.1,5.7h0c3,0,5.1-2.9,4.1-5.7l-2.6-8ZM37,37.9s-3.4,3.8-4.1,6.1c2.2,0,4.2-.5,6.4-2.8l-.7,8.5c-2-2.8-4.4-4.1-5.7-3.8.1,3.1.5,6.7,5.8,7.2,3.7.3,6.7-1.5,7-3.8.4-2.6-2-4.3-3.7-1.6-1.4-4.5,2.4-6.1,4.9-3.2-1.9-4.5-1.8-7.7,2.4-10.9,3,4,2.6,7.3-1.2,11.1,2.4-1.3,6.2,0,4,4.6-1.2-2.8-3.7-2.2-4.2.2-.3,1.7.7,3.7,3,4.2,1.9.3,4.7-.9,7-5.9-1.3,0-2.4.7-3.9,1.7l2.4-8c.6,2.3,1.4,3.7,2.2,4.5.6-1.6.5-2.8,0-5.3l5,1.8c-2.6,3.6-5.2,8.7-7.3,17.5-7.4-1.1-15.7-1.7-24.5-1.7h0c-8.8,0-17.1.6-24.5,1.7-2.1-8.9-4.7-13.9-7.3-17.5l5-1.8c-.5,2.5-.6,3.7,0,5.3.8-.8,1.6-2.3,2.2-4.5l2.4,8c-1.5-1-2.6-1.7-3.9-1.7,2.3,5,5.2,6.2,7,5.9,2.3-.4,3.3-2.4,3-4.2-.5-2.4-3-3.1-4.2-.2-2.2-4.6,1.6-6,4-4.6-3.7-3.7-4.2-7.1-1.2-11.1,4.2,3.2,4.3,6.4,2.4,10.9,2.5-2.8,6.3-1.3,4.9,3.2-1.8-2.7-4.1-1-3.7,1.6.3,2.3,3.3,4.1,7,3.8,5.4-.5,5.7-4.2,5.8-7.2-1.3-.2-3.7,1-5.7,3.8l-.7-8.5c2.2,2.3,4.2,2.7,6.4,2.8-.7-2.3-4.1-6.1-4.1-6.1h10.6,0Z"/>
19
+ </g>
20
+ <circle class="govuk-logo-dot" cx="226" cy="36" r="7.3"/>
21
+ <path d="M93.94 41.25c.4 1.81 1.2 3.21 2.21 4.62 1 1.4 2.21 2.41 3.61 3.21s3.21 1.2 5.22 1.2 3.61-.4 4.82-1c1.4-.6 2.41-1.4 3.21-2.41.8-1 1.4-2.01 1.61-3.01s.4-2.01.4-3.01v.14h-10.86v-7.02h20.07v24.08h-8.03v-5.56c-.6.8-1.38 1.61-2.19 2.41-.8.8-1.81 1.2-2.81 1.81-1 .4-2.21.8-3.41 1.2s-2.41.4-3.81.4a18.56 18.56 0 0 1-14.65-6.63c-1.6-2.01-3.01-4.41-3.81-7.02s-1.4-5.62-1.4-8.83.4-6.02 1.4-8.83a20.45 20.45 0 0 1 19.46-13.65c3.21 0 4.01.2 5.82.8 1.81.4 3.61 1.2 5.02 2.01 1.61.8 2.81 2.01 4.01 3.21s2.21 2.61 2.81 4.21l-7.63 4.41c-.4-1-1-1.81-1.61-2.61-.6-.8-1.4-1.4-2.21-2.01-.8-.6-1.81-1-2.81-1.4-1-.4-2.21-.4-3.61-.4-2.01 0-3.81.4-5.22 1.2-1.4.8-2.61 1.81-3.61 3.21s-1.61 2.81-2.21 4.62c-.4 1.81-.6 3.71-.6 5.42s.8 5.22.8 5.22Zm57.8-27.9c3.21 0 6.22.6 8.63 1.81 2.41 1.2 4.82 2.81 6.62 4.82S170.2 24.39 171 27s1.4 5.62 1.4 8.83-.4 6.02-1.4 8.83-2.41 5.02-4.01 7.02-4.01 3.61-6.62 4.82-5.42 1.81-8.63 1.81-6.22-.6-8.63-1.81-4.82-2.81-6.42-4.82-3.21-4.41-4.01-7.02-1.4-5.62-1.4-8.83.4-6.02 1.4-8.83 2.41-5.02 4.01-7.02 4.01-3.61 6.42-4.82 5.42-1.81 8.63-1.81Zm0 36.73c1.81 0 3.61-.4 5.02-1s2.61-1.81 3.61-3.01 1.81-2.81 2.21-4.41c.4-1.81.8-3.61.8-5.62 0-2.21-.2-4.21-.8-6.02s-1.2-3.21-2.21-4.62c-1-1.2-2.21-2.21-3.61-3.01s-3.21-1-5.02-1-3.61.4-5.02 1c-1.4.8-2.61 1.81-3.61 3.01s-1.81 2.81-2.21 4.62c-.4 1.81-.8 3.61-.8 5.62 0 2.41.2 4.21.8 6.02.4 1.81 1.2 3.21 2.21 4.41s2.21 2.21 3.61 3.01c1.4.8 3.21 1 5.02 1Zm36.32 7.96-12.24-44.15h9.83l8.43 32.77h.4l8.23-32.77h9.83L200.3 58.04h-12.24Zm74.14-7.96c2.18 0 3.51-.6 3.51-.6 1.2-.6 2.01-1 2.81-1.81s1.4-1.81 1.81-2.81a13 13 0 0 0 .8-4.01V13.9h8.63v28.15c0 2.41-.4 4.62-1.4 6.62-.8 2.01-2.21 3.61-3.61 5.02s-3.41 2.41-5.62 3.21-4.62 1.2-7.02 1.2-5.02-.4-7.02-1.2c-2.21-.8-4.01-1.81-5.62-3.21s-2.81-3.01-3.61-5.02-1.4-4.21-1.4-6.62V13.9h8.63v26.95c0 1.61.2 3.01.8 4.01.4 1.2 1.2 2.21 2.01 2.81.8.8 1.81 1.4 2.81 1.81 0 0 1.34.6 3.51.6Zm34.22-36.18v18.92l15.65-18.92h10.82l-15.03 17.32 16.03 26.83h-10.21l-11.44-20.21-5.62 6.22v13.99h-8.83V13.9"/>
22
+ </svg>`;
23
+
24
+ type GovukHeaderProps = {
25
+ homepageUrl?: string;
26
+ productName?: string;
27
+ containerClasses?: string;
28
+ class?: string;
29
+ [key: string]: unknown;
30
+ };
31
+
32
+ export default function GovukHeader({
33
+ homepageUrl = '//gov.uk',
34
+ productName,
35
+ containerClasses = 'govuk-width-container',
36
+ class: className,
37
+ ...rest
38
+ }: GovukHeaderProps) {
39
+ const classes = ['govuk-header', className ?? ''].filter(Boolean).join(' ');
40
+ const containerClass = ['govuk-header__container', containerClasses]
41
+ .filter(Boolean)
42
+ .join(' ');
43
+
44
+ const linkHtml = productName
45
+ ? `${CROWN_LOGO}<span class="govuk-header__product-name">${productName}</span>`
46
+ : CROWN_LOGO;
47
+
48
+ return (
49
+ <div className={classes} {...rest}>
50
+ <div className={containerClass}>
51
+ <div className="govuk-header__logo">
52
+ <a
53
+ href={homepageUrl}
54
+ className="govuk-header__homepage-link"
55
+ dangerouslySetInnerHTML={{ __html: linkHtml }}
56
+ />
57
+ </div>
58
+ </div>
59
+ </div>
60
+ );
61
+ }
@@ -3,16 +3,18 @@ import { ReactNode } from 'react';
3
3
  type HeaderProps = {
4
4
  href?: string;
5
5
  class?: string;
6
+ containerClasses?: string;
6
7
  children?: ReactNode;
7
8
  [key: string]: unknown;
8
9
  };
9
10
 
10
- export default function Header({ href, class: className, children, ...rest }: HeaderProps) {
11
+ export default function Header({ href, class: className, containerClasses, children, ...rest }: HeaderProps) {
11
12
  const classes = ["govuk-generic-header", className ?? ""].filter(Boolean).join(" ");
13
+ const container = ["govuk-generic-header__container", containerClasses || "govuk-width-container"].join(" ");
12
14
 
13
15
  return (
14
16
  <div className={classes} {...rest}>
15
- <div className="govuk-generic-header__container govuk-width-container">
17
+ <div className={container}>
16
18
  <div className="govuk-generic-header__logo">
17
19
  <a className="govuk-generic-header__homepage-link" href={href}>
18
20
  {children ?? ""}
package/src/index.ts CHANGED
@@ -17,6 +17,7 @@ export { default as CardLink } from "./card/CardLink";
17
17
  export { default as Card } from "./card/Card";
18
18
  export { default as CharacterCountMessage } from "./character-count/CharacterCountMessage";
19
19
  export { default as CharacterCount } from "./character-count/CharacterCount";
20
+ export { default as CheckboxConditional } from "./checkboxes/CheckboxConditional";
20
21
  export { default as CheckboxDivider } from "./checkboxes/CheckboxDivider";
21
22
  export { default as CheckboxInput } from "./checkboxes/CheckboxInput";
22
23
  export { default as CheckboxItem } from "./checkboxes/CheckboxItem";
@@ -39,15 +40,22 @@ export { default as ErrorSummaryItem } from "./error-summary/ErrorSummaryItem";
39
40
  export { default as ErrorSummaryList } from "./error-summary/ErrorSummaryList";
40
41
  export { default as ErrorSummaryTitle } from "./error-summary/ErrorSummaryTitle";
41
42
  export { default as ErrorSummary } from "./error-summary/ErrorSummary";
43
+ export { default as ExitThisPage } from "./exit-this-page/ExitThisPage";
42
44
  export { default as FieldsetLegend } from "./fieldset/FieldsetLegend";
43
45
  export { default as Fieldset } from "./fieldset/Fieldset";
46
+ export { default as Feedback } from "./feedback/Feedback";
44
47
  export { default as FileUpload } from "./file-upload/FileUpload";
48
+ export { default as Footer } from "./footer/Footer";
45
49
  export { default as FormGroup } from "./form-group/FormGroup";
50
+ export { default as GovukHeader } from "./govuk-header/GovukHeader";
46
51
  export { default as Header } from "./header/Header";
47
52
  export { default as Hint } from "./hint/Hint";
48
53
  export { default as Input } from "./input/Input";
49
54
  export { default as InputLabel } from "./input-label/InputLabel";
50
55
  export { default as InsetText } from "./inset-text/InsetText";
56
+ export { default as Label } from "./label/Label";
57
+ export { default as LanguageNavigationItem } from "./language-navigation/LanguageNavigationItem";
58
+ export { default as LanguageNavigation } from "./language-navigation/LanguageNavigation";
51
59
  export { default as Link } from "./link/Link";
52
60
  export { default as ListItem } from "./list/ListItem";
53
61
  export { default as List } from "./list/List";
@@ -61,11 +69,18 @@ export { default as PaginationList } from "./pagination/PaginationList";
61
69
  export { default as PaginationNext } from "./pagination/PaginationNext";
62
70
  export { default as PaginationPrev } from "./pagination/PaginationPrev";
63
71
  export { default as Pagination } from "./pagination/Pagination";
72
+ export { default as PanelTitle } from "./panel/PanelTitle";
73
+ export { default as PanelBody } from "./panel/PanelBody";
74
+ export { default as PanelActions } from "./panel/PanelActions";
75
+ export { default as Panel } from "./panel/Panel";
64
76
  export { default as PasswordInput } from "./password-input/PasswordInput";
65
77
  export { default as PhaseBanner } from "./phase-banner/PhaseBanner";
78
+ export { default as PhaseBannerText } from "./phase-banner/PhaseBannerText";
79
+ export { default as RadioConditional } from "./radios/RadioConditional";
66
80
  export { default as RadioDivider } from "./radios/RadioDivider";
67
81
  export { default as RadioInput } from "./radios/RadioInput";
68
82
  export { default as RadioItem } from "./radios/RadioItem";
83
+ export { default as RadioLabel } from "./radios/RadioLabel";
69
84
  export { default as Radios } from "./radios/Radios";
70
85
  export { default as SelectOption } from "./select/SelectOption";
71
86
  export { default as Select } from "./select/Select";
@@ -83,6 +98,12 @@ export { default as SummaryListKey } from "./summary-list/SummaryListKey";
83
98
  export { default as SummaryListRow } from "./summary-list/SummaryListRow";
84
99
  export { default as SummaryListValue } from "./summary-list/SummaryListValue";
85
100
  export { default as SummaryList } from "./summary-list/SummaryList";
101
+ export { default as SummaryCard } from "./summary-card/SummaryCard";
102
+ export { default as SummaryCardTitleWrapper } from "./summary-card/SummaryCardTitleWrapper";
103
+ export { default as SummaryCardTitle } from "./summary-card/SummaryCardTitle";
104
+ export { default as SummaryCardActions } from "./summary-card/SummaryCardActions";
105
+ export { default as SummaryCardAction } from "./summary-card/SummaryCardAction";
106
+ export { default as SummaryCardContent } from "./summary-card/SummaryCardContent";
86
107
  export { default as TableBody } from "./table/TableBody";
87
108
  export { default as TableCaption } from "./table/TableCaption";
88
109
  export { default as TableCell } from "./table/TableCell";