@arbor-education/design-system.components 0.25.4 → 0.25.6

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 (69) hide show
  1. package/CHANGELOG.md +14 -0
  2. package/dist/components/fileUpload/FileUpload.d.ts +21 -0
  3. package/dist/components/fileUpload/FileUpload.d.ts.map +1 -0
  4. package/dist/components/fileUpload/FileUpload.js +23 -0
  5. package/dist/components/fileUpload/FileUpload.js.map +1 -0
  6. package/dist/components/fileUpload/FileUpload.stories.d.ts +71 -0
  7. package/dist/components/fileUpload/FileUpload.stories.d.ts.map +1 -0
  8. package/dist/components/fileUpload/FileUpload.stories.js +736 -0
  9. package/dist/components/fileUpload/FileUpload.stories.js.map +1 -0
  10. package/dist/components/fileUpload/FileUpload.test.d.ts +2 -0
  11. package/dist/components/fileUpload/FileUpload.test.d.ts.map +1 -0
  12. package/dist/components/fileUpload/FileUpload.test.js +99 -0
  13. package/dist/components/fileUpload/FileUpload.test.js.map +1 -0
  14. package/dist/components/formField/inputs/selectDropdown/SelectDropdown.js +1 -1
  15. package/dist/components/formField/inputs/selectDropdown/SelectDropdown.js.map +1 -1
  16. package/dist/components/formField/inputs/selectDropdown/SelectDropdown.stories.d.ts.map +1 -1
  17. package/dist/components/formField/inputs/selectDropdown/SelectDropdown.stories.js +14 -15
  18. package/dist/components/formField/inputs/selectDropdown/SelectDropdown.stories.js.map +1 -1
  19. package/dist/components/formField/inputs/selectDropdown/SelectDropdown.test.js +11 -0
  20. package/dist/components/formField/inputs/selectDropdown/SelectDropdown.test.js.map +1 -1
  21. package/dist/components/grid/Grid.d.ts +14 -0
  22. package/dist/components/grid/Grid.d.ts.map +1 -0
  23. package/dist/components/grid/Grid.js +11 -0
  24. package/dist/components/grid/Grid.js.map +1 -0
  25. package/dist/components/grid/Grid.stories.d.ts +52 -0
  26. package/dist/components/grid/Grid.stories.d.ts.map +1 -0
  27. package/dist/components/grid/Grid.stories.js +675 -0
  28. package/dist/components/grid/Grid.stories.js.map +1 -0
  29. package/dist/components/grid/Grid.test.d.ts +2 -0
  30. package/dist/components/grid/Grid.test.d.ts.map +1 -0
  31. package/dist/components/grid/Grid.test.js +59 -0
  32. package/dist/components/grid/Grid.test.js.map +1 -0
  33. package/dist/components/grid/GridColumn.d.ts +11 -0
  34. package/dist/components/grid/GridColumn.d.ts.map +1 -0
  35. package/dist/components/grid/GridColumn.js +7 -0
  36. package/dist/components/grid/GridColumn.js.map +1 -0
  37. package/dist/components/grid/GridRow.d.ts +10 -0
  38. package/dist/components/grid/GridRow.d.ts.map +1 -0
  39. package/dist/components/grid/GridRow.js +7 -0
  40. package/dist/components/grid/GridRow.js.map +1 -0
  41. package/dist/components/icon/allowedIcons.d.ts +1 -0
  42. package/dist/components/icon/allowedIcons.d.ts.map +1 -1
  43. package/dist/components/icon/allowedIcons.js +2 -1
  44. package/dist/components/icon/allowedIcons.js.map +1 -1
  45. package/dist/index.css +252 -0
  46. package/dist/index.css.map +1 -1
  47. package/dist/index.d.ts +2 -0
  48. package/dist/index.d.ts.map +1 -1
  49. package/dist/index.js +2 -0
  50. package/dist/index.js.map +1 -1
  51. package/package.json +3 -1
  52. package/src/components/button/button.scss +2 -0
  53. package/src/components/fileUpload/FileUpload.stories.tsx +920 -0
  54. package/src/components/fileUpload/FileUpload.test.tsx +172 -0
  55. package/src/components/fileUpload/FileUpload.tsx +144 -0
  56. package/src/components/fileUpload/fileUpload.scss +74 -0
  57. package/src/components/formField/inputs/selectDropdown/SelectDropdown.stories.tsx +15 -16
  58. package/src/components/formField/inputs/selectDropdown/SelectDropdown.test.tsx +19 -0
  59. package/src/components/formField/inputs/selectDropdown/SelectDropdown.tsx +1 -1
  60. package/src/components/grid/Grid.stories.tsx +1130 -0
  61. package/src/components/grid/Grid.test.tsx +67 -0
  62. package/src/components/grid/Grid.tsx +34 -0
  63. package/src/components/grid/GridColumn.tsx +31 -0
  64. package/src/components/grid/GridRow.tsx +29 -0
  65. package/src/components/icon/allowedIcons.tsx +2 -0
  66. package/src/components/progress/progress.scss +1 -0
  67. package/src/docs/Contributing.mdx +16 -0
  68. package/src/index.scss +2 -0
  69. package/src/index.ts +2 -0
