uikit-react-public 0.11.24 → 0.14.21

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 (184) hide show
  1. package/dist/components/Badge/Badge.d.ts +6 -0
  2. package/dist/components/Badge/Badge.stories.d.ts +15 -0
  3. package/dist/components/Badge/index.d.ts +2 -0
  4. package/dist/components/Button/Button.d.ts +2 -1
  5. package/dist/components/CookieNotice/CookieNotice.d.ts +16 -0
  6. package/dist/components/CookieNotice/index.d.ts +2 -0
  7. package/dist/components/Dialog/BaseDialog.d.ts +7 -2
  8. package/dist/components/FileInput/FileInput.d.ts +8 -0
  9. package/dist/components/FileInput/FileInput.stories.d.ts +16 -0
  10. package/dist/components/FileInput/__tests__/FileInput.test.d.ts +1 -0
  11. package/dist/components/FileInput/index.d.ts +2 -0
  12. package/dist/components/Header/Header.d.ts +4 -1
  13. package/dist/components/Heading/Heading.d.ts +1 -1
  14. package/dist/components/Link/BaseLink.d.ts +10 -0
  15. package/dist/components/Link/Link.d.ts +5 -10
  16. package/dist/components/Link/Link.stories.d.ts +1 -1
  17. package/dist/components/Link/index.d.ts +1 -1
  18. package/dist/components/Menu/MenuContent.d.ts +1 -1
  19. package/dist/components/Menu/MenuItem.d.ts +2 -0
  20. package/dist/components/Menu/MenuSection.d.ts +1 -1
  21. package/dist/components/Search/Search.d.ts +16 -0
  22. package/dist/components/Search/Search.stories.d.ts +34 -0
  23. package/dist/components/Search/__tests__/Search.test.d.ts +1 -0
  24. package/dist/components/Search/index.d.ts +2 -0
  25. package/dist/components/Select/Select.d.ts +1 -1
  26. package/dist/components/Select/Select.stories.d.ts +3 -7
  27. package/dist/components/Select/Select.types.d.ts +19 -14
  28. package/dist/components/Select/subcomponents/CustomOption.d.ts +1 -1
  29. package/dist/components/Select/subcomponents/CustomSelect.d.ts +1 -2
  30. package/dist/components/Select/subcomponents/Panel.d.ts +1 -1
  31. package/dist/components/Select/subcomponents/VisibleField.d.ts +4 -4
  32. package/dist/components/StandaloneLink/StandaloneLink.d.ts +12 -0
  33. package/dist/components/StandaloneLink/StandaloneLink.stories.d.ts +13 -0
  34. package/dist/components/StandaloneLink/__tests__/StandaloneLink.test.d.ts +1 -0
  35. package/dist/components/StandaloneLink/index.d.ts +2 -0
  36. package/dist/components/Table/Table.d.ts +10 -8
  37. package/dist/components/Table/Table.stories.d.ts +21 -0
  38. package/dist/components/Table/Table.types.d.ts +11 -0
  39. package/dist/components/Table/__tests__/Table.test.d.ts +1 -0
  40. package/dist/components/Table/index.d.ts +2 -1
  41. package/dist/components/Table/subcomponents/Body.d.ts +4 -0
  42. package/dist/components/Table/subcomponents/Cell/Cell.d.ts +12 -0
  43. package/dist/components/Table/subcomponents/Cell/Cell.stories.d.ts +313 -0
  44. package/dist/components/Table/subcomponents/Cell/CellContent.d.ts +10 -0
  45. package/dist/components/Table/subcomponents/Cell/__tests__/Cell.test.d.ts +1 -0
  46. package/dist/components/Table/subcomponents/Head.d.ts +4 -0
  47. package/dist/components/Table/subcomponents/HeadCell/HeadCell.d.ts +13 -0
  48. package/dist/components/Table/subcomponents/HeadCell/HeadCell.stories.d.ts +312 -0
  49. package/dist/components/Table/subcomponents/HeadCell/HeadCellContent.d.ts +10 -0
  50. package/dist/components/Table/subcomponents/HeadCell/__tests__/HeadCell.test.d.ts +1 -0
  51. package/dist/components/Table/subcomponents/Row.d.ts +5 -0
  52. package/dist/components/Table/subcomponents/SortIcon.d.ts +7 -0
  53. package/dist/components/Table/subcomponents/index.d.ts +10 -0
  54. package/dist/components/Tabs/Tab.d.ts +1 -1
  55. package/dist/components/Tabs/TabContext.d.ts +1 -0
  56. package/dist/components/Tabs/Tabs.d.ts +3 -1
  57. package/dist/components/Tabs/Tabs.stories.d.ts +3 -0
  58. package/dist/components/Timepicker/Timepicker.d.ts +10 -0
  59. package/dist/components/Timepicker/Timepicker.stories.d.ts +7 -0
  60. package/dist/components/Timepicker/__tests__/Timepicker.test.d.ts +1 -0
  61. package/dist/components/Timepicker/index.d.ts +2 -0
  62. package/dist/components/Timepicker/utils/convertDateToTimeString.d.ts +2 -0
  63. package/dist/components/Timepicker/utils/convertDateToTimeString.test.d.ts +1 -0
  64. package/dist/components/Timepicker/utils/index.d.ts +1 -0
  65. package/dist/components/WeekPicker/WeekPicker.d.ts +3 -0
  66. package/dist/components/WeekPicker/index.d.ts +1 -0
  67. package/dist/components/WeekPicker/subcomponents/CustomDatepicker.d.ts +17 -0
  68. package/dist/components/WeekPicker/subcomponents/DatepickerInput.d.ts +13 -0
  69. package/dist/components/WeekPicker/subcomponents/VisibleField.d.ts +15 -0
  70. package/dist/components/WeekPicker/subcomponents/index.d.ts +3 -0
  71. package/dist/components/index.d.ts +11 -0
  72. package/dist/hooks/index.d.ts +2 -0
  73. package/dist/hooks/useFocusTrap.d.ts +9 -0
  74. package/dist/index.d.ts +1 -0
  75. package/dist/index.js +5703 -4448
  76. package/dist/theme/defaultTheme.d.ts +7 -0
  77. package/dist/theme/useTheme.d.ts +14 -0
  78. package/dist/utils/__tests__/capitalise.test.d.ts +1 -0
  79. package/dist/utils/capitalise.d.ts +2 -0
  80. package/lib/components/Alert/Alert.tsx +7 -1
  81. package/lib/components/Alert/__tests__/__snapshots__/Alert.test.tsx.snap +4 -0
  82. package/lib/components/Badge/Badge.stories.tsx +19 -0
  83. package/lib/components/Badge/Badge.tsx +48 -0
  84. package/lib/components/Badge/index.ts +2 -0
  85. package/lib/components/Breadcrumbs/__tests__/__snapshots__/Breadcrumbs.test.tsx.snap +4 -4
  86. package/lib/components/Button/Button.tsx +5 -2
  87. package/lib/components/Calendar/subcomponents/Grid.tsx +0 -1
  88. package/lib/components/CookieNotice/CookieNotice.tsx +114 -0
  89. package/lib/components/CookieNotice/index.ts +2 -0
  90. package/lib/components/Dialog/BaseDialog.tsx +44 -4
  91. package/lib/components/Field/__tests__/Field.test.tsx +148 -148
  92. package/lib/components/FileInput/FileInput.stories.tsx +70 -0
  93. package/lib/components/FileInput/FileInput.tsx +68 -0
  94. package/lib/components/FileInput/__tests__/FileInput.test.tsx +99 -0
  95. package/lib/components/FileInput/__tests__/__snapshots__/FileInput.test.tsx.snap +91 -0
  96. package/lib/components/FileInput/index.ts +2 -0
  97. package/lib/components/Footer/__tests__/__snapshots__/Footer.test.tsx.snap +25 -25
  98. package/lib/components/Header/Header.tsx +19 -2
  99. package/lib/components/Header/__tests__/__snapshots__/Header.test.tsx.snap +4 -4
  100. package/lib/components/Heading/Documentation.mdx +1 -1
  101. package/lib/components/Heading/Heading.tsx +1 -1
  102. package/lib/components/Heading/__tests__/Heading.test.tsx +7 -19
  103. package/lib/components/Heading/__tests__/__snapshots__/Heading.test.tsx.snap +7 -7
  104. package/lib/components/Label/Label.tsx +0 -2
  105. package/lib/components/Label/__tests__/__snapshots__/Label.test.tsx.snap +7 -7
  106. package/lib/components/Link/BaseLink.tsx +84 -0
  107. package/lib/components/Link/Link.tsx +72 -32
  108. package/lib/components/Link/__tests__/__snapshots__/link.test.tsx.snap +3 -3
  109. package/lib/components/Link/__tests__/link.test.tsx +6 -13
  110. package/lib/components/Link/index.ts +1 -1
  111. package/lib/components/Menu/Menu.context.tsx +3 -1
  112. package/lib/components/Menu/Menu.tsx +2 -2
  113. package/lib/components/Menu/MenuContent.tsx +5 -5
  114. package/lib/components/Menu/MenuItem.tsx +20 -3
  115. package/lib/components/Menu/MenuSection.tsx +4 -3
  116. package/lib/components/Pagination/PaginationControls.tsx +1 -3
  117. package/lib/components/Search/Search.stories.tsx +41 -0
  118. package/lib/components/Search/Search.tsx +167 -0
  119. package/lib/components/Search/__tests__/Search.test.tsx +94 -0
  120. package/lib/components/Search/__tests__/__snapshots__/Search.test.tsx.snap +179 -0
  121. package/lib/components/Search/index.ts +2 -0
  122. package/lib/components/Select/Select.stories.tsx +8 -35
  123. package/lib/components/Select/Select.tsx +2 -2
  124. package/lib/components/Select/Select.types.ts +20 -15
  125. package/lib/components/Select/__tests__/__snapshots__/Select.test.tsx.snap +3 -3
  126. package/lib/components/Select/subcomponents/CustomOption.tsx +22 -9
  127. package/lib/components/Select/subcomponents/CustomSelect.tsx +31 -20
  128. package/lib/components/Select/subcomponents/Panel.tsx +4 -5
  129. package/lib/components/Select/subcomponents/VisibleField.tsx +26 -22
  130. package/lib/components/StandaloneLink/StandaloneLink.stories.tsx +32 -0
  131. package/lib/components/StandaloneLink/StandaloneLink.tsx +183 -0
  132. package/lib/components/StandaloneLink/__tests__/StandaloneLink.test.tsx +57 -0
  133. package/lib/components/StandaloneLink/__tests__/__snapshots__/StandaloneLink.test.tsx.snap +19 -0
  134. package/lib/components/StandaloneLink/index.ts +2 -0
  135. package/lib/components/Table/Table.stories.tsx +337 -0
  136. package/lib/components/Table/Table.tsx +42 -67
  137. package/lib/components/Table/Table.types.ts +14 -0
  138. package/lib/components/Table/__tests__/Table.test.tsx +121 -0
  139. package/lib/components/Table/__tests__/__snapshots__/Table.test.tsx.snap +210 -0
  140. package/lib/components/Table/index.ts +8 -1
  141. package/lib/components/Table/subcomponents/Body.tsx +18 -0
  142. package/lib/components/Table/subcomponents/Cell/Cell.stories.tsx +151 -0
  143. package/lib/components/Table/subcomponents/Cell/Cell.tsx +72 -0
  144. package/lib/components/Table/subcomponents/Cell/CellContent.tsx +91 -0
  145. package/lib/components/Table/subcomponents/Cell/__tests__/Cell.test.tsx +115 -0
  146. package/lib/components/Table/subcomponents/Cell/__tests__/__snapshots__/Cell.test.tsx.snap +107 -0
  147. package/lib/components/Table/subcomponents/Head.tsx +34 -0
  148. package/lib/components/Table/subcomponents/HeadCell/HeadCell.stories.tsx +85 -0
  149. package/lib/components/Table/subcomponents/HeadCell/HeadCell.tsx +99 -0
  150. package/lib/components/Table/subcomponents/HeadCell/HeadCellContent.tsx +61 -0
  151. package/lib/components/Table/subcomponents/HeadCell/__tests__/HeadCell.test.tsx +137 -0
  152. package/lib/components/Table/subcomponents/HeadCell/__tests__/__snapshots__/HeadCell.test.tsx.snap +110 -0
  153. package/lib/components/Table/subcomponents/Row.tsx +49 -0
  154. package/lib/components/Table/subcomponents/SortIcon.tsx +63 -0
  155. package/lib/components/Table/subcomponents/index.ts +14 -0
  156. package/lib/components/Tabs/Tab.tsx +3 -3
  157. package/lib/components/Tabs/TabContext.tsx +1 -0
  158. package/lib/components/Tabs/Tabs.stories.tsx +9 -3
  159. package/lib/components/Tabs/Tabs.tsx +10 -32
  160. package/lib/components/Tabs/__tests__/Tabs.test.tsx +10 -4
  161. package/lib/components/Tabs/__tests__/__snapshots__/Tabs.test.tsx.snap +32 -32
  162. package/lib/components/Timepicker/Timepicker.stories.tsx +43 -0
  163. package/lib/components/Timepicker/Timepicker.tsx +96 -0
  164. package/lib/components/Timepicker/__tests__/Timepicker.test.tsx +55 -0
  165. package/lib/components/Timepicker/__tests__/__snapshots__/Timepicker.test.tsx.snap +19 -0
  166. package/lib/components/Timepicker/index.tsx +2 -0
  167. package/lib/components/Timepicker/utils/convertDateToTimeString.test.ts +54 -0
  168. package/lib/components/Timepicker/utils/convertDateToTimeString.ts +10 -0
  169. package/lib/components/Timepicker/utils/index.ts +1 -0
  170. package/lib/components/WeekPicker/WeekPicker.tsx +26 -0
  171. package/lib/components/WeekPicker/index.ts +1 -0
  172. package/lib/components/WeekPicker/subcomponents/CustomDatepicker.tsx +298 -0
  173. package/lib/components/WeekPicker/subcomponents/DatepickerInput.tsx +111 -0
  174. package/lib/components/WeekPicker/subcomponents/VisibleField.tsx +126 -0
  175. package/lib/components/WeekPicker/subcomponents/index.ts +3 -0
  176. package/lib/components/index.ts +17 -0
  177. package/lib/hooks/index.ts +2 -0
  178. package/lib/hooks/useFocusTrap.ts +123 -0
  179. package/lib/index.ts +1 -0
  180. package/lib/theme/defaultTheme.ts +7 -0
  181. package/lib/utils/__tests__/capitalise.test.ts +40 -0
  182. package/lib/utils/capitalise.ts +4 -0
  183. package/package.json +1 -1
  184. package/lib/components/Field/__tests__/__snapshots__/Field.test.tsx.snap +0 -300
