@uktrade/react-component-library 0.10.1

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 (90) hide show
  1. package/LICENSE +21 -0
  2. package/Readme.md +64 -0
  3. package/dist/components/ApiBoundary/ApiBoundary.d.ts +10 -0
  4. package/dist/components/ApiBoundary/ApiBoundary.d.ts.map +1 -0
  5. package/dist/components/ApiBoundary/ApiBoundary.js +7 -0
  6. package/dist/components/ApiBoundary/ApiBoundary.module.css +30 -0
  7. package/dist/components/ApiQuery/ApiCreateClient.d.ts +3 -0
  8. package/dist/components/ApiQuery/ApiCreateClient.d.ts.map +1 -0
  9. package/dist/components/ApiQuery/ApiCreateClient.js +11 -0
  10. package/dist/components/ApiQuery/ApiCreateHooks.d.ts +25 -0
  11. package/dist/components/ApiQuery/ApiCreateHooks.d.ts.map +1 -0
  12. package/dist/components/ApiQuery/ApiCreateHooks.js +55 -0
  13. package/dist/components/ApiQuery/ApiProvider.d.ts +30 -0
  14. package/dist/components/ApiQuery/ApiProvider.d.ts.map +1 -0
  15. package/dist/components/ApiQuery/ApiProvider.js +59 -0
  16. package/dist/components/ApiQuery/index.d.ts +4 -0
  17. package/dist/components/ApiQuery/index.d.ts.map +1 -0
  18. package/dist/components/ApiQuery/index.js +3 -0
  19. package/dist/components/Arrow/Arrow.d.ts +8 -0
  20. package/dist/components/Arrow/Arrow.d.ts.map +1 -0
  21. package/dist/components/Arrow/Arrow.js +12 -0
  22. package/dist/components/Arrow/Arrow.module.css +21 -0
  23. package/dist/components/Arrows/Arrows.d.ts +7 -0
  24. package/dist/components/Arrows/Arrows.d.ts.map +1 -0
  25. package/dist/components/Arrows/Arrows.js +6 -0
  26. package/dist/components/Arrows/Arrows.module.css +25 -0
  27. package/dist/components/BackLink.d.ts +9 -0
  28. package/dist/components/BackLink.d.ts.map +1 -0
  29. package/dist/components/BackLink.js +6 -0
  30. package/dist/components/Button.d.ts +8 -0
  31. package/dist/components/Button.d.ts.map +1 -0
  32. package/dist/components/Button.js +4 -0
  33. package/dist/components/ButtonGroup.d.ts +6 -0
  34. package/dist/components/ButtonGroup.d.ts.map +1 -0
  35. package/dist/components/ButtonGroup.js +6 -0
  36. package/dist/components/Colours.d.ts +20 -0
  37. package/dist/components/Colours.d.ts.map +1 -0
  38. package/dist/components/Colours.js +20 -0
  39. package/dist/components/LoadingSpinner/LoadingSpinner.d.ts +7 -0
  40. package/dist/components/LoadingSpinner/LoadingSpinner.d.ts.map +1 -0
  41. package/dist/components/LoadingSpinner/LoadingSpinner.js +6 -0
  42. package/dist/components/LoadingSpinner/LoadingSpinner.module.css +33 -0
  43. package/dist/components/SummaryItem/SummaryItem.d.ts +39 -0
  44. package/dist/components/SummaryItem/SummaryItem.d.ts.map +1 -0
  45. package/dist/components/SummaryItem/SummaryItem.js +25 -0
  46. package/dist/components/SummaryList/SummaryList.d.ts +17 -0
  47. package/dist/components/SummaryList/SummaryList.d.ts.map +1 -0
  48. package/dist/components/SummaryList/SummaryList.js +7 -0
  49. package/dist/components/SummaryList/SummaryList.module.css +14 -0
  50. package/dist/components/Tags/Tags.d.ts +16 -0
  51. package/dist/components/Tags/Tags.d.ts.map +1 -0
  52. package/dist/components/Tags/Tags.js +16 -0
  53. package/dist/components/Tags/Tags.module.css +17 -0
  54. package/dist/components/ViewFormItem/ViewFormItem.d.ts +11 -0
  55. package/dist/components/ViewFormItem/ViewFormItem.d.ts.map +1 -0
  56. package/dist/components/ViewFormItem/ViewFormItem.js +13 -0
  57. package/dist/components/ViewFormItem/ViewFormItem.module.css +11 -0
  58. package/dist/index.d.ts +14 -0
  59. package/dist/index.d.ts.map +1 -0
  60. package/dist/index.js +13 -0
  61. package/dist/utils/cn.d.ts +2 -0
  62. package/dist/utils/cn.d.ts.map +1 -0
  63. package/dist/utils/cn.js +3 -0
  64. package/package.json +78 -0
  65. package/src/components/ApiBoundary/ApiBoundary.module.css +30 -0
  66. package/src/components/ApiBoundary/ApiBoundary.tsx +44 -0
  67. package/src/components/Arrow/Arrow.module.css +21 -0
  68. package/src/components/Arrow/Arrow.tsx +41 -0
  69. package/src/components/Arrows/Arrows.module.css +25 -0
  70. package/src/components/Arrows/Arrows.tsx +26 -0
  71. package/src/components/BackLink.tsx +28 -0
  72. package/src/components/Button.tsx +18 -0
  73. package/src/components/ButtonGroup.tsx +16 -0
  74. package/src/components/Colours.tsx +20 -0
  75. package/src/components/Footer/.gitkeep +0 -0
  76. package/src/components/Header/.gitkeep +0 -0
  77. package/src/components/Hero/.gitkeep +0 -0
  78. package/src/components/LoadingSpinner/LoadingSpinner.module.css +33 -0
  79. package/src/components/LoadingSpinner/LoadingSpinner.tsx +19 -0
  80. package/src/components/NavBar/.gitkeep +0 -0
  81. package/src/components/SummaryItem/SummaryItem.tsx +96 -0
  82. package/src/components/SummaryList/SummaryList.module.css +14 -0
  83. package/src/components/SummaryList/SummaryList.tsx +64 -0
  84. package/src/components/Tags/Tags.module.css +17 -0
  85. package/src/components/Tags/Tags.tsx +39 -0
  86. package/src/components/ViewFormItem/ViewFormItem.module.css +11 -0
  87. package/src/components/ViewFormItem/ViewFormItem.tsx +41 -0
  88. package/src/index.ts +12 -0
  89. package/src/types/custom.d.ts +4 -0
  90. package/src/utils/cn.ts +3 -0
