uikit-react-public 0.21.8 → 0.22.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.
- package/dist/components/Heading/Heading.d.ts +6 -4
- package/dist/components/Heading/Heading.stories.d.ts +8 -6
- package/dist/components/Paragraph/Paragraph.d.ts +5 -2
- package/dist/components/Paragraph/Paragraph.stories.d.ts +6 -3
- 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 +6 -4
- package/dist/index.js +3712 -3783
- package/lib/components/Button/__tests__/__snapshots__/Button.test.tsx.snap +5 -3
- package/lib/components/Field/Field.tsx +0 -3
- package/lib/components/Heading/Heading.stories.tsx +34 -41
- package/lib/components/Heading/Heading.tsx +180 -49
- package/lib/components/Heading/__tests__/__snapshots__/Heading.test.tsx.snap +4 -4
- package/lib/components/Paragraph/Paragraph.stories.tsx +29 -27
- package/lib/components/Paragraph/Paragraph.tsx +212 -81
- package/lib/components/Paragraph/__tests__/__snapshots__/Paragraph.test.tsx.snap +5 -5
- 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/Table/improvements-tracking.md +25 -0
- package/lib/components/index.ts +7 -4
- package/package.json +2 -1
- package/dist/components/HeadingNew/Heading.d.ts +0 -13
- package/dist/components/HeadingNew/index.d.ts +0 -2
- package/dist/components/ParagraphNew/Paragraph.d.ts +0 -13
- package/dist/components/ParagraphNew/index.d.ts +0 -4
- package/lib/components/HeadingNew/Heading.tsx +0 -208
- package/lib/components/HeadingNew/index.ts +0 -2
- package/lib/components/ParagraphNew/Paragraph.tsx +0 -200
- package/lib/components/ParagraphNew/index.ts +0 -6
|
@@ -1,95 +1,226 @@
|
|
|
1
|
-
import { memo, HTMLAttributes,
|
|
1
|
+
import { memo, HTMLAttributes, JSX } from 'react';
|
|
2
2
|
import { css, cx } from '@emotion/css';
|
|
3
3
|
import useTheme from '../../theme/useTheme';
|
|
4
4
|
import marginsStyle, { MarginProps } from '../common/marginsStyle';
|
|
5
5
|
|
|
6
6
|
export const NAME = 'ucl-uikit-paragrah';
|
|
7
7
|
|
|
8
|
-
export
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
8
|
+
export type ParagraphLevel =
|
|
9
|
+
| 'lg'
|
|
10
|
+
| 'lg-medium'
|
|
11
|
+
| 'lg-semibold'
|
|
12
|
+
| 'lg-bold'
|
|
13
|
+
| 'md'
|
|
14
|
+
| 'md-medium'
|
|
15
|
+
| 'md-semibold'
|
|
16
|
+
| 'md-semibold'
|
|
17
|
+
| 'md-medium-numeric'
|
|
18
|
+
| 'sm'
|
|
19
|
+
| 'sm-medium'
|
|
20
|
+
| 'sm-semibold'
|
|
21
|
+
| 'xs'
|
|
22
|
+
| 'xs-medium';
|
|
23
|
+
|
|
24
|
+
export interface ParagraphBaseProps extends HTMLAttributes<HTMLParagraphElement> {
|
|
25
|
+
level?: ParagraphLevel;
|
|
26
|
+
size?: 'standfirst' | 'body' | 'small'; // deprecated
|
|
27
|
+
emphasis?: 'high' | 'medium'; // deprecated
|
|
28
|
+
as?: 'p' | 'div' | 'span';
|
|
29
|
+
margins?: boolean; // deprecated
|
|
13
30
|
testId?: string;
|
|
31
|
+
ref?: React.Ref<HTMLParagraphElement>;
|
|
14
32
|
}
|
|
15
33
|
|
|
16
34
|
export type ParagraphProps = ParagraphBaseProps & MarginProps;
|
|
17
35
|
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
36
|
+
const Paragraph = ({
|
|
37
|
+
level = 'md',
|
|
38
|
+
size = 'body',
|
|
39
|
+
emphasis = 'high',
|
|
40
|
+
as = 'p',
|
|
41
|
+
margins = true,
|
|
42
|
+
testId = NAME,
|
|
43
|
+
className,
|
|
44
|
+
ref,
|
|
45
|
+
noMargins,
|
|
46
|
+
...props
|
|
47
|
+
}: ParagraphProps) => {
|
|
48
|
+
const [theme] = useTheme();
|
|
49
|
+
|
|
50
|
+
const {
|
|
51
|
+
typography: {
|
|
52
|
+
body: {
|
|
53
|
+
lg,
|
|
54
|
+
lgMedium,
|
|
55
|
+
lgSemibold,
|
|
56
|
+
lgBold,
|
|
57
|
+
md,
|
|
58
|
+
mdMedium,
|
|
59
|
+
mdSemibold,
|
|
60
|
+
mdMediumNumeric,
|
|
61
|
+
sm,
|
|
62
|
+
smMedium,
|
|
63
|
+
smSemibold,
|
|
64
|
+
xs,
|
|
65
|
+
xsMedium,
|
|
66
|
+
},
|
|
29
67
|
},
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
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
|
-
|
|
93
|
-
|
|
68
|
+
} = theme;
|
|
69
|
+
|
|
70
|
+
const mappedLevel: ParagraphLevel =
|
|
71
|
+
level ||
|
|
72
|
+
(size === 'standfirst'
|
|
73
|
+
? emphasis === 'medium'
|
|
74
|
+
? 'lg-medium'
|
|
75
|
+
: 'lg'
|
|
76
|
+
: size === 'small'
|
|
77
|
+
? emphasis === 'medium'
|
|
78
|
+
? 'sm-medium'
|
|
79
|
+
: 'sm'
|
|
80
|
+
: emphasis === 'medium'
|
|
81
|
+
? 'md-medium'
|
|
82
|
+
: 'md');
|
|
83
|
+
|
|
84
|
+
const baseStyle = css`
|
|
85
|
+
font-family: ${md.fontFamily};
|
|
86
|
+
font-feature-settings: ${md.fontSettings};
|
|
87
|
+
color: ${emphasis === 'medium'
|
|
88
|
+
? theme.colour.text.secondary
|
|
89
|
+
: theme.colour.text.default};
|
|
90
|
+
margin: 0;
|
|
91
|
+
`;
|
|
92
|
+
|
|
93
|
+
const lgStyle = css`
|
|
94
|
+
font-size: ${lg.fontSize}px;
|
|
95
|
+
font-weight: ${lg.fontWeight};
|
|
96
|
+
line-height: ${lg.lineHeight}%;
|
|
97
|
+
`;
|
|
98
|
+
|
|
99
|
+
const lgMediumStyle = css`
|
|
100
|
+
font-size: ${lgMedium.fontSize}px;
|
|
101
|
+
font-weight: ${lgMedium.fontWeight};
|
|
102
|
+
line-height: ${lgMedium.lineHeight}%;
|
|
103
|
+
`;
|
|
104
|
+
|
|
105
|
+
const lgSemiboldStyle = css`
|
|
106
|
+
font-size: ${lgSemibold.fontSize}px;
|
|
107
|
+
font-weight: ${lgSemibold.fontWeight};
|
|
108
|
+
line-height: ${lgSemibold.lineHeight}%;
|
|
109
|
+
`;
|
|
110
|
+
|
|
111
|
+
const lgBoldStyle = css`
|
|
112
|
+
font-size: ${lgBold.fontSize}px;
|
|
113
|
+
font-weight: ${lgBold.fontWeight};
|
|
114
|
+
line-height: ${lgBold.lineHeight}%;
|
|
115
|
+
`;
|
|
116
|
+
|
|
117
|
+
const mdStyle = css`
|
|
118
|
+
font-size: ${md.fontSize}px;
|
|
119
|
+
font-weight: ${md.fontWeight};
|
|
120
|
+
line-height: ${md.lineHeight}%;
|
|
121
|
+
`;
|
|
122
|
+
|
|
123
|
+
const mdMediumStyle = css`
|
|
124
|
+
font-size: ${mdMedium.fontSize}px;
|
|
125
|
+
font-weight: ${mdMedium.fontWeight};
|
|
126
|
+
line-height: ${mdMedium.lineHeight}%;
|
|
127
|
+
`;
|
|
128
|
+
|
|
129
|
+
const mdSemiboldStyle = css`
|
|
130
|
+
font-size: ${mdSemibold.fontSize}px;
|
|
131
|
+
font-weight: ${mdSemibold.fontWeight};
|
|
132
|
+
line-height: ${mdSemibold.lineHeight}%;
|
|
133
|
+
`;
|
|
134
|
+
|
|
135
|
+
const mdMediumNumericStyle = css`
|
|
136
|
+
font-size: ${mdMediumNumeric.fontSize}px;
|
|
137
|
+
font-weight: ${mdMediumNumeric.fontWeight};
|
|
138
|
+
line-height: ${mdMediumNumeric.lineHeight}%;
|
|
139
|
+
`;
|
|
140
|
+
|
|
141
|
+
const smStyle = css`
|
|
142
|
+
font-size: ${sm.fontSize}px;
|
|
143
|
+
font-weight: ${sm.fontWeight};
|
|
144
|
+
line-height: ${sm.lineHeight}%;
|
|
145
|
+
`;
|
|
146
|
+
|
|
147
|
+
const smMediumStyle = css`
|
|
148
|
+
font-size: ${smMedium.fontSize}px;
|
|
149
|
+
font-weight: ${smMedium.fontWeight};
|
|
150
|
+
line-height: ${smMedium.lineHeight}%;
|
|
151
|
+
`;
|
|
152
|
+
|
|
153
|
+
const smSemiboldStyle = css`
|
|
154
|
+
font-size: ${smSemibold.fontSize}px;
|
|
155
|
+
font-weight: ${smSemibold.fontWeight};
|
|
156
|
+
line-height: ${smSemibold.lineHeight}%;
|
|
157
|
+
`;
|
|
158
|
+
|
|
159
|
+
const xsStyle = css`
|
|
160
|
+
font-size: ${xs.fontSize}px;
|
|
161
|
+
font-weight: ${xs.fontWeight};
|
|
162
|
+
line-height: ${xs.lineHeight}%;
|
|
163
|
+
`;
|
|
164
|
+
|
|
165
|
+
const xsMediumStyle = css`
|
|
166
|
+
font-size: ${xsMedium.fontSize}px;
|
|
167
|
+
font-weight: ${xsMedium.fontWeight};
|
|
168
|
+
line-height: ${xsMedium.lineHeight}%;
|
|
169
|
+
`;
|
|
170
|
+
|
|
171
|
+
const style = cx(
|
|
172
|
+
NAME,
|
|
173
|
+
baseStyle,
|
|
174
|
+
mappedLevel === 'lg' && lgStyle,
|
|
175
|
+
mappedLevel === 'lg-medium' && lgMediumStyle,
|
|
176
|
+
mappedLevel === 'lg-semibold' && lgSemiboldStyle,
|
|
177
|
+
mappedLevel === 'lg-bold' && lgBoldStyle,
|
|
178
|
+
mappedLevel === 'md' && mdStyle,
|
|
179
|
+
mappedLevel === 'md-medium' && mdMediumStyle,
|
|
180
|
+
mappedLevel === 'md-semibold' && mdSemiboldStyle,
|
|
181
|
+
mappedLevel === 'md-medium-numeric' && mdMediumNumericStyle,
|
|
182
|
+
mappedLevel === 'sm' && smStyle,
|
|
183
|
+
mappedLevel === 'sm-medium' && smMediumStyle,
|
|
184
|
+
mappedLevel === 'sm-semibold' && smSemiboldStyle,
|
|
185
|
+
mappedLevel === 'xs' && xsStyle,
|
|
186
|
+
mappedLevel === 'xs-medium' && xsMediumStyle,
|
|
187
|
+
marginsStyle(
|
|
188
|
+
{ ...props, noMargins: noMargins || margins === false },
|
|
189
|
+
theme
|
|
190
|
+
),
|
|
191
|
+
className
|
|
192
|
+
);
|
|
193
|
+
|
|
194
|
+
const paragraphTag = as as keyof JSX.IntrinsicElements;
|
|
195
|
+
|
|
196
|
+
return (
|
|
197
|
+
<>
|
|
198
|
+
{paragraphTag === 'p' && (
|
|
199
|
+
<p
|
|
200
|
+
ref={ref}
|
|
201
|
+
className={style}
|
|
202
|
+
data-testid={testId}
|
|
203
|
+
{...props}
|
|
204
|
+
/>
|
|
205
|
+
)}
|
|
206
|
+
{paragraphTag === 'div' && (
|
|
207
|
+
<div
|
|
208
|
+
ref={ref as React.Ref<HTMLDivElement>}
|
|
209
|
+
className={style}
|
|
210
|
+
data-testid={testId}
|
|
211
|
+
{...props}
|
|
212
|
+
/>
|
|
213
|
+
)}
|
|
214
|
+
{paragraphTag === 'span' && (
|
|
215
|
+
<span
|
|
216
|
+
ref={ref as React.Ref<HTMLSpanElement>}
|
|
217
|
+
className={style}
|
|
218
|
+
data-testid={testId}
|
|
219
|
+
{...props}
|
|
220
|
+
/>
|
|
221
|
+
)}
|
|
222
|
+
</>
|
|
223
|
+
);
|
|
224
|
+
};
|
|
94
225
|
|
|
95
226
|
export default memo(Paragraph);
|
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
|
|
3
3
|
exports[`Paragraph > snapshot: custom test id 1`] = `
|
|
4
4
|
<p
|
|
5
|
-
class="ucl-uikit-paragrah css-
|
|
5
|
+
class="ucl-uikit-paragrah css-h12wmf"
|
|
6
6
|
data-testid="custom-test-id"
|
|
7
7
|
>
|
|
8
8
|
This is a test
|
|
@@ -11,7 +11,7 @@ exports[`Paragraph > snapshot: custom test id 1`] = `
|
|
|
11
11
|
|
|
12
12
|
exports[`Paragraph > snapshot: emphasis 1`] = `
|
|
13
13
|
<p
|
|
14
|
-
class="ucl-uikit-paragrah css-
|
|
14
|
+
class="ucl-uikit-paragrah css-h12wmf"
|
|
15
15
|
data-testid="ucl-uikit-paragrah"
|
|
16
16
|
>
|
|
17
17
|
high emphasis
|
|
@@ -20,7 +20,7 @@ exports[`Paragraph > snapshot: emphasis 1`] = `
|
|
|
20
20
|
|
|
21
21
|
exports[`Paragraph > snapshot: minimal props 1`] = `
|
|
22
22
|
<p
|
|
23
|
-
class="ucl-uikit-paragrah css-
|
|
23
|
+
class="ucl-uikit-paragrah css-h12wmf"
|
|
24
24
|
data-testid="ucl-uikit-paragrah"
|
|
25
25
|
>
|
|
26
26
|
This is a test
|
|
@@ -29,7 +29,7 @@ exports[`Paragraph > snapshot: minimal props 1`] = `
|
|
|
29
29
|
|
|
30
30
|
exports[`Paragraph > snapshot: no margins 1`] = `
|
|
31
31
|
<p
|
|
32
|
-
class="ucl-uikit-paragrah css-
|
|
32
|
+
class="ucl-uikit-paragrah css-1dosm7d"
|
|
33
33
|
data-testid="ucl-uikit-paragrah"
|
|
34
34
|
>
|
|
35
35
|
no margins
|
|
@@ -38,7 +38,7 @@ exports[`Paragraph > snapshot: no margins 1`] = `
|
|
|
38
38
|
|
|
39
39
|
exports[`Paragraph > snapshot: size 1`] = `
|
|
40
40
|
<p
|
|
41
|
-
class="ucl-uikit-paragrah css-
|
|
41
|
+
class="ucl-uikit-paragrah css-h12wmf"
|
|
42
42
|
data-testid="ucl-uikit-paragrah"
|
|
43
43
|
>
|
|
44
44
|
standfirst
|
|
@@ -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"
|
|
@@ -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.
|