@@ -0,0 +1,67 @@
1
+ import { expect, test, describe } from 'vitest';
2
+ import { render, screen } from '@testing-library/react';
3
+ import '@testing-library/jest-dom/vitest';
4
+ import { Grid } from './Grid.js';
5
+
6
+ describe('Grid', () => {
7
+ test('renders govuk-main-wrapper class', () => {
8
+ const { container } = render(<Grid />);
9
+ expect(container.firstChild).toHaveClass('govuk-main-wrapper');
10
+ });
11
+
12
+ test('renders children', () => {
13
+ render(<Grid><span>School report</span></Grid>);
14
+ expect(screen.getByText('School report')).toBeInTheDocument();
15
+ });
16
+
17
+ test('merges custom className with govuk-main-wrapper', () => {
18
+ const { container } = render(<Grid className="my-layout" />);
19
+ expect(container.firstChild).toHaveClass('govuk-main-wrapper', 'my-layout');
20
+ });
21
+ });
22
+
23
+ describe('Grid.Row', () => {
24
+ test('renders govuk-grid-row class', () => {
25
+ const { container } = render(<Grid.Row />);
26
+ expect(container.firstChild).toHaveClass('govuk-grid-row');
27
+ });
28
+
29
+ test('renders children', () => {
30
+ render(<Grid.Row><span>Attendance data</span></Grid.Row>);
31
+ expect(screen.getByText('Attendance data')).toBeInTheDocument();
32
+ });
33
+
34
+ test('merges custom className with govuk-grid-row', () => {
35
+ const { container } = render(<Grid.Row className="my-row" />);
36
+ expect(container.firstChild).toHaveClass('govuk-grid-row', 'my-row');
37
+ });
38
+ });
39
+
40
+ describe('Grid.Column', () => {
41
+ test('defaults to govuk-grid-column-full when columnWidth is omitted', () => {
42
+ const { container } = render(<Grid.Column />);
43
+ expect(container.firstChild).toHaveClass('govuk-grid-column-full');
44
+ });
45
+
46
+ test('renders children', () => {
47
+ render(<Grid.Column columnWidth="full"><span>Student profile</span></Grid.Column>);
48
+ expect(screen.getByText('Student profile')).toBeInTheDocument();
49
+ });
50
+
51
+ test('merges custom className', () => {
52
+ const { container } = render(<Grid.Column columnWidth="full" className="my-col" />);
53
+ expect(container.firstChild).toHaveClass('govuk-grid-column-full', 'my-col');
54
+ });
55
+
56
+ test.each([
57
+ ['full', 'govuk-grid-column-full'],
58
+ ['one-half', 'govuk-grid-column-one-half'],
59
+ ['one-third', 'govuk-grid-column-one-third'],
60
+ ['two-thirds', 'govuk-grid-column-two-thirds'],
61
+ ['one-quarter', 'govuk-grid-column-one-quarter'],
62
+ ['three-quarters', 'govuk-grid-column-three-quarters'],
63
+ ] as const)('applies %s class for columnWidth="%s"', (width, expectedClass) => {
64
+ const { container } = render(<Grid.Column columnWidth={width} />);
65
+ expect(container.firstChild).toHaveClass(expectedClass);
66
+ });
67
+ });
@@ -0,0 +1,34 @@
1
+ import classNames from 'classnames';
2
+ import type { ReactNode } from 'react';
3
+ import { GridRow } from './GridRow.js';
4
+ import { GridColumn } from './GridColumn.js';
5
+
6
+ export type GridProps = {
7
+ className?: string;
8
+ children?: ReactNode;
9
+ };
10
+
11
+ export const Grid = (props: GridProps) => {
12
+ const {
13
+ className,
14
+ children,
15
+ } = props;
16
+
17
+ return (
18
+ <div
19
+ className={classNames(
20
+ 'govuk-main-wrapper',
21
+ className,
22
+ )}
23
+ >
24
+ {children}
25
+ </div>
26
+ );
27
+ };
28
+
29
+ Grid.Row = GridRow;
30
+ Grid.Column = GridColumn;
31
+
32
+ export namespace Grid {
33
+ export type Props = GridProps;
34
+ }
@@ -0,0 +1,31 @@
1
+ import classNames from 'classnames';
2
+ import type { ReactNode } from 'react';
3
+
4
+ export type GridColumnProps = {
5
+ className?: string;
6
+ children?: ReactNode;
7
+ columnWidth?: 'one-quarter' | 'three-quarters' | 'one-third' | 'two-thirds' | 'one-half' | 'full';
8
+ };
9
+
10
+ export const GridColumn = (props: GridColumnProps) => {
11
+ const {
12
+ className,
13
+ children,
14
+ columnWidth = 'full',
15
+ } = props;
16
+
17
+ return (
18
+ <div
19
+ className={classNames(
20
+ `govuk-grid-column-${columnWidth}`,
21
+ className,
22
+ )}
23
+ >
24
+ {children}
25
+ </div>
26
+ );
27
+ };
28
+
29
+ export namespace GridColumn {
30
+ export type Props = GridColumnProps;
31
+ }
@@ -0,0 +1,29 @@
1
+ import classNames from 'classnames';
2
+ import type { ReactNode } from 'react';
3
+
4
+ export type GridRowProps = {
5
+ className?: string;
6
+ children?: ReactNode;
7
+ };
8
+
9
+ export const GridRow = (props: GridRowProps) => {
10
+ const {
11
+ className,
12
+ children,
13
+ } = props;
14
+
15
+ return (
16
+ <div
17
+ className={classNames(
18
+ 'govuk-grid-row',
19
+ className,
20
+ )}
21
+ >
22
+ {children}
23
+ </div>
24
+ );
25
+ };
26
+
27
+ export namespace GridRow {
28
+ export type Props = GridRowProps;
29
+ }
@@ -29,6 +29,7 @@ import {
29
29
  Clipboard,
30
30
  ClipboardList,
31
31
  Clock3,
32
+ CloudUpload,
32
33
  Copy,
33
34
  CornerDownLeft,
34
35
  Dot,
@@ -127,6 +128,7 @@ export const allowedIcons = {
127
128
  'clipboard-list': ClipboardList,
128
129
  'clipboard': Clipboard,
129
130
  'clock-3': Clock3,
131
+ 'cloud-upload': CloudUpload,
130
132
  'copy': Copy,
131
133
  'corner-down-left': CornerDownLeft,
132
134
  'date': CalendarFold,
@@ -9,5 +9,6 @@
9
9
  height: 100%;
10
10
  background-color: var(--color-brand-600);
11
11
  border-radius: var(--border-radius-large);
12
+ transition: transform 250ms linear;
12
13
  }
13
14
  }
