uikit-react-public 0.21.9 → 0.22.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.
- package/dist/components/Spinner/Spinner.d.ts +3 -2
- package/dist/components/Spinner/Spinner.stories.d.ts +1 -1
- package/dist/components/index.d.ts +2 -0
- package/dist/index.js +2668 -2639
- package/lib/components/Breadcrumbs/__tests__/__snapshots__/Breadcrumbs.test.tsx.snap +4 -4
- package/lib/components/Button/__tests__/__snapshots__/Button.test.tsx.snap +5 -3
- package/lib/components/Field/Field.tsx +0 -3
- package/lib/components/Footer/__tests__/__snapshots__/Footer.test.tsx.snap +25 -25
- package/lib/components/FooterNew/__tests__/__snapshots__/Footer.test.tsx.snap +28 -28
- package/lib/components/Link/BaseLink.tsx +4 -1
- package/lib/components/Link/__tests__/__snapshots__/link.test.tsx.snap +2 -2
- package/lib/components/Spinner/Spinner.tsx +69 -70
- package/lib/components/Spinner/__tests__/Spinner.test.tsx +33 -1
- package/lib/components/Spinner/__tests__/__snapshots__/Spinner.test.tsx.snap +20 -12
- package/lib/components/StandaloneLink/__tests__/__snapshots__/StandaloneLink.test.tsx.snap +2 -2
- package/lib/components/Table/improvements-tracking.md +25 -0
- package/lib/components/index.ts +3 -0
- package/package.json +2 -1
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { SVGAttributes,
|
|
1
|
+
import { SVGAttributes, Ref, memo } from 'react';
|
|
2
2
|
import { css, cx } from '@emotion/css';
|
|
3
3
|
import { useTheme } from '../../theme';
|
|
4
4
|
|
|
@@ -8,87 +8,86 @@ export interface SpinnerProps extends SVGAttributes<SVGSVGElement> {
|
|
|
8
8
|
size?: number;
|
|
9
9
|
strokeWidth?: number;
|
|
10
10
|
testId?: string;
|
|
11
|
+
ref?: Ref<SVGSVGElement>;
|
|
11
12
|
inheritColour?: boolean;
|
|
12
13
|
}
|
|
13
14
|
|
|
14
|
-
const Spinner =
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
ref
|
|
25
|
-
) => {
|
|
26
|
-
const [theme] = useTheme();
|
|
15
|
+
const Spinner = ({
|
|
16
|
+
size = 72,
|
|
17
|
+
strokeWidth = 4,
|
|
18
|
+
className,
|
|
19
|
+
testId = NAME,
|
|
20
|
+
inheritColour = false,
|
|
21
|
+
ref,
|
|
22
|
+
...rest
|
|
23
|
+
}: SpinnerProps) => {
|
|
24
|
+
const [theme] = useTheme();
|
|
27
25
|
|
|
28
|
-
|
|
29
|
-
|
|
26
|
+
const rotationDuration = `3s`; // rotation duration
|
|
27
|
+
const dashDuration = `2s`; // dash duration
|
|
30
28
|
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
29
|
+
const baseStyle = css`
|
|
30
|
+
color: ${inheritColour ? 'inherit' : theme.colour.icon.brand};
|
|
31
|
+
`;
|
|
34
32
|
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
33
|
+
const gStyle = css`
|
|
34
|
+
transform-origin: 50% 50%;
|
|
35
|
+
animation: rotate ${rotationDuration} linear infinite;
|
|
38
36
|
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
}
|
|
37
|
+
@keyframes rotate {
|
|
38
|
+
100% {
|
|
39
|
+
transform: rotate(360deg);
|
|
43
40
|
}
|
|
44
|
-
|
|
41
|
+
}
|
|
42
|
+
`;
|
|
45
43
|
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
44
|
+
const circleStyle = css`
|
|
45
|
+
stroke-linecap: square;
|
|
46
|
+
animation: dash ${dashDuration} ease-in-out infinite;
|
|
49
47
|
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
}
|
|
55
|
-
50% {
|
|
56
|
-
stroke-dasharray: 90, 150;
|
|
57
|
-
stroke-dashoffset: -35;
|
|
58
|
-
}
|
|
59
|
-
100% {
|
|
60
|
-
stroke-dasharray: 90, 150;
|
|
61
|
-
stroke-dashoffset: -124;
|
|
62
|
-
}
|
|
48
|
+
@keyframes dash {
|
|
49
|
+
0% {
|
|
50
|
+
stroke-dasharray: 1, 150;
|
|
51
|
+
stroke-dashoffset: 0;
|
|
63
52
|
}
|
|
64
|
-
|
|
53
|
+
50% {
|
|
54
|
+
stroke-dasharray: 90, 150;
|
|
55
|
+
stroke-dashoffset: -35;
|
|
56
|
+
}
|
|
57
|
+
100% {
|
|
58
|
+
stroke-dasharray: 90, 150;
|
|
59
|
+
stroke-dashoffset: -124;
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
`;
|
|
65
63
|
|
|
66
|
-
|
|
64
|
+
const style = cx(NAME, baseStyle, className);
|
|
67
65
|
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
);
|
|
66
|
+
return (
|
|
67
|
+
<svg
|
|
68
|
+
role='progressbar'
|
|
69
|
+
aria-label='Loading'
|
|
70
|
+
viewBox='0 0 50 50'
|
|
71
|
+
className={style}
|
|
72
|
+
data-testid={testId}
|
|
73
|
+
ref={ref}
|
|
74
|
+
width={size} // Set the width of the SVG element
|
|
75
|
+
height={size} // Set the height of the SVG element
|
|
76
|
+
{...rest}
|
|
77
|
+
>
|
|
78
|
+
<g className={gStyle}>
|
|
79
|
+
<circle
|
|
80
|
+
className={circleStyle}
|
|
81
|
+
cx='25'
|
|
82
|
+
cy='25'
|
|
83
|
+
r='20'
|
|
84
|
+
fill='none'
|
|
85
|
+
stroke='currentColor'
|
|
86
|
+
strokeWidth={strokeWidth}
|
|
87
|
+
/>
|
|
88
|
+
</g>
|
|
89
|
+
</svg>
|
|
90
|
+
);
|
|
91
|
+
};
|
|
93
92
|
|
|
94
93
|
export default memo(Spinner);
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { describe, expect, test } from 'vitest';
|
|
2
|
-
import { render } from '@testing-library/react';
|
|
2
|
+
import { render, screen } from '@testing-library/react';
|
|
3
3
|
import { css } from '@emotion/css';
|
|
4
4
|
import SpinnerSvg from '../Spinner';
|
|
5
5
|
import { ThemeContextProvider } from '../../..';
|
|
@@ -68,4 +68,36 @@ describe('SpinnerSvg', () => {
|
|
|
68
68
|
const svg = getByTestId('custom-test-id');
|
|
69
69
|
expect(svg).toBeDefined();
|
|
70
70
|
});
|
|
71
|
+
|
|
72
|
+
// Accessibility tests
|
|
73
|
+
|
|
74
|
+
test('has role="progressbar" by default', () => {
|
|
75
|
+
render(
|
|
76
|
+
<ThemeContextProvider>
|
|
77
|
+
<SpinnerSvg />
|
|
78
|
+
</ThemeContextProvider>
|
|
79
|
+
);
|
|
80
|
+
expect(screen.getByRole('progressbar')).toBeInTheDocument();
|
|
81
|
+
});
|
|
82
|
+
|
|
83
|
+
test('has aria-label="Loading" by default', () => {
|
|
84
|
+
render(
|
|
85
|
+
<ThemeContextProvider>
|
|
86
|
+
<SpinnerSvg />
|
|
87
|
+
</ThemeContextProvider>
|
|
88
|
+
);
|
|
89
|
+
expect(screen.getByRole('progressbar')).toHaveAccessibleName('Loading');
|
|
90
|
+
});
|
|
91
|
+
|
|
92
|
+
test('aria-label can be overridden via props', () => {
|
|
93
|
+
render(
|
|
94
|
+
<ThemeContextProvider>
|
|
95
|
+
<SpinnerSvg aria-label='Loading visitors' />
|
|
96
|
+
</ThemeContextProvider>
|
|
97
|
+
);
|
|
98
|
+
expect(screen.getByRole('progressbar')).toHaveAccessibleName(
|
|
99
|
+
'Loading visitors'
|
|
100
|
+
);
|
|
101
|
+
expect(screen.getByRole('progressbar')).not.toHaveAccessibleName('Loading');
|
|
102
|
+
});
|
|
71
103
|
});
|
|
@@ -2,17 +2,19 @@
|
|
|
2
2
|
|
|
3
3
|
exports[`SpinnerSvg > Snapshot: custom className 1`] = `
|
|
4
4
|
<svg
|
|
5
|
-
|
|
5
|
+
aria-label="Loading"
|
|
6
|
+
class="ucl-uikit-spinner css-rppy7j"
|
|
6
7
|
data-testid="ucl-uikit-spinner"
|
|
7
8
|
height="72"
|
|
9
|
+
role="progressbar"
|
|
8
10
|
viewBox="0 0 50 50"
|
|
9
11
|
width="72"
|
|
10
12
|
>
|
|
11
13
|
<g
|
|
12
|
-
class="css-
|
|
14
|
+
class="css-swia5b"
|
|
13
15
|
>
|
|
14
16
|
<circle
|
|
15
|
-
class="css-
|
|
17
|
+
class="css-1iyl2x2"
|
|
16
18
|
cx="25"
|
|
17
19
|
cy="25"
|
|
18
20
|
fill="none"
|
|
@@ -26,17 +28,19 @@ exports[`SpinnerSvg > Snapshot: custom className 1`] = `
|
|
|
26
28
|
|
|
27
29
|
exports[`SpinnerSvg > snapshot: custom size 1`] = `
|
|
28
30
|
<svg
|
|
29
|
-
|
|
31
|
+
aria-label="Loading"
|
|
32
|
+
class="ucl-uikit-spinner css-1scd17h"
|
|
30
33
|
data-testid="ucl-uikit-spinner"
|
|
31
34
|
height="32"
|
|
35
|
+
role="progressbar"
|
|
32
36
|
viewBox="0 0 50 50"
|
|
33
37
|
width="32"
|
|
34
38
|
>
|
|
35
39
|
<g
|
|
36
|
-
class="css-
|
|
40
|
+
class="css-swia5b"
|
|
37
41
|
>
|
|
38
42
|
<circle
|
|
39
|
-
class="css-
|
|
43
|
+
class="css-1iyl2x2"
|
|
40
44
|
cx="25"
|
|
41
45
|
cy="25"
|
|
42
46
|
fill="none"
|
|
@@ -50,17 +54,19 @@ exports[`SpinnerSvg > snapshot: custom size 1`] = `
|
|
|
50
54
|
|
|
51
55
|
exports[`SpinnerSvg > snapshot: default props 1`] = `
|
|
52
56
|
<svg
|
|
53
|
-
|
|
57
|
+
aria-label="Loading"
|
|
58
|
+
class="ucl-uikit-spinner css-1scd17h"
|
|
54
59
|
data-testid="ucl-uikit-spinner"
|
|
55
60
|
height="72"
|
|
61
|
+
role="progressbar"
|
|
56
62
|
viewBox="0 0 50 50"
|
|
57
63
|
width="72"
|
|
58
64
|
>
|
|
59
65
|
<g
|
|
60
|
-
class="css-
|
|
66
|
+
class="css-swia5b"
|
|
61
67
|
>
|
|
62
68
|
<circle
|
|
63
|
-
class="css-
|
|
69
|
+
class="css-1iyl2x2"
|
|
64
70
|
cx="25"
|
|
65
71
|
cy="25"
|
|
66
72
|
fill="none"
|
|
@@ -74,17 +80,19 @@ exports[`SpinnerSvg > snapshot: default props 1`] = `
|
|
|
74
80
|
|
|
75
81
|
exports[`SpinnerSvg > snapshot: inherits parent colour when inheritColour is true 1`] = `
|
|
76
82
|
<svg
|
|
77
|
-
|
|
83
|
+
aria-label="Loading"
|
|
84
|
+
class="ucl-uikit-spinner css-15f359x"
|
|
78
85
|
data-testid="ucl-uikit-spinner"
|
|
79
86
|
height="72"
|
|
87
|
+
role="progressbar"
|
|
80
88
|
viewBox="0 0 50 50"
|
|
81
89
|
width="72"
|
|
82
90
|
>
|
|
83
91
|
<g
|
|
84
|
-
class="css-
|
|
92
|
+
class="css-swia5b"
|
|
85
93
|
>
|
|
86
94
|
<circle
|
|
87
|
-
class="css-
|
|
95
|
+
class="css-1iyl2x2"
|
|
88
96
|
cx="25"
|
|
89
97
|
cy="25"
|
|
90
98
|
fill="none"
|
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
|
|
3
3
|
exports[`Link > snapshot: no props 1`] = `
|
|
4
4
|
<a
|
|
5
|
-
class="ucl-uikit-base-link ucl-uikit-standalone-link css-
|
|
5
|
+
class="ucl-uikit-base-link ucl-uikit-standalone-link css-zj0pf"
|
|
6
6
|
data-testid="ucl-uikit-standalone-link"
|
|
7
7
|
>
|
|
8
8
|
test
|
|
@@ -11,7 +11,7 @@ exports[`Link > snapshot: no props 1`] = `
|
|
|
11
11
|
|
|
12
12
|
exports[`Link > snapshot: testId prop 1`] = `
|
|
13
13
|
<a
|
|
14
|
-
class="ucl-uikit-base-link ucl-uikit-standalone-link css-
|
|
14
|
+
class="ucl-uikit-base-link ucl-uikit-standalone-link css-zj0pf"
|
|
15
15
|
data-testid="test123"
|
|
16
16
|
>
|
|
17
17
|
testidlink
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
# Table – Improvements Tracking
|
|
2
|
+
|
|
3
|
+
## Decision: Table.Cell should not support a `variant='button'` prop
|
|
4
|
+
|
|
5
|
+
**Status:** Decided
|
|
6
|
+
**Date:** 2026-04-13
|
|
7
|
+
**Context:** EVE frontend – My Visitors screen (`MyVisitorsScreen.tsx`)
|
|
8
|
+
|
|
9
|
+
### Problem
|
|
10
|
+
|
|
11
|
+
We considered two approaches for adding interactive actions (e.g. "Invite again") inside table cells:
|
|
12
|
+
|
|
13
|
+
- **A) `variant='button'` on `Table.Cell`** – The cell itself renders as a button, with props like `buttonProps`, `loading`, and `onClick` forwarded through the cell.
|
|
14
|
+
- **B) `<Button>` as a child of `Table.Cell`** – The cell remains a plain container; a `<Button>` component is composed inside it.
|
|
15
|
+
|
|
16
|
+
### Decision
|
|
17
|
+
|
|
18
|
+
**Go with B – compose `<Button>` as a child.**
|
|
19
|
+
|
|
20
|
+
### Rationale
|
|
21
|
+
|
|
22
|
+
- **Composition over configuration.** Adding `variant='button'` conflates layout (cell) and interaction (button) concerns, increasing the API surface of `Table.Cell` with forwarded props (`loading`, `onClick`, `disabled`, `size`, button variant, etc.).
|
|
23
|
+
- **Flexibility.** A child `<Button>` can easily be swapped for an icon button, a link, a menu, or multiple actions — without the cell API needing to accommodate every combination.
|
|
24
|
+
- **No duplicated logic.** `<Button>` already handles loading spinners, disabled states, and accessibility. A `variant='button'` cell would need to re-implement or proxy all of that.
|
|
25
|
+
- **Simpler Table.Cell API.** Fewer props to document, test, and maintain.
|
package/lib/components/index.ts
CHANGED
|
@@ -31,6 +31,9 @@ export type { SnackbarProps } from './Snackbar';
|
|
|
31
31
|
export { default as Avatar } from './Avatar';
|
|
32
32
|
export type { AvatarProps } from './Avatar';
|
|
33
33
|
|
|
34
|
+
export { default as Badge } from './Badge';
|
|
35
|
+
export type { BadgeProps } from './Badge';
|
|
36
|
+
|
|
34
37
|
export { default as Spinner } from './Spinner';
|
|
35
38
|
export type { SpinnerProps } from './Spinner';
|
|
36
39
|
|
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.
|
|
5
|
+
"version": "0.22.1",
|
|
6
6
|
"type": "module",
|
|
7
7
|
"main": "dist/index.js",
|
|
8
8
|
"types": "dist/index.d.ts",
|
|
@@ -17,6 +17,7 @@
|
|
|
17
17
|
"dev": "vite",
|
|
18
18
|
"dev_expose": "vite --host",
|
|
19
19
|
"build": "tsc --p ./tsconfig-build.json && vite build",
|
|
20
|
+
"build:watch": "tsc --p ./tsconfig-build.json --watch --preserveWatchOutput & vite build --watch",
|
|
20
21
|
"lint": "eslint . --ext ts,tsx --report-unused-disable-directives --max-warnings 0",
|
|
21
22
|
"pre-commit": "lint-staged",
|
|
22
23
|
"format": "prettier \"./**/*.{ts,tsx}\" --write --config ./prettierrc",
|