uikit-react-public 0.40.3 → 0.41.0

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 (30) hide show
  1. package/dist/components/BreadcrumbsNew/BaseBreadcrumbsItem.d.ts +1 -2
  2. package/dist/components/BreadcrumbsNew/BreadcrumbsLink.d.ts +3 -1
  3. package/dist/components/ProgressBar/ProgressBar.d.ts +24 -0
  4. package/dist/components/ProgressBar/ProgressBar.stories.d.ts +77 -0
  5. package/dist/components/ProgressBar/__tests__/ProgressBar.test.d.ts +1 -0
  6. package/dist/components/ProgressBar/index.d.ts +2 -0
  7. package/dist/components/Table/Table.context.d.ts +2 -0
  8. package/dist/components/Table/Table.d.ts +1 -1
  9. package/dist/components/Table/Table.stories.d.ts +1 -1
  10. package/dist/components/Table/Table.types.d.ts +2 -0
  11. package/dist/components/index.d.ts +2 -0
  12. package/dist/index.js +5717 -5554
  13. package/lib/components/BreadcrumbsNew/BaseBreadcrumbsItem.tsx +0 -9
  14. package/lib/components/BreadcrumbsNew/BreadcrumbsLink.tsx +23 -6
  15. package/lib/components/BreadcrumbsNew/__tests__/Breadcrumbs.test.tsx +3 -0
  16. package/lib/components/ProgressBar/ProgressBar.stories.tsx +131 -0
  17. package/lib/components/ProgressBar/ProgressBar.tsx +220 -0
  18. package/lib/components/ProgressBar/__tests__/ProgressBar.test.tsx +120 -0
  19. package/lib/components/ProgressBar/index.ts +6 -0
  20. package/lib/components/Table/Table.context.ts +10 -1
  21. package/lib/components/Table/Table.tsx +8 -3
  22. package/lib/components/Table/Table.types.ts +2 -0
  23. package/lib/components/Table/__tests__/Table.test.tsx +90 -0
  24. package/lib/components/Table/subcomponents/Body.tsx +7 -1
  25. package/lib/components/Table/subcomponents/Cell/Cell.tsx +22 -18
  26. package/lib/components/Table/subcomponents/Cell/CellContent.tsx +11 -5
  27. package/lib/components/Table/subcomponents/Head.tsx +7 -1
  28. package/lib/components/Table/subcomponents/Row.tsx +10 -6
  29. package/lib/components/index.ts +7 -0
  30. package/package.json +1 -1
@@ -3,6 +3,10 @@ import { describe, expect, test } from 'vitest';
3
3
  import { fireEvent, render, screen, within } from '@testing-library/react';
4
4
  import Table from '../Table';
5
5
  import { ThemeContextProvider } from '../../../theme/useTheme';
6
+ import defaultTheme from '../../../theme/original/defaultTheme';
7
+
8
+ const getGeneratedClass = (element: HTMLElement) =>
9
+ [...element.classList].find((className) => className.startsWith('css-'));
6
10
 