@@ -0,0 +1,33 @@
1
+ .hods-loading-spinner {
2
+ position: relative;
3
+ display: flex;
4
+ flex-direction: column;
5
+ align-items: center;
6
+ justify-content: center;
7
+ min-height: 100px;
8
+ }
9
+
10
+ .hods-loading-spinner__spinner {
11
+ border: 8px solid #dee0e2;
12
+ border-top-color: #005ea5; /* govuk blue */
13
+ border-radius: 50%;
14
+ width: 60px;
15
+ height: 60px;
16
+ animation: hods-spin 1s linear infinite;
17
+ }
18
+
19
+ .hods-loading-spinner__text {
20
+ margin-top: 0.75rem;
21
+ font-size: 1rem;
22
+ color: #0b0c0c; /* govuk body text */
23
+ text-align: center;
24
+ }
25
+
26
+ @keyframes hods-spin {
27
+ 0% {
28
+ transform: rotate(0deg);
29
+ }
30
+ 100% {
31
+ transform: rotate(360deg);
32
+ }
33
+ }
@@ -0,0 +1,19 @@
1
+ "use client"
2
+
3
+ import type { FC, ReactNode } from "react";
4
+
5
+ import styles from "./LoadingSpinner.module.css";
6
+
7
+ interface LoadingSpinnerProps {
8
+ children?: ReactNode;
9
+ }
10
+
11
+ // https://design.homeoffice.gov.uk/design-system/components?name=Loading%20spinner
12
+ export const LoadingSpinner: FC<LoadingSpinnerProps> = ({ children }) => (
13
+ <div className={styles["hods-loading-spinner"]} role="status" aria-live="polite" aria-busy="true">
14
+ <div className={styles["hods-loading-spinner__spinner"]} aria-hidden="true" />
15
+ {children && <div className={styles["hods-loading-spinner__text"]}>{children}</div>}
16
+ </div>
17
+ );
18
+
19
+ export default LoadingSpinner;
File without changes
@@ -0,0 +1,96 @@
1
+ "use client"
2
+
3
+ import type React from "react";
4
+
5
+ export interface SummaryItemConfig {
6
+ name: string;
7
+ value: React.ReactNode;
8
+ actions?: SummaryListAction[];
9
+ }
10
+
11
+ export type SummaryListAction = {
12
+ text: string;
13
+ href: string;
14
+ visuallyHidden?: string;
15
+ };
16
+
17
+ export interface SummaryListActionProps {
18
+ action: SummaryListAction;
19
+ }
20
+
21
+ export interface SummaryListActionsListProps {
22
+ actions?: SummaryListAction[];
23
+ }
24
+
25
+ interface SummaryItemProps {
26
+ name: string;
27
+ children: React.ReactNode;
28
+ actions?: SummaryListAction[];
29
+ }
30
+
31
+ /**
32
+ * Single action link
33
+ */
34
+ export const SummaryListAction = ({
35
+ action,
36
+ }: SummaryListActionProps): React.JSX.Element => {
37
+ return (
38
+ <a className="govuk-link" href={action.href}>
39
+ {action.text}
40
+ {action.visuallyHidden && (
41
+ <span className="govuk-visually-hidden">
42
+ {" "}
43
+ {action.visuallyHidden}
44
+ </span>
45
+ )}
46
+ </a>
47
+ );
48
+ };
49
+
50
+ /**
51
+ * Actions container
52
+ * - Renders nothing if no actions
53
+ * - Renders a link if one action
54
+ * - Renders a list if multiple actions
55
+ */
56
+ export const SummaryListActionsList = ({
57
+ actions,
58
+ }: SummaryListActionsListProps): React.JSX.Element | null => {
59
+ if (!actions || actions.length === 0) return null;
60
+
61
+ return (
62
+ <dd className="govuk-summary-list__actions">
63
+ {actions.length === 1 ? (
64
+ <SummaryListAction action={actions[0]} />
65
+ ) : (
66
+ <ul className="govuk-summary-list__actions-list">
67
+ {actions.map((action, index) => (
68
+ <li
69
+ key={`${action.href}-${index}`}
70
+ className="govuk-summary-list__actions-list-item"
71
+ >
72
+ <SummaryListAction action={action} />
73
+ </li>
74
+ ))}
75
+ </ul>
76
+ )}
77
+ </dd>
78
+ );
79
+ };
80
+
81
+ /**
82
+ * Standard GOV.UK Summary List row
83
+ */
84
+ export const SummaryItem = ({
85
+ name,
86
+ children,
87
+ actions,
88
+ }: SummaryItemProps): React.JSX.Element => {
89
+ return (
90
+ <div className="govuk-summary-list__row">
91
+ <dt className="govuk-summary-list__key">{name}</dt>
92
+ <dd className="govuk-summary-list__value">{children}</dd>
93
+ <SummaryListActionsList actions={actions} />
94
+ </div>
95
+ );
96
+ };
@@ -0,0 +1,14 @@
1
+ .root {
2
+ .govukSummaryCardContent {
3
+ display: table;
4
+ width: calc(100% - 40px);
5
+ table-layout: fixed;
6
+ border-collapse: collapse;
7
+ margin: 20px;
8
+ margin-top: 10px;
9
+ }
10
+
11
+ .summaryCardTitleActions {
12
+ font-weight: 400;
13
+ }
14
+ }
@@ -0,0 +1,64 @@
1
+ "use client"
2
+
3
+ import type React from "react";
4
+ import clsx from "clsx";
5
+
6
+ import { SummaryListAction } from "../SummaryItem/SummaryItem";
7
+ import styles from "./SummaryList.module.css";
8
+
9
+ export interface SummaryListProps extends React.HTMLAttributes<HTMLDListElement> {
10
+ title: string;
11
+ children?: React.ReactNode;
12
+ actions?: SummaryListAction[];
13
+ className?: string;
14
+ }
15
+
16
+ export const SummaryList = ({ title, children, className, ...props }: SummaryListProps) => (
17
+ <>
18
+ {title && <h2 className="govuk-heading-l">{title}</h2>}
19
+ <dl className={clsx("govuk-summary-list", className)} {...props}>
20
+ {children}
21
+ </dl>
22
+ </>
23
+ );
24
+
25
+ export interface SummaryCardProps extends React.HTMLAttributes<HTMLDivElement> {
26
+ title: string;
27
+ children?: React.ReactNode;
28
+ actions?: SummaryListAction[];
29
+ className?: string;
30
+ }
31
+
32
+ export const SummaryCard = ({ title, children, actions, className, ...props }: SummaryCardProps) => (
33
+ <div className={clsx(styles.root, className)}>
34
+ <div className="govuk-summary-card govuk-body" {...props}>
35
+ <div className="govuk-summary-card__title-wrapper">
36
+ <h2 className="govuk-summary-card__title">{title}</h2>
37
+
38
+ {actions && (
39
+ <ul
40
+ className={clsx(
41
+ "govuk-summary-card__actions",
42
+ styles.summaryCardTitleActions
43
+ )}
44
+ >
45
+ {actions.map((action) => (
46
+ <li key={action.text} className="govuk-summary-card__action">
47
+ <SummaryListAction action={action} />
48
+ </li>
49
+ ))}
50
+ </ul>
51
+ )}
52
+ </div>
53
+
54
+ <div
55
+ className={clsx(
56
+ "govuk-summary-card__content",
57
+ styles.govukSummaryCardContent
58
+ )}
59
+ >
60
+ {children}
61
+ </div>
62
+ </div>
63
+ </div>
64
+ );
@@ -0,0 +1,17 @@
1
+ .root {
2
+ display: inline-flex;
3
+ flex-wrap: wrap;
4
+
5
+ @media (max-width: 640px) {
6
+ float: none;
7
+ clear: left;
8
+ }
9
+
10
+ @media (min-width: 640px) {
11
+ float: right;
12
+ }
13
+
14
+ .tag:not(:last-child) {
15
+ margin-right: 0.5rem;
16
+ }
17
+ }
@@ -0,0 +1,39 @@
1
+ "use client"
2
+
3
+ import clsx from "clsx";
4
+ import type React from "react";
5
+ import { TagColours } from "../Colours";
6
+ import styles from "./Tags.module.css";
7
+
8
+ export type TagProps = {
9
+ text: string;
10
+ colour: TagColours;
11
+ };
12
+
13
+ export const Tag = ({ text, colour }: TagProps): React.JSX.Element => {
14
+ return <strong className={clsx("govuk-tag", colour, styles.tag)}>{text}</strong>;
15
+ };
16
+
17
+ export type TagsProps = {
18
+ children: React.ReactNode;
19
+ };
20
+
21
+ export const Tags = ({ children }: TagsProps): React.JSX.Element => {
22
+ return <span className={clsx("govuk-tags", styles.root)}>{children}</span>;
23
+ };
24
+
25
+ export type TagsListProps = {
26
+ tags: TagProps[];
27
+ };
28
+
29
+ export const TagsList = ({ tags }: TagsListProps): React.JSX.Element => {
30
+ if (!tags || tags.length === 0) return <></>;
31
+
32
+ return (
33
+ <Tags>
34
+ {tags.map((tag) => (
35
+ <Tag key={tag.text} text={tag.text} colour={tag.colour} />
36
+ ))}
37
+ </Tags>
38
+ );
39
+ };
@@ -0,0 +1,11 @@
1
+ .root {
2
+ clear: both;
3
+
4
+ .key {
5
+ font-weight: normal;
6
+ }
7
+
8
+ & .govuk-tags {
9
+ float: none;
10
+ }
11
+ }
@@ -0,0 +1,41 @@
1
+ "use client"
2
+
3
+ import clsx from "clsx";
4
+ import type { ReactNode } from "react";
5
+ import { TagColours } from "../Colours";
6
+ import { TagsList, type TagProps } from "../Tags/Tags";
7
+ import styles from "./ViewFormItem.module.css";
8
+
9
+
10
+ interface LinkAndTagItemProps {
11
+ name: string;
12
+ href: string;
13
+ children?: ReactNode;
14
+ tags?: TagProps[];
15
+ }
16
+
17
+ export const ViewFormItem = ({
18
+ name,
19
+ href,
20
+ children,
21
+ tags = [],
22
+ }: LinkAndTagItemProps) => {
23
+ tags.push({
24
+ text: children ? "Completed" : "Not started",
25
+ colour: children ? TagColours.LightBlue : TagColours.Grey,
26
+ });
27
+
28
+ return (
29
+ <div className={clsx(styles.root, "view-form-item", "govuk-summary-list__row")}>
30
+ <dt className={clsx(styles.key, "govuk-summary-list__key")}>
31
+ <a className="govuk-link" href={href}>
32
+ {name}
33
+ </a>
34
+ </dt>
35
+ <dd className="govuk-summary-list__value">{children}</dd>
36
+ <dd className={clsx(styles.actions, "govuk-summary-list__actions")}>
37
+ <TagsList tags={tags} />
38
+ </dd>
39
+ </div>
40
+ );
41
+ };
package/src/index.ts ADDED
@@ -0,0 +1,12 @@
1
+ export * from "./components/SummaryList/SummaryList";
2
+ export * from "./components/SummaryItem/SummaryItem";
3
+ export * from "./components/ViewFormItem/ViewFormItem";
4
+ export * from "./components/Arrow/Arrow";
5
+ export * from "./components/Arrows/Arrows";
6
+ export * from "./components/Tags/Tags";
7
+ export * from "./components/Colours";
8
+ export * from "./components/Button";
9
+ export * from "./components/ButtonGroup";
10
+ export * from "./components/BackLink";
11
+ export * from "./components/LoadingSpinner/LoadingSpinner";
12
+ export * from "./components/ApiBoundary/ApiBoundary";
@@ -0,0 +1,4 @@
1
+ declare module "*.module.css" {
2
+ const classes: { [key: string]: string };
3
+ export default classes;
4
+ }
@@ -0,0 +1,3 @@
1
+ export function cn(...classes: (string | undefined | false)[]) {
2
+ return classes.filter(Boolean).join(" ");
3
+ }