@@ -52,6 +52,8 @@ It also automatically adds the component's exports to `src/index.ts` and `src/in
52
52
 
53
53
  ## Key conventions
54
54
 
55
+ Most of these are enforced automatically by ESLint — run `yarn eslint --fix` and let it guide you. A few the linter can't catch are worth knowing.
56
+
55
57
  ### File and directory naming
56
58
 
57
59
  <table>
@@ -97,6 +99,20 @@ import { Button } from '../../components/button/Button'; // ✗
97
99
  </tbody>
98
100
  </table>
99
101
 
102
+ ### Prefer team hooks
103
+
104
+ Before writing your own hook, check `Utils/hooks` — reuse one that already exists, and reach for one that encapsulates a common pattern rather than hand-rolling it. For example, use `useComponentDidMount` for run-once-on-mount effects rather than `useEffect(fn, [])`. Always give `useEffect` a dependency array, even an empty one.
105
+
106
+ ### One component per file
107
+
108
+ Keep one component per file. This applies to compound components too: define each part in its own file and assemble the public API in the root component's file by importing the parts. `Table` is a good example — it pulls in `TableHeader`, `TableFooter`, and its cell renderers from their own files. See the **Compound components** design principle below for the API pattern itself.
109
+
110
+ ### Keep comments rare and meaningful
111
+
112
+ Good code is self-documenting, so comments should be the exception rather than the rule. Before writing one, make the code explain itself instead: choose descriptive names, and lift complex expressions or conditions into well-named constants. A clear name is worth more than a sentence describing it.
113
+
114
+ Reserve comments for the _why_ behind something unusual — a constraint, a workaround, a non-obvious decision — never the _what_ the code already says plainly. If you feel the need to explain a piece of code, that's often a sign the code itself should be clearer. This matters especially for agent-assisted changes, which tend to over-narrate — strip the running commentary before opening a PR.
115
+
100
116
  ---