@@ -0,0 +1,107 @@
1
+ // Vitest Snapshot v1, https://vitest.dev/guide/snapshot.html
2
+
3
+ exports[`Cell > Snapshot: default 1`] = `
4
+ <table>
5
+ <tbody>
6
+ <tr>
7
+ <td
8
+ class="css-u1gowl ucl-uikit-table__cell"
9
+ data-testid="ucl-uikit-table__cell"
10
+ >
11
+ <div
12
+ class="ucl-uikit-table__cell-content css-1ao6jhw"
13
+ data-testid="ucl-uikit-table__cell-content"
14
+ >
15
+ Default cell
16
+ </div>
17
+ </td>
18
+ </tr>
19
+ </tbody>
20
+ </table>
21
+ `;
22
+
23
+ exports[`Cell > Snapshot: variants 1`] = `
24
+ <table>
25
+ <tbody>
26
+ <tr>
27
+ <td
28
+ class="css-u1gowl ucl-uikit-table__cell"
29
+ data-testid="ucl-uikit-table__cell"
30
+ >
31
+ <div
32
+ class="ucl-uikit-table__cell-content css-tlcu3i"
33
+ data-testid="ucl-uikit-table__cell-content"
34
+ >
35
+ 123
36
+ </div>
37
+ </td>
38
+ <td
39
+ class="css-u1gowl ucl-uikit-table__cell"
40
+ data-testid="ucl-uikit-table__cell"
41
+ >
42
+ <div
43
+ class="ucl-uikit-table__cell-content css-1kkenvm"
44
+ data-testid="ucl-uikit-table__cell-content"
45
+ >
46
+ <span
47
+ class="ucl-uikit-checkbox css-cg31xm"
48
+ >
49
+ <input
50
+ class="css-nzy7im"
51
+ data-testid="ucl-uikit-checkbox"
52
+ type="checkbox"
53
+ />
54
+ </span>
55
+ </div>
56
+ </td>
57
+ <td
58
+ class="css-u1gowl ucl-uikit-table__cell"
59
+ data-testid="ucl-uikit-table__cell"
60
+ >
61
+ <div
62
+ class="ucl-uikit-table__cell-content css-1ao6jhw"
63
+ data-testid="ucl-uikit-table__cell-content"
64
+ >
65
+ <svg
66
+ class="ucl-uikit-icon css-148hpxb"
67
+ data-testid="ucl-uikit-icon"
68
+ fill="none"
69
+ height="24"
70
+ stroke="currentColor"
71
+ stroke-linecap="round"
72
+ stroke-linejoin="round"
73
+ stroke-width="2"
74
+ viewBox="0 0 24 24"
75
+ width="24"
76
+ xmlns="http://www.w3.org/2000/svg"
77
+ >
78
+ <path
79
+ d="M11 4H4a2 2 0 0 0-2 2v14a2 2 0 0 0 2 2h14a2 2 0 0 0 2-2v-7"
80
+ />
81
+ <path
82
+ d="M18.5 2.5a2.121 2.121 0 0 1 3 3L12 15l-4 1 1-4 9.5-9.5z"
83
+ />
84
+ </svg>
85
+ </div>
86
+ </td>
87
+ <td
88
+ class="css-u1gowl ucl-uikit-table__cell"
89
+ data-testid="ucl-uikit-table__cell"
90
+ >
91
+ <div
92
+ class="css-1fubti ucl-uikit-table__cell-content"
93
+ data-testid="ucl-uikit-table__cell-content"
94
+ >
95
+ <button
96
+ aria-disabled="false"
97
+ class="ucl-uikit-button css-3pq14u"
98
+ data-testid="ucl-uikit-button"
99
+ >
100
+ Button
101
+ </button>
102
+ </div>
103
+ </td>
104
+ </tr>
105
+ </tbody>
106
+ </table>
107
+ `;
@@ -0,0 +1,34 @@
1
+ import { css, cx } from '@emotion/css';
2
+ import { useTheme } from '../../../theme';
3
+
4
+ export interface TableHeadProps
5
+ extends React.HTMLAttributes<HTMLTableSectionElement> {}
6
+
7
+ const NAME = 'ucl-uikit-table__head';
8
+
9
+ const Head = ({ className, children, ...props }: TableHeadProps) => {
10
+ const [theme] = useTheme();
11
+
12
+ const baseStyle = css`
13
+ height: 40px;
14
+ background-color: #f8f8f8; // TODO: Add a design token
15
+ `;
16
+
17
+ const rowStyle = css`
18
+ border-bottom: 1px solid ${theme.color.neutral.grey20};
19
+ `;
20
+
21
+ const style = cx(baseStyle, className, NAME);
22
+
23
+ return (
24
+ <thead
25
+ className={style}
26
+ data-testid={NAME}
27
+ {...props}
28
+ >
29
+ <tr className={rowStyle}>{children}</tr>
30
+ </thead>
31
+ );
32
+ };
33
+
34
+ export default Head;
@@ -0,0 +1,85 @@
1
+ import { useState } from 'react';
2
+ import type { Meta, StoryObj } from '@storybook/react';
3
+ import HeadCell from './HeadCell';
4
+ import Head from '../Head';
5
+ import { SortOrder } from '../../Table.types';
6
+
7
+ const meta = {
8
+ title: 'Components/Work in progress/Table/HeadCell',
9
+ component: HeadCell,
10
+ parameters: {
11
+ layout: 'centered',
12
+ },
13
+ args: {
14
+ variant: 'default',
15
+ accessor: 'name',
16
+ sort: null,
17
+ showSortIcon: true,
18
+ children: 'Head Cell',
19
+ },
20
+ tags: ['autodocs'],
21
+ decorators: [
22
+ (Story) => (
23
+ <table style={{ borderCollapse: 'collapse' }}>
24
+ <Head>
25
+ <Story />
26
+ </Head>
27
+ </table>
28
+ ),
29
+ ],
30
+ } satisfies Meta<typeof HeadCell>;
31
+
32
+ export default meta;
33
+ type Story = StoryObj<typeof meta>;
34
+
35
+ export const Default: Story = {
36
+ render: (args) => {
37
+ const [sort, setSort] = useState<SortOrder>(null);
38
+ const handleSortChange = (
39
+ accessor: string,
40
+ newSort: SortOrder,
41
+ event: React.UIEvent
42
+ ) => {
43
+ setSort(newSort);
44
+ console.log('Sort changed:', accessor, newSort, event);
45
+ };
46
+ return (
47
+ <HeadCell
48
+ {...args}
49
+ sort={sort}
50
+ onSortChange={handleSortChange}
51
+ />
52
+ );
53
+ },
54
+ };
55
+
56
+ export const NoSorting: Story = {
57
+ name: 'No sorting icon',
58
+ args: {
59
+ showSortIcon: false,
60
+ },
61
+ };
62
+
63
+ export const Checkbox: Story = {
64
+ name: 'Checkbox variant',
65
+ args: {
66
+ variant: 'checkbox',
67
+ },
68
+ render: (args) => {
69
+ const [checked, setChecked] = useState(false);
70
+ const handleCheck = (
71
+ checked: boolean,
72
+ event: React.ChangeEvent<HTMLInputElement>
73
+ ) => {
74
+ setChecked(checked);
75
+ console.log('Checkbox changed:', checked, event);
76
+ };
77
+ return (
78
+ <HeadCell
79
+ {...args}
80
+ checked={checked}
81
+ onCheck={handleCheck}
82
+ />
83
+ );
84
+ },
85
+ };
@@ -0,0 +1,99 @@
1
+ import { css, cx } from '@emotion/css';
2
+ import { useTheme } from '../../../../theme';
3
+ import HeadCellContent from './HeadCellContent';
4
+ import type { ColumnVariant, SortOrder } from '../../Table.types';
5
+
6
+ export interface TableHeadCellProps
7
+ extends React.HTMLAttributes<HTMLTableCellElement> {
8
+ variant?: ColumnVariant;
9
+ accessor?: string;
10
+ sort?: SortOrder;
11
+ onSortChange?: (
12
+ accessor: string,
13
+ sort: SortOrder,
14
+ event: React.UIEvent
15
+ ) => void;
16
+ showSortIcon?: boolean;
17
+ checked?: boolean;
18
+ onCheck?: (
19
+ checked: boolean,
20
+ event: React.ChangeEvent<HTMLInputElement>
21
+ ) => void;
22
+ testId?: string;
23
+ }
24
+
25
+ const NAME = 'ucl-uikit-table__head-cell';
26
+
27
+ const HeadCell = ({
28
+ variant = 'default',
29
+ accessor,
30
+ sort = null,
31
+ onSortChange,
32
+ showSortIcon = true,
33
+ checked = false,
34
+ onCheck,
35
+ testId = NAME,
36
+ className,
37
+ children,
38
+ ...props
39
+ }: TableHeadCellProps) => {
40
+ const [theme] = useTheme();
41
+
42
+ const isSortable = variant !== 'checkbox' && onSortChange && accessor;
43
+
44
+ const handleClick = (event: React.MouseEvent) => {
45
+ if (onSortChange && !accessor)
46
+ console.warn(`${NAME}: onSortChange requires an accessor to be defined.`);
47
+ else if (isSortable) {
48
+ // Rotate sorting order on click
49
+ if (sort === 'asc') {
50
+ onSortChange(accessor, 'desc', event);
51
+ } else if (sort === 'desc') {
52
+ onSortChange(accessor, null, event);
53
+ } else {
54
+ onSortChange(accessor, 'asc', event);
55
+ }
56
+ }
57
+ };
58
+
59
+ const handleCheckboxChange = (event: React.ChangeEvent<HTMLInputElement>) => {
60
+ if (variant === 'checkbox' && onCheck) onCheck(event.target.checked, event);
61
+ };
62
+
63
+ const baseStyle = css`
64
+ padding: ${theme.padding.p8} ${theme.padding.p16};
65
+ color: ${theme.color.text.secondary};
66
+ font-family: ${theme.font.family.primary};
67
+ font-weight: 400;
68
+ text-align: left;
69
+ cursor: pointer;
70
+ user-select: none;
71
+ `;
72
+
73
+ const style = cx(baseStyle, className, NAME);
74
+
75
+ return (
76
+ <th
77
+ onClick={handleClick}
78
+ scope='col'
79
+ className={style}
80
+ data-testid={testId}
81
+ data-accessor={accessor}
82
+ data-sort={sort}
83
+ role={isSortable ? 'button' : undefined}
84
+ {...props}
85
+ >
86
+ <HeadCellContent
87
+ variant={variant}
88
+ sort={sort}
89
+ showSortIcon={showSortIcon}
90
+ checked={checked}
91
+ onCheckboxChange={handleCheckboxChange}
92
+ >
93
+ {children}
94
+ </HeadCellContent>
95
+ </th>
96
+ );
97
+ };
98
+
99
+ export default HeadCell;
@@ -0,0 +1,61 @@
1
+ import { css, cx } from '@emotion/css';
2
+ import SortIcon from '../SortIcon';
3
+ import Checkbox from '../../../Checkbox/Checkbox';
4
+ import type { ColumnVariant, SortOrder } from '../../Table.types';
5
+
6
+ interface HeadCellContentProps extends React.HTMLAttributes<HTMLDivElement> {
7
+ variant: ColumnVariant;
8
+ sort: SortOrder;
9
+ showSortIcon: boolean;
10
+ checked: boolean;
11
+ onCheckboxChange: (event: React.ChangeEvent<HTMLInputElement>) => void;
12
+ }
13
+
14
+ const NAME = 'ucl-uikit-table__head-cell-content';
15
+
16
+ const HeadCellContent = ({
17
+ variant,
18
+ sort,
19
+ showSortIcon,
20
+ checked,
21
+ onCheckboxChange,
22
+ children,
23
+ }: HeadCellContentProps) => {
24
+ const baseStyle = css`
25
+ display: flex;
26
+ align-items: center;
27
+ gap: 8px;
28
+ `;
29
+
30
+ const checkboxVariantStyle = css`
31
+ justify-content: flex-end;
32
+ `;
33
+
34
+ const style = cx(
35
+ baseStyle,
36
+ variant === 'checkbox' && checkboxVariantStyle,
37
+ NAME
38
+ );
39
+
40
+ return (
41
+ <div
42
+ className={style}
43
+ data-testid={NAME}
44
+ >
45
+ {variant === 'default' && (
46
+ <>
47
+ {children}
48
+ {showSortIcon && <SortIcon sortOrder={sort} />}
49
+ </>
50
+ )}
51
+ {variant === 'checkbox' && (
52
+ <Checkbox
53
+ checked={checked}
54
+ onChange={onCheckboxChange}
55
+ />
56
+ )}
57
+ </div>
58
+ );
59
+ };
60
+
61
+ export default HeadCellContent;
@@ -0,0 +1,137 @@
1
+ import { describe, expect, test } from 'vitest';
2
+ import { render, screen } from '@testing-library/react';
3
+ import HeadCell from '../HeadCell';
4
+ import { ThemeContextProvider } from '../../../../../theme/useTheme';
5
+
6
+ describe('HeadCell', () => {
7
+ // Snapshot tests
8
+
9
+ test('Snapshot: default', () => {
10
+ const renderResult = render(
11
+ <ThemeContextProvider>
12
+ <table>
13
+ <thead>
14
+ <tr>
15
+ <HeadCell>Default header cell</HeadCell>
16
+ </tr>
17
+ </thead>
18
+ </table>
19
+ </ThemeContextProvider>
20
+ );
21
+ expect(renderResult.container.firstChild).toMatchSnapshot();
22
+ });
23
+
24
+ test('no sorting icon', () => {
25
+ const renderResult = render(
26
+ <ThemeContextProvider>
27
+ <table>
28
+ <thead>
29
+ <tr>
30
+ <HeadCell showSortIcon={false}>No sorting icon</HeadCell>
31
+ </tr>
32
+ </thead>
33
+ </table>
34
+ </ThemeContextProvider>
35
+ );
36
+ expect(renderResult.container.firstChild).toMatchSnapshot();
37
+ });
38
+
39
+ test('Snapshot: checkbox variant', () => {
40
+ const renderResult = render(
41
+ <ThemeContextProvider>
42
+ <table>
43
+ <thead>
44
+ <tr>
45
+ <HeadCell variant='checkbox'>Checkbox header cell</HeadCell>
46
+ </tr>
47
+ </thead>
48
+ </table>
49
+ </ThemeContextProvider>
50
+ );
51
+ expect(renderResult.container.firstChild).toMatchSnapshot();
52
+ });
53
+
54
+ // Unit tests
55
+
56
+ test('Text is visible via children prop', () => {
57
+ render(
58
+ <ThemeContextProvider>
59
+ <table>
60
+ <thead>
61
+ <tr>
62
+ <HeadCell>Visible header text</HeadCell>
63
+ </tr>
64
+ </thead>
65
+ </table>
66
+ </ThemeContextProvider>
67
+ );
68
+ expect(screen.getByText('Visible header text')).toBeInTheDocument();
69
+ expect(screen.getByText('Visible header text')).toBeVisible();
70
+ });
71
+
72
+ test('Checkbox variant has a checkbox', () => {
73
+ render(
74
+ <ThemeContextProvider>
75
+ <table>
76
+ <thead>
77
+ <tr>
78
+ <HeadCell variant='checkbox'>Checkbox header cell</HeadCell>
79
+ </tr>
80
+ </thead>
81
+ </table>
82
+ </ThemeContextProvider>
83
+ );
84
+ expect(screen.getByRole('checkbox')).toBeInTheDocument();
85
+ });
86
+
87
+ test('Can be found via default testId', () => {
88
+ const defaultTestId = 'ucl-uikit-table__head-cell';
89
+ render(
90
+ <ThemeContextProvider>
91
+ <table>
92
+ <thead>
93
+ <tr>
94
+ <HeadCell>Test Header Cell</HeadCell>
95
+ </tr>
96
+ </thead>
97
+ </table>
98
+ </ThemeContextProvider>
99
+ );
100
+ expect(screen.getByTestId(defaultTestId)).toBeInTheDocument();
101
+ });
102
+
103
+ test('Can be found via custom testId', () => {
104
+ const customTestId = 'custom-header-cell-test-id';
105
+ render(
106
+ <ThemeContextProvider>
107
+ <table>
108
+ <thead>
109
+ <tr>
110
+ <HeadCell testId={customTestId}>Test Header Cell</HeadCell>
111
+ </tr>
112
+ </thead>
113
+ </table>
114
+ </ThemeContextProvider>
115
+ );
116
+ expect(screen.getByTestId(customTestId)).toBeInTheDocument();
117
+ });
118
+
119
+ test('accessor prop is data-accessor attribute', () => {
120
+ const accessor = 'test-accessor';
121
+ render(
122
+ <ThemeContextProvider>
123
+ <table>
124
+ <thead>
125
+ <tr>
126
+ <HeadCell accessor={accessor}>Header with accessor</HeadCell>
127
+ </tr>
128
+ </thead>
129
+ </table>
130
+ </ThemeContextProvider>
131
+ );
132
+ expect(screen.getByTestId('ucl-uikit-table__head-cell')).toHaveAttribute(
133
+ 'data-accessor',
134
+ accessor
135
+ );
136
+ });
137
+ });
@@ -0,0 +1,110 @@
1
+ // Vitest Snapshot v1, https://vitest.dev/guide/snapshot.html
2
+
3
+ exports[`HeadCell > Snapshot: checkbox variant 1`] = `
4
+ <table>
5
+ <thead>
6
+ <tr>
7
+ <th
8
+ class="css-1g8x9da ucl-uikit-table__head-cell"
9
+ data-testid="ucl-uikit-table__head-cell"
10
+ scope="col"
11
+ >
12
+ <div
13
+ class="ucl-uikit-table__head-cell-content css-18gk4sb"
14
+ data-testid="ucl-uikit-table__head-cell-content"
15
+ >
16
+ <span
17
+ class="ucl-uikit-checkbox css-cg31xm"
18
+ >
19
+ <input
20
+ class="css-nzy7im"
21
+ data-testid="ucl-uikit-checkbox"
22
+ type="checkbox"
23
+ />
24
+ </span>
25
+ </div>
26
+ </th>
27
+ </tr>
28
+ </thead>
29
+ </table>
30
+ `;
31
+
32
+ exports[`HeadCell > Snapshot: default 1`] = `
33
+ <table>
34
+ <thead>
35
+ <tr>
36
+ <th
37
+ class="css-1g8x9da ucl-uikit-table__head-cell"
38
+ data-testid="ucl-uikit-table__head-cell"
39
+ scope="col"
40
+ >
41
+ <div
42
+ class="css-13bwe7d ucl-uikit-table__head-cell-content"
43
+ data-testid="ucl-uikit-table__head-cell-content"
44
+ >
45
+ Default header cell
46
+ <svg
47
+ fill="none"
48
+ height="16"
49
+ viewBox="0 0 48 48"
50
+ width="16"
51
+ xmlns="http://www.w3.org/2000/svg"
52
+ >
53
+ <g>
54
+ <path
55
+ d="M8 28L15 35L22 28"
56
+ stroke="#CCCCCC"
57
+ stroke-linecap="round"
58
+ stroke-linejoin="round"
59
+ stroke-width="4"
60
+ />
61
+ <path
62
+ d="M15 35V10"
63
+ stroke="#CCCCCC"
64
+ stroke-linecap="round"
65
+ stroke-linejoin="round"
66
+ stroke-width="4"
67
+ />
68
+ <path
69
+ d="M43 19L36 12L29 19"
70
+ stroke="#CCCCCC"
71
+ stroke-linecap="round"
72
+ stroke-linejoin="round"
73
+ stroke-width="4"
74
+ />
75
+ <path
76
+ d="M36 12V37"
77
+ stroke="#CCCCCC"
78
+ stroke-linecap="round"
79
+ stroke-linejoin="round"
80
+ stroke-width="4"
81
+ />
82
+ </g>
83
+ </svg>
84
+ </div>
85
+ </th>
86
+ </tr>
87
+ </thead>
88
+ </table>
89
+ `;
90
+
91
+ exports[`HeadCell > no sorting icon 1`] = `
92
+ <table>
93
+ <thead>
94
+ <tr>
95
+ <th
96
+ class="css-1g8x9da ucl-uikit-table__head-cell"
97
+ data-testid="ucl-uikit-table__head-cell"
98
+ scope="col"
99
+ >
100
+ <div
101
+ class="css-13bwe7d ucl-uikit-table__head-cell-content"
102
+ data-testid="ucl-uikit-table__head-cell-content"
103
+ >
104
+ No sorting icon
105
+ </div>
106
+ </th>
107
+ </tr>
108
+ </thead>
109
+ </table>
110
+ `;
@@ -0,0 +1,49 @@
1
+ import { css, cx } from '@emotion/css';
2
+ import { useTheme } from '../../../theme';
3
+
4
+ export interface TableRowProps
5
+ extends React.HTMLAttributes<HTMLTableRowElement> {
6
+ selected?: boolean;
7
+ }
8
+
9
+ const NAME = 'ucl-uikit-table__row';
10
+
11
+ const Row = ({
12
+ selected = false,
13
+ className,
14
+ children,
15
+ ...props
16
+ }: TableRowProps) => {
17
+ const [theme] = useTheme();
18
+
19
+ const baseStyle = css`
20
+ height: 40px;
21
+ border-bottom: 1px solid ${theme.color.neutral.grey20};
22
+
23
+ &:hover {
24
+ background-color: ${theme.color.neutral.grey5};
25
+ }
26
+ `;
27
+
28
+ const highlightedStyle = css`
29
+ background-color: ${theme.color.interaction.blue5};
30
+
31
+ &:hover {
32
+ background-color: ${theme.color.interaction.blue5};
33
+ }
34
+ `;
35
+
36
+ const style = cx(baseStyle, selected && highlightedStyle, className, NAME);
37
+
38
+ return (
39
+ <tr
40
+ className={style}
41
+ data-testid={NAME}
42
+ {...props}
43
+ >
44
+ {children}
45
+ </tr>
46
+ );
47
+ };
48
+
49
+ export default Row;