7
11
  describe('Table', () => {
8
12
  // Snapshot tests
@@ -231,4 +235,90 @@ describe('Table', () => {
231
235
 
232
236
  expect(row).toHaveAttribute('data-mobile-expanded', 'true');
233
237
  });
238
+
239
+ test('uses the real mobile breakpoint for the card layout by default', () => {
240
+ render(
241
+ <ThemeContextProvider>
242
+ <Table>
243
+ <Table.Body>
244
+ <Table.Row>
245
+ <Table.Cell>Test Cell</Table.Cell>
246
+ </Table.Row>
247
+ </Table.Body>
248
+ </Table>
249
+ </ThemeContextProvider>
250
+ );
251
+
252
+ const table = screen.getByTestId('ucl-uikit-table');
253
+ const tableClass = getGeneratedClass(table);
254
+ const mobileMaxWidth = defaultTheme.breakpoints.tablet - 1;
255
+
256
+ expect(tableClass).toBeDefined();
257
+ expect(document.head.textContent).toContain(
258
+ `@media screen and (max-width: ${mobileMaxWidth}px){.${tableClass}{display:block;border-collapse:separate;}}`
259
+ );
260
+ });
261
+
262
+ test('disableMobileView removes the mobile-card layout media query from the table', () => {
263
+ render(
264
+ <ThemeContextProvider>
265
+ <Table disableMobileView>
266
+ <Table.Body>
267
+ <Table.Row>
268
+ <Table.Cell>Test Cell</Table.Cell>
269
+ </Table.Row>
270
+ </Table.Body>
271
+ </Table>
272
+ </ThemeContextProvider>
273
+ );
274
+
275
+ const table = screen.getByTestId('ucl-uikit-table');
276
+ const tableClass = getGeneratedClass(table);
277
+ const mobileMaxWidth = defaultTheme.breakpoints.tablet - 1;
278
+
279
+ expect(tableClass).toBeDefined();
280
+ expect(document.head.textContent).toContain(
281
+ `@media screen and (max-width: -1px){.${tableClass}{display:block;border-collapse:separate;}}`
282
+ );
283
+ expect(document.head.textContent).not.toContain(
284
+ `@media screen and (max-width: ${mobileMaxWidth}px){.${tableClass}{display:block;border-collapse:separate;}}`
285
+ );
286
+ });
287
+
288
+ test('disableMobileView also disables the row card layout and details disclosure media queries', () => {
289
+ render(
290
+ <ThemeContextProvider>
291
+ <Table disableMobileView>
292
+ <Table.Head>
293
+ <Table.HeadCell mobileRole='primary'>Name</Table.HeadCell>
294
+ <Table.HeadCell>Email</Table.HeadCell>
295
+ </Table.Head>
296
+ <Table.Body>
297
+ <Table.Row>
298
+ <Table.Cell>Ada Lovelace</Table.Cell>
299
+ <Table.Cell>ada@example.com</Table.Cell>
300
+ </Table.Row>
301
+ </Table.Body>
302
+ </Table>
303
+ </ThemeContextProvider>
304
+ );
305
+
306
+ const row = screen.getByTestId('ucl-uikit-table__row');
307
+ const rowClass = getGeneratedClass(row);
308
+ const detailsCell = row.querySelector('[data-mobile-role="details"]');
309
+ const detailsClass =
310
+ detailsCell && getGeneratedClass(detailsCell as HTMLElement);
311
+
312
+ expect(rowClass).toBeDefined();
313
+ expect(document.head.textContent).toContain(
314
+ `@media screen and (max-width: -1px){.${rowClass}{display:grid;`
315
+ );
316
+
317
+ // The details disclosure cell is hidden via a min-width query one above
318
+ // the (disabled) mobile breakpoint, so it forces display:none at every width.
319
+ expect(detailsClass).toBeDefined();
320
+ expect(document.head.textContent).toContain(
321
+ `@media screen and (min-width: 0px){.${detailsClass}{display:none;}}`
322
+ );
323
+ });
234
324
  });
@@ -1,5 +1,6 @@
1
1
  import { css, cx } from '@emotion/css';
2
2
  import { useTheme } from '../../../theme';
3
+ import { getMobileBreakpoint, useTableContext } from '../Table.context';
3
4
 
4
5
  export interface TableBodyProps extends React.HTMLAttributes<HTMLTableSectionElement> {}
5
6
 
@@ -7,9 +8,14 @@ const NAME = 'ucl-uikit-table__body';
7
8
 