101
117
 
102
118
  ## Design principles
package/src/index.scss CHANGED
@@ -1,4 +1,5 @@
1
1
  @use "../node_modules/react-day-picker/src/style.css";
2
+ @use "../node_modules/govuk-frontend/dist/govuk/objects/grid.import.scss";
2
3
  @use "./tokens.scss";
3
4
  @use "./global.scss";
4
5
  @use "components/breadcrumbs/breadcrumbs.scss";
@@ -58,6 +59,7 @@
58
59
  @use "components/dataViewCard/dataViewCard.scss";
59
60
  @use "components/treeRow/treeRow.scss";
60
61
  @use "components/sidebarNav/sidebarNav.scss";
62
+ @use "components/fileUpload/fileUpload.scss";
61
63
  @use "components/skeleton/skeleton.scss";
62
64
 
63
65
  // stylelint-disable-next-line at-rule-disallowed-list -- plain CSS import (font face), exempt from Sass @import deprecation
package/src/index.ts CHANGED
@@ -88,3 +88,5 @@ export { PopupParentContext } from 'Utils/popupParent/PopupParentContext';
88
88
  export { SlideoverUtils } from 'Utils/SlideoverUtils';
89
89
  export { ArborLogo, type ArborLogoProps } from 'Components/arborLogo/ArborLogo';
90
90
  export { DataViewCard, type DataViewCardProps } from 'Components/dataViewCard/DataViewCard';
91
+ export { FileUpload, type FileUploadProps } from 'Components/fileUpload/FileUpload';
92
+ export { Grid, type GridProps } from 'Components/grid/Grid';