8
9
  const Body = ({ className, children, ...props }: TableBodyProps) => {
9
10
  const [theme] = useTheme();
11
+ const { disableMobileView } = useTableContext();
12
+ const mobileBreakpoint = getMobileBreakpoint(
13
+ theme.breakpoints.tablet,
14
+ disableMobileView
15
+ );
10
16
 
11
17
  const baseStyle = css`
12
- @media screen and (max-width: ${theme.breakpoints.tablet - 1}px) {
18
+ @media screen and (max-width: ${mobileBreakpoint}px) {
13
19
  display: block;
14
20
  width: 100%;
15
21
  }
@@ -1,7 +1,7 @@
1
1
  import { css, cx } from '@emotion/css';
2
2
  import CellContent from './CellContent';
3
3
  import { useTheme } from '../../../../theme';
4
- import { useTableContext } from '../../Table.context';
4
+ import { getMobileBreakpoint, useTableContext } from '../../Table.context';
5
5
  import type {
6
6
  ColumnVariant,
7
7
  NormalizedTableMobileRole,
@@ -62,7 +62,11 @@ const Cell = ({
62
62
  ...props
63
63
  }: TableCellProps) => {
64
64
  const [theme] = useTheme();
65
- const { columns } = useTableContext();
65
+ const { columns, disableMobileView } = useTableContext();
66
+ const mobileBreakpoint = getMobileBreakpoint(
67
+ theme.breakpoints.tablet,
68
+ disableMobileView
69
+ );
66
70
  const mobileColumn = columns[__mobileColumnIndex ?? -1];
67
71
  const mobileRole = mobileColumn?.mobileRole ?? getDefaultMobileRole(variant);
68
72
  const mobileLabel = mobileColumn?.mobileLabel;
@@ -96,7 +100,7 @@ const Cell = ({
96
100
  font-weight: ${theme.typography.body.sm.fontWeight};
97
101
  line-height: ${theme.typography.body.sm.lineHeight}%;
98
102
 
99
- @media screen and (max-width: ${theme.breakpoints.tablet - 1}px) {
103
+ @media screen and (max-width: ${mobileBreakpoint}px) {
100
104
  min-width: 0;
101
105
  height: auto;
102
106
  padding: 0;
@@ -104,7 +108,7 @@ const Cell = ({
104
108
  `;
105
109
 
106
110
  const mobileSelectionStyle = css`
107
- @media screen and (max-width: ${theme.breakpoints.tablet - 1}px) {
111
+ @media screen and (max-width: ${mobileBreakpoint}px) {
108
112
  grid-column: 1;
109
113
  grid-row: 1 / span 2;
110
114
  order: 0;
@@ -114,7 +118,7 @@ const Cell = ({
114
118
  `;
115
119
 
116
120
  const mobilePrimaryStyle = css`
117
- @media screen and (max-width: ${theme.breakpoints.tablet - 1}px) {
121
+ @media screen and (max-width: ${mobileBreakpoint}px) {
118
122
  display: grid;
119
123
  grid-template-columns: minmax(0, 1fr) auto;
120
124
  align-items: start;
@@ -124,26 +128,26 @@ const Cell = ({
124
128
  `;
125
129
 
126
130
  const mobilePrimaryAfterSelectionStyle = css`
127
- @media screen and (max-width: ${theme.breakpoints.tablet - 1}px) {
131
+ @media screen and (max-width: ${mobileBreakpoint}px) {
128
132
  grid-column: 2;
129
133
  }
130
134
  `;
131
135
 
132
136
  const mobilePrimaryWithoutSelectionStyle = css`
133
- @media screen and (max-width: ${theme.breakpoints.tablet - 1}px) {
137
+ @media screen and (max-width: ${mobileBreakpoint}px) {
134
138
  grid-column: 1 / 3;
135
139
  }
136
140
  `;
137
141
 
138
142
  const mobilePrimaryWithPrimaryMetaStyle = css`
139
- @media screen and (max-width: ${theme.breakpoints.tablet - 1}px) {
143
+ @media screen and (max-width: ${mobileBreakpoint}px) {
140
144
  grid-row: 2;
141
145
  order: 2;
142
146
  }
143
147
  `;
144
148
 
145
149
  const mobilePrimaryWithoutPrimaryMetaStyle = css`
146
- @media screen and (max-width: ${theme.breakpoints.tablet - 1}px) {
150
+ @media screen and (max-width: ${mobileBreakpoint}px) {
147
151
  grid-row: 1 / span 2;
148
152
  order: 1;
149
153
  align-self: center;
@@ -151,7 +155,7 @@ const Cell = ({
151
155
  `;
152
156
 
153
157
  const mobilePrimaryMetaStyle = css`
154
- @media screen and (max-width: ${theme.breakpoints.tablet - 1}px) {
158
+ @media screen and (max-width: ${mobileBreakpoint}px) {
155
159
  grid-row: 1;
156
160
  order: 1;
157
161
  min-height: 18px;
@@ -159,19 +163,19 @@ const Cell = ({
159
163
  `;
160
164
 
161
165
  const mobilePrimaryMetaAfterSelectionStyle = css`
162
- @media screen and (max-width: ${theme.breakpoints.tablet - 1}px) {
166
+ @media screen and (max-width: ${mobileBreakpoint}px) {
163
167
  grid-column: 2;
164
168
  }
165
169
  `;
166
170
 
167
171
  const mobilePrimaryMetaWithoutSelectionStyle = css`
168
- @media screen and (max-width: ${theme.breakpoints.tablet - 1}px) {
172
+ @media screen and (max-width: ${mobileBreakpoint}px) {
169
173
  grid-column: 1 / 3;
170
174
  }
171
175
  `;
172
176
 
173
177
  const mobileStatusStyle = css`
174
- @media screen and (max-width: ${theme.breakpoints.tablet - 1}px) {
178
+ @media screen and (max-width: ${mobileBreakpoint}px) {
175
179
  grid-column: 3;
176
180
  grid-row: 1 / span 2;
177
181
  order: 2;
@@ -180,7 +184,7 @@ const Cell = ({
180
184
  `;
181
185
 
182
186
  const mobileContextMenuStyle = css`
183
- @media screen and (max-width: ${theme.breakpoints.tablet - 1}px) {
187
+ @media screen and (max-width: ${mobileBreakpoint}px) {
184
188
  grid-column: 4;
185
189
  grid-row: 1 / span 2;
186
190
  order: 3;
@@ -189,7 +193,7 @@ const Cell = ({
189
193
  `;
190
194
 
191
195
  const mobileFieldStyle = css`
192
- @media screen and (max-width: ${theme.breakpoints.tablet - 1}px) {
196
+ @media screen and (max-width: ${mobileBreakpoint}px) {
193
197
  display: grid;
194
198
  grid-template-columns: minmax(90px, 32%) minmax(0, 1fr);
195
199
  grid-column: 1 / -1;
@@ -207,7 +211,7 @@ const Cell = ({
207
211
  `;
208
212
 
209
213
  const mobileFirstFieldStyle = css`
210
- @media screen and (max-width: ${theme.breakpoints.tablet - 1}px) {
214
+ @media screen and (max-width: ${mobileBreakpoint}px) {
211
215
  margin-top: ${theme.margin.m16};
212
216
  padding-top: ${theme.padding.p12};
213
217
  border-top: ${theme.border.b1} solid ${theme.colour.border.default};
@@ -215,7 +219,7 @@ const Cell = ({
215
219
  `;
216
220
 
217
221
  const mobilePrimaryActionStyle = css`
218
- @media screen and (max-width: ${theme.breakpoints.tablet - 1}px) {
222
+ @media screen and (max-width: ${mobileBreakpoint}px) {
219
223
  grid-column: 1 / -1;
220
224
  order: 30;
221
225
  margin-top: ${theme.margin.m8};
@@ -225,7 +229,7 @@ const Cell = ({
225
229
  `;
226
230
 
227
231
  const mobileHiddenStyle = css`
228
- @media screen and (max-width: ${theme.breakpoints.tablet - 1}px) {
232
+ @media screen and (max-width: ${mobileBreakpoint}px) {
229
233
  display: none;
230
234
  }
231
235
  `;
@@ -4,6 +4,7 @@ import type { CheckboxProps } from '../../../Checkbox/Checkbox';
4
4
  import Button from '../../../Button';
5
5
  import type { ButtonProps } from '../../../Button';
6
6
  import { useTheme } from '../../../../theme';
7
+ import { getMobileBreakpoint, useTableContext } from '../../Table.context';
7
8
  import type {
8
9
  ColumnVariant,
9
10
  NormalizedTableMobileRole,
@@ -37,6 +38,11 @@ const CellContent = ({
37
38
  children,
38
39
  }: CellContentProps) => {
39
40
  const [theme] = useTheme();
41
+ const { disableMobileView } = useTableContext();
42
+ const mobileBreakpoint = getMobileBreakpoint(
43
+ theme.breakpoints.tablet,
44
+ disableMobileView
45
+ );
40
46
 
41
47
  const baseStyle = css`
42
48
  display: flex;
@@ -67,7 +73,7 @@ const CellContent = ({
67
73
  `;
68
74
 
69
75
  const mobileStyle = css`
70
- @media screen and (max-width: ${theme.breakpoints.tablet - 1}px) {
76
+ @media screen and (max-width: ${mobileBreakpoint}px) {
71
77
  align-items: flex-start;
72
78
  justify-content: flex-start;
73
79
  min-width: 0;
@@ -77,7 +83,7 @@ const CellContent = ({
77
83
  `;
78
84
 
79
85
  const mobilePrimaryStyle = css`
80
- @media screen and (max-width: ${theme.breakpoints.tablet - 1}px) {
86
+ @media screen and (max-width: ${mobileBreakpoint}px) {
81
87
  display: -webkit-box;
82
88
  overflow: hidden;
83
89
  color: ${theme.colour.text.default};
@@ -92,7 +98,7 @@ const CellContent = ({
92
98
  `;
93
99
 
94
100
  const mobilePrimaryMetaStyle = css`
95
- @media screen and (max-width: ${theme.breakpoints.tablet - 1}px) {
101
+ @media screen and (max-width: ${mobileBreakpoint}px) {
96
102
  color: ${theme.colour.text.secondary};
97
103
  font-family: ${theme.typography.body.xs.fontFamily};
98
104
  font-feature-settings: ${theme.typography.body.xs.fontSettings};
@@ -103,14 +109,14 @@ const CellContent = ({
103
109
  `;
104
110
 
105
111
  const mobilePrimaryActionStyle = css`
106
- @media screen and (max-width: ${theme.breakpoints.tablet - 1}px) {
112
+ @media screen and (max-width: ${mobileBreakpoint}px) {
107
113
  color: ${theme.colour.link.visited};
108
114
  font-weight: ${theme.typography.body.sm.fontWeight};
109
115
  }
110
116
  `;
111
117
 
112
118
  const mobileHeaderTrailingStyle = css`
113
- @media screen and (max-width: ${theme.breakpoints.tablet - 1}px) {
119
+ @media screen and (max-width: ${mobileBreakpoint}px) {
114
120
  justify-content: flex-end;
115
121
  }
116
122
  `;
@@ -1,5 +1,6 @@
1
1
  import { css, cx } from '@emotion/css';
2
2
  import { useTheme } from '../../../theme';
3
+ import { getMobileBreakpoint, useTableContext } from '../Table.context';
3
4
 
4
5
  export interface TableHeadProps extends React.HTMLAttributes<HTMLTableSectionElement> {}
5
6
 
@@ -7,12 +8,17 @@ const NAME = 'ucl-uikit-table__head';
7
8
 
8
9
  const Head = ({ className, children, ...props }: TableHeadProps) => {
9
10
  const [theme] = useTheme();
11
+ const { disableMobileView } = useTableContext();
12
+ const mobileBreakpoint = getMobileBreakpoint(
13
+ theme.breakpoints.tablet,
14
+ disableMobileView
15
+ );
10
16
 
11
17
  const baseStyle = css`
12
18
  height: 40px;
13
19
  background-color: ${theme.colour.surface.secondary};
14
20
 
15
- @media screen and (max-width: ${theme.breakpoints.tablet - 1}px) {
21
+ @media screen and (max-width: ${mobileBreakpoint}px) {
16
22
  position: absolute;
17
23
  width: 1px;
18
24
  height: 1px;
@@ -1,7 +1,7 @@
1
1
  import { Children, cloneElement, isValidElement, useState } from 'react';
2
2
  import { css, cx } from '@emotion/css';
3
3
  import { useTheme } from '../../../theme';
4
- import { useTableContext } from '../Table.context';
4
+ import { getMobileBreakpoint, useTableContext } from '../Table.context';
5
5
  import Icon from '../../Icon/Icon';
6
6
  import type { TableCellProps } from './Cell/Cell';
7
7
  import type { NormalizedTableMobileRole } from '../Table.types';
@@ -41,7 +41,11 @@ const Row = ({
41
41
  ...props
42
42
  }: TableRowProps) => {
43
43
  const [theme] = useTheme();
44
- const { columns } = useTableContext();
44
+ const { columns, disableMobileView } = useTableContext();
45
+ const mobileBreakpoint = getMobileBreakpoint(
46
+ theme.breakpoints.tablet,
47
+ disableMobileView
48
+ );
45
49
  const [uncontrolledMobileExpanded, setUncontrolledMobileExpanded] = useState(
46
50
  defaultMobileExpanded
47
51
  );
@@ -93,7 +97,7 @@ const Row = ({
93
97
  background-color: ${theme.colour.surface.secondary};
94
98
  }
95
99
 
96
- @media screen and (max-width: ${theme.breakpoints.tablet - 1}px) {
100
+ @media screen and (max-width: ${mobileBreakpoint}px) {
97
101
  display: grid;
98
102
  grid-template-columns: auto minmax(0, 1fr) auto;
99
103
  align-items: start;
@@ -127,7 +131,7 @@ const Row = ({
127
131
  background-color: ${theme.colour.surface.brandSecondary};
128
132
  }
129
133
 
130
- @media screen and (max-width: ${theme.breakpoints.tablet - 1}px) {
134
+ @media screen and (max-width: ${mobileBreakpoint}px) {
131
135
  background-color: ${theme.colour.surface.brandSecondary};
132
136
  border-color: ${theme.colour.border.brandSubtle};
133
137
 
@@ -138,7 +142,7 @@ const Row = ({
138
142
  `;
139
143
 
140
144
  const mobileContextMenuGridStyle = css`
141
- @media screen and (max-width: ${theme.breakpoints.tablet - 1}px) {
145
+ @media screen and (max-width: ${mobileBreakpoint}px) {
142
146
  grid-template-columns: auto minmax(0, 1fr) auto auto;
143
147
  }
144
148
  `;
@@ -157,7 +161,7 @@ const Row = ({
157
161
  order: 10;
158
162
  margin-top: ${theme.margin.m8};
159
163
 
160
- @media screen and (min-width: ${theme.breakpoints.tablet}px) {
164
+ @media screen and (min-width: ${mobileBreakpoint + 1}px) {
161
165
  display: none;
162
166
  }
163
167
  `;
@@ -46,6 +46,13 @@ export type { BaseCheckboxProps, BaseCheckboxState } from './BaseCheckbox';
46
46
  export { default as Spinner } from './Spinner';
47
47
  export type { SpinnerProps } from './Spinner';
48
48
 
49
+ export { default as ProgressBar } from './ProgressBar';
50
+ export type {
51
+ ProgressBarProps,
52
+ ProgressBarSize,
53
+ ProgressBarVariant,
54
+ } from './ProgressBar';
55
+
49
56
  export { default as Textarea } from './Textarea';
50
57
  export type { TextareaProps } from './Textarea';
51
58
 
package/package.json CHANGED
@@ -2,7 +2,7 @@
2
2
  "name": "uikit-react-public",
3
3
  "private": false,
4
4
  "license": "UNLICENSED",
5
- "version": "0.40.3",
5
+ "version": "0.41.0",
6
6
  "type": "module",
7
7
  "main": "dist/index.js",
8
8
  "types": "dist/index.d.ts",