@pega/cosmos-react-work 9.10.1 → 9.12.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/lib/components/CaseView/CaseView.styles.d.ts.map +1 -1
- package/lib/components/CaseView/CaseView.styles.js +7 -3
- package/lib/components/CaseView/CaseView.styles.js.map +1 -1
- package/lib/components/Shortcuts/Shortcuts.d.ts.map +1 -1
- package/lib/components/Shortcuts/Shortcuts.js +13 -6
- package/lib/components/Shortcuts/Shortcuts.js.map +1 -1
- package/lib/components/Shortcuts/Shortcuts.styles.d.ts +13 -2
- package/lib/components/Shortcuts/Shortcuts.styles.d.ts.map +1 -1
- package/lib/components/Shortcuts/Shortcuts.styles.js +71 -29
- package/lib/components/Shortcuts/Shortcuts.styles.js.map +1 -1
- package/lib/components/Shortcuts/Shortcuts.types.d.ts +4 -0
- package/lib/components/Shortcuts/Shortcuts.types.d.ts.map +1 -1
- package/lib/components/Shortcuts/Shortcuts.types.js.map +1 -1
- package/lib/components/Stages/Stages.d.ts +4 -2
- package/lib/components/Stages/Stages.d.ts.map +1 -1
- package/lib/components/Stages/Stages.js +100 -88
- package/lib/components/Stages/Stages.js.map +1 -1
- package/lib/components/Stages/Stages.styles.d.ts +57 -0
- package/lib/components/Stages/Stages.styles.d.ts.map +1 -1
- package/lib/components/Stages/Stages.styles.js +326 -53
- package/lib/components/Stages/Stages.styles.js.map +1 -1
- package/lib/components/Stages/Stages.test-ids.d.ts +2 -0
- package/lib/components/Stages/Stages.test-ids.d.ts.map +1 -0
- package/lib/components/Stages/Stages.test-ids.js +3 -0
- package/lib/components/Stages/Stages.test-ids.js.map +1 -0
- package/lib/components/Stages/Stages.types.d.ts +3 -3
- package/lib/components/Stages/Stages.types.d.ts.map +1 -1
- package/lib/components/Stages/Stages.types.js.map +1 -1
- package/lib/components/Stages/index.d.ts +1 -0
- package/lib/components/Stages/index.d.ts.map +1 -1
- package/lib/components/Stages/index.js +1 -0
- package/lib/components/Stages/index.js.map +1 -1
- package/lib/components/Tasks/TaskList.d.ts.map +1 -1
- package/lib/components/Tasks/TaskList.js +24 -16
- package/lib/components/Tasks/TaskList.js.map +1 -1
- package/lib/components/Tasks/Tasks.d.ts +5 -0
- package/lib/components/Tasks/Tasks.d.ts.map +1 -1
- package/lib/components/Tasks/Tasks.js +7 -5
- package/lib/components/Tasks/Tasks.js.map +1 -1
- package/package.json +3 -3
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import styled, { css } from 'styled-components';
|
|
2
|
+
import { transparentize } from 'polished';
|
|
2
3
|
import { calculateFontSize, DateTimeDisplay, defaultThemeProp, Icon, Text, StyledIcon, calculateForegroundColor } from '@pega/cosmos-react-core';
|
|
3
4
|
const stageClipPath = (leftNotch, rightPoint, mirrored = false) => {
|
|
4
5
|
if (mirrored) {
|
|
@@ -32,14 +33,25 @@ const stageClipPath = (leftNotch, rightPoint, mirrored = false) => {
|
|
|
32
33
|
// === Chevron Configuration ===
|
|
33
34
|
// Centralizes spacing and border thickness via CSS custom properties set at StyledStages
|
|
34
35
|
const chevronConfig = {
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
36
|
+
// Horizontal projection of the rotated border-square forming the chevron point (fine pointer).
|
|
37
|
+
// Derived from the border-square size × cos(45° + skew). Tuned to visually align with the stage height.
|
|
38
|
+
// All values scaled by 1.25× relative to the original 4× spacing design (now 5× spacing height).
|
|
39
|
+
width: 'calc(1.445 * var(--chevron-spacing))',
|
|
40
|
+
// Same horizontal projection for coarse/touch pointer (larger square, proportionally wider point).
|
|
41
|
+
coarseWidth: 'calc(1.797 * var(--chevron-spacing))',
|
|
42
|
+
// Side length of the rotated border-square forming the chevron (fine pointer: 3.75× base spacing).
|
|
43
|
+
squareSize: 'calc(3.75 * var(--chevron-spacing))',
|
|
44
|
+
// Side length of the rotated border-square for coarse/touch pointer (5× base spacing).
|
|
45
|
+
coarseSquareSize: 'calc(5 * var(--chevron-spacing))',
|
|
46
|
+
// Distance to inset the ::before notch from the left edge of the stage (fine pointer).
|
|
47
|
+
// 0.86 ≈ width − half-border-overlap, keeps the notch flush with the preceding chevron point.
|
|
48
|
+
offsetLeft: 'calc(0.86 * var(--chevron-spacing))',
|
|
49
|
+
// Distance to inset the ::after point from the right edge of the stage (fine pointer).
|
|
50
|
+
// Equal to `width` so the point extends exactly one chevron-width beyond the stage boundary.
|
|
51
|
+
offsetRight: 'calc(1.445 * var(--chevron-spacing))',
|
|
52
|
+
// Coarse-pointer equivalents of offsetLeft/offsetRight, scaled to match coarseWidth/coarseSquareSize.
|
|
53
|
+
coarseOffsetLeft: 'calc(1.2875 * var(--chevron-spacing))',
|
|
54
|
+
coarseOffsetRight: 'calc(1.797 * var(--chevron-spacing))'
|
|
43
55
|
};
|
|
44
56
|
// === Chevron Helpers ===
|
|
45
57
|
// After team discussion we decided to use logical properties throughout — `inset-block-start`
|
|
@@ -62,17 +74,17 @@ const createChevronPseudo = (borderWidth, borderColor, size) => `
|
|
|
62
74
|
pointer-events: none;
|
|
63
75
|
`;
|
|
64
76
|
const createChevronBaseStyles = (config, borderThicknessVar) => css `
|
|
65
|
-
&:not(:
|
|
66
|
-
&:not(:last-of-type)::after {
|
|
77
|
+
&:not(:nth-of-type(-n + 2))::before,
|
|
78
|
+
&:not(:nth-last-of-type(-n + 2))::after {
|
|
67
79
|
border-inline-end-width: calc(1.5 * ${borderThicknessVar});
|
|
68
80
|
border-block-start-width: calc(1.5 * ${borderThicknessVar});
|
|
69
81
|
}
|
|
70
82
|
|
|
71
|
-
&:not(:
|
|
83
|
+
&:not(:nth-of-type(-n + 2))::before {
|
|
72
84
|
inset-inline-start: calc(-1 * ${config.width} - ${config.offsetLeft});
|
|
73
85
|
}
|
|
74
86
|
|
|
75
|
-
&:not(:last-of-type)::after {
|
|
87
|
+
&:not(:nth-last-of-type(-n + 2))::after {
|
|
76
88
|
inset-inline-end: calc(-1 * ${config.width} + ${config.offsetRight});
|
|
77
89
|
}
|
|
78
90
|
`;
|
|
@@ -93,30 +105,224 @@ const createChevronInteractiveStates = (config, borderThicknessVar, includeHover
|
|
|
93
105
|
border-block-start-width: calc(2 * ${borderThicknessVar});
|
|
94
106
|
}
|
|
95
107
|
`;
|
|
108
|
+
/**
|
|
109
|
+
* Outer wrapper `<div>` for the stages bar. Applies layered scroll-fade masks and
|
|
110
|
+
* reserves scrollbar space so the fade gradient does not overlap the scrollbar track.
|
|
111
|
+
*/
|
|
112
|
+
export const StyledStagesWrapper = styled.div(({ theme }) => {
|
|
113
|
+
return css `
|
|
114
|
+
--stages-fade-width: calc(${theme.base.spacing} * 2);
|
|
115
|
+
--stages-fade-start: 0;
|
|
116
|
+
--stages-fade-end: 0;
|
|
117
|
+
--stages-scrollbar-reserve: calc(${theme.base.spacing} * 0.25);
|
|
118
|
+
|
|
119
|
+
/* Places gradient stops one physical pixel outside the element boundary,
|
|
120
|
+
* preventing browser anti-aliasing from creating a semi-transparent seam
|
|
121
|
+
* at mask edges. 1px is the correct unit here: it must be exactly one CSS pixel
|
|
122
|
+
* (independent of font-size), so the mask boundary doesn't introduce a seam at the
|
|
123
|
+
* element edge due to anti-aliasing.
|
|
124
|
+
* See also StyledSentinel, which uses 1px for the same reason.
|
|
125
|
+
*/
|
|
126
|
+
/* stylelint-disable-next-line unit-allowed-list -- 1px is intentional; see comment above */
|
|
127
|
+
--mask-edge-overhang: 1px;
|
|
128
|
+
position: relative;
|
|
129
|
+
width: 100%;
|
|
130
|
+
overflow: hidden;
|
|
131
|
+
border-radius: ${theme.components.card['border-radius']};
|
|
132
|
+
border-end-start-radius: var(
|
|
133
|
+
--stages-wrapper-bottom-radius,
|
|
134
|
+
${theme.components.card['border-radius']}
|
|
135
|
+
);
|
|
136
|
+
border-end-end-radius: var(
|
|
137
|
+
--stages-wrapper-bottom-radius,
|
|
138
|
+
${theme.components.card['border-radius']}
|
|
139
|
+
);
|
|
140
|
+
-webkit-mask-image: linear-gradient(black, black),
|
|
141
|
+
linear-gradient(
|
|
142
|
+
to right,
|
|
143
|
+
transparent calc(-1 * var(--mask-edge-overhang)),
|
|
144
|
+
black var(--stages-fade-start),
|
|
145
|
+
black calc(100% - var(--stages-fade-end)),
|
|
146
|
+
transparent calc(100% + var(--mask-edge-overhang))
|
|
147
|
+
);
|
|
148
|
+
mask-image: linear-gradient(black, black),
|
|
149
|
+
linear-gradient(
|
|
150
|
+
to right,
|
|
151
|
+
transparent calc(-1 * var(--mask-edge-overhang)),
|
|
152
|
+
black var(--stages-fade-start),
|
|
153
|
+
black calc(100% - var(--stages-fade-end)),
|
|
154
|
+
transparent calc(100% + var(--mask-edge-overhang))
|
|
155
|
+
);
|
|
156
|
+
mask-size:
|
|
157
|
+
100% var(--stages-scrollbar-reserve),
|
|
158
|
+
100% calc(100% - var(--stages-scrollbar-reserve));
|
|
159
|
+
mask-position:
|
|
160
|
+
0 100%,
|
|
161
|
+
0 0;
|
|
162
|
+
mask-repeat: no-repeat, no-repeat;
|
|
163
|
+
|
|
164
|
+
[dir='rtl'] & {
|
|
165
|
+
-webkit-mask-image: linear-gradient(black, black),
|
|
166
|
+
linear-gradient(
|
|
167
|
+
to right,
|
|
168
|
+
transparent calc(-1 * var(--mask-edge-overhang)),
|
|
169
|
+
black var(--stages-fade-end),
|
|
170
|
+
black calc(100% - var(--stages-fade-start)),
|
|
171
|
+
transparent calc(100% + var(--mask-edge-overhang))
|
|
172
|
+
);
|
|
173
|
+
mask-image: linear-gradient(black, black),
|
|
174
|
+
linear-gradient(
|
|
175
|
+
to right,
|
|
176
|
+
transparent calc(-1 * var(--mask-edge-overhang)),
|
|
177
|
+
black var(--stages-fade-end),
|
|
178
|
+
black calc(100% - var(--stages-fade-start)),
|
|
179
|
+
transparent calc(100% + var(--mask-edge-overhang))
|
|
180
|
+
);
|
|
181
|
+
}
|
|
182
|
+
|
|
183
|
+
&:has(:focus-visible) {
|
|
184
|
+
box-shadow: ${theme.base.shadow['focus-group']};
|
|
185
|
+
}
|
|
186
|
+
|
|
187
|
+
@media (pointer: coarse) {
|
|
188
|
+
--stages-fade-width: calc(${theme.base.spacing} * 3);
|
|
189
|
+
-webkit-mask-image: linear-gradient(
|
|
190
|
+
to right,
|
|
191
|
+
transparent calc(-1 * var(--mask-edge-overhang)),
|
|
192
|
+
black var(--stages-fade-start),
|
|
193
|
+
black calc(100% - var(--stages-fade-end)),
|
|
194
|
+
transparent calc(100% + var(--mask-edge-overhang))
|
|
195
|
+
);
|
|
196
|
+
mask-image: linear-gradient(
|
|
197
|
+
to right,
|
|
198
|
+
transparent calc(-1 * var(--mask-edge-overhang)),
|
|
199
|
+
black var(--stages-fade-start),
|
|
200
|
+
black calc(100% - var(--stages-fade-end)),
|
|
201
|
+
transparent calc(100% + var(--mask-edge-overhang))
|
|
202
|
+
);
|
|
203
|
+
mask-size: 100% 100%;
|
|
204
|
+
mask-position: 0 0;
|
|
205
|
+
mask-repeat: no-repeat;
|
|
206
|
+
|
|
207
|
+
[dir='rtl'] & {
|
|
208
|
+
-webkit-mask-image: linear-gradient(
|
|
209
|
+
to right,
|
|
210
|
+
transparent calc(-1 * var(--mask-edge-overhang)),
|
|
211
|
+
black var(--stages-fade-end),
|
|
212
|
+
black calc(100% - var(--stages-fade-start)),
|
|
213
|
+
transparent calc(100% + var(--mask-edge-overhang))
|
|
214
|
+
);
|
|
215
|
+
mask-image: linear-gradient(
|
|
216
|
+
to right,
|
|
217
|
+
transparent calc(-1 * var(--mask-edge-overhang)),
|
|
218
|
+
black var(--stages-fade-end),
|
|
219
|
+
black calc(100% - var(--stages-fade-start)),
|
|
220
|
+
transparent calc(100% + var(--mask-edge-overhang))
|
|
221
|
+
);
|
|
222
|
+
}
|
|
223
|
+
}
|
|
224
|
+
`;
|
|
225
|
+
});
|
|
226
|
+
StyledStagesWrapper.defaultProps = defaultThemeProp;
|
|
227
|
+
/**
|
|
228
|
+
* Scrollable `<ol>` containing all stage chevron items. Sets the `--chevron-spacing`
|
|
229
|
+
* and `--chevron-border-thickness` custom properties consumed by child elements.
|
|
230
|
+
*/
|
|
96
231
|
export const StyledStages = styled.ol(({ theme }) => {
|
|
97
232
|
return css `
|
|
98
233
|
--chevron-spacing: ${theme.base.spacing};
|
|
99
234
|
--chevron-border-thickness: ${theme.components.button['border-width']};
|
|
100
|
-
background
|
|
235
|
+
background: ${theme.components.card.background};
|
|
101
236
|
border-radius: ${theme.components.card['border-radius']};
|
|
102
237
|
display: flex;
|
|
103
238
|
padding: 0;
|
|
104
239
|
width: 100%;
|
|
105
|
-
overflow:
|
|
240
|
+
overflow-x: auto;
|
|
241
|
+
overflow-y: hidden;
|
|
106
242
|
list-style: none;
|
|
243
|
+
scrollbar-width: thin;
|
|
244
|
+
scrollbar-color: transparent transparent;
|
|
245
|
+
|
|
246
|
+
&:hover,
|
|
247
|
+
&:focus-within {
|
|
248
|
+
scrollbar-color: var(
|
|
249
|
+
--stages-scrollbar-thumb,
|
|
250
|
+
${transparentize(0.4, theme.base.palette['border-line'])}
|
|
251
|
+
)
|
|
252
|
+
var(--stages-scrollbar-track, transparent);
|
|
253
|
+
}
|
|
107
254
|
|
|
108
|
-
|
|
109
|
-
|
|
255
|
+
&::-webkit-scrollbar {
|
|
256
|
+
height: 0.25rem;
|
|
257
|
+
}
|
|
258
|
+
|
|
259
|
+
@media (pointer: coarse) {
|
|
260
|
+
scrollbar-width: none;
|
|
261
|
+
|
|
262
|
+
&::-webkit-scrollbar {
|
|
263
|
+
display: none;
|
|
264
|
+
}
|
|
110
265
|
}
|
|
111
266
|
`;
|
|
112
267
|
});
|
|
113
268
|
StyledStages.defaultProps = defaultThemeProp;
|
|
114
|
-
|
|
269
|
+
/**
|
|
270
|
+
* A sentinel is an invisible 1 px <li> placed at each end of the scrollable stage list.
|
|
271
|
+
* It is observed by an IntersectionObserver; when it scrolls out of view, the component sets
|
|
272
|
+
* --stages-fade-start or --stages-fade-end to show a gradient fade indicating more stages
|
|
273
|
+
* are reachable by scrolling. When it comes back into view the property is reset to 0.
|
|
274
|
+
*
|
|
275
|
+
* Sentinel elements carry aria-hidden="true" so they are valid list items semantically.
|
|
276
|
+
* Because styled-components scopes all CSS to a generated class, the chevron and layout rules
|
|
277
|
+
* in StyledStageContainer never apply to these elements — they carry a different class.
|
|
278
|
+
* CSS type-based selectors (:nth-of-type, :nth-last-of-type) in StyledStageContainer are
|
|
279
|
+
* offset by 1 at each end to skip the sentinels and target only real stage items.
|
|
280
|
+
*/
|
|
281
|
+
export const StyledSentinel = styled.li `
|
|
282
|
+
flex-shrink: 0;
|
|
283
|
+
|
|
284
|
+
/* NOTE: the sentinel must occupy
|
|
285
|
+
* a single physical pixel so IntersectionObserver can detect it at threshold 0 while having
|
|
286
|
+
* negligible layout impact. A rem value could collapse to zero at small font sizes.
|
|
287
|
+
*/
|
|
288
|
+
/* stylelint-disable-next-line unit-allowed-list -- 1px is intentional */
|
|
289
|
+
width: 1px;
|
|
290
|
+
/* stylelint-disable-next-line unit-allowed-list -- 1px is intentional */
|
|
291
|
+
height: 1px;
|
|
292
|
+
padding: 0;
|
|
293
|
+
margin: 0;
|
|
294
|
+
pointer-events: none;
|
|
295
|
+
|
|
296
|
+
/* Collapse the sentinel's layout footprint to zero on the side facing the stages.
|
|
297
|
+
* Without this, each 1px sentinel creates a visible gap between the stage buttons
|
|
298
|
+
* and the left/right edges of the wrapper. The sentinel remains in flow (required
|
|
299
|
+
* for IntersectionObserver scroll detection) but no longer displaces stage content.
|
|
300
|
+
*/
|
|
301
|
+
&:first-of-type {
|
|
302
|
+
/* stylelint-disable-next-line unit-allowed-list -- 1px matches sentinel width */
|
|
303
|
+
margin-inline-end: -1px;
|
|
304
|
+
}
|
|
305
|
+
|
|
306
|
+
&:last-of-type {
|
|
307
|
+
/* stylelint-disable-next-line unit-allowed-list -- 1px matches sentinel width */
|
|
308
|
+
margin-inline-start: -1px;
|
|
309
|
+
}
|
|
310
|
+
`;
|
|
311
|
+
StyledSentinel.defaultProps = defaultThemeProp;
|
|
312
|
+
/**
|
|
313
|
+
* Inner `<span>` holding stage label content. Optionally applies `text-overflow: ellipsis`
|
|
314
|
+
* for stages with long labels.
|
|
315
|
+
*/
|
|
316
|
+
export const StyledInnerStage = styled.span(({ theme, ellipsis }) => {
|
|
115
317
|
return css `
|
|
116
|
-
display: inline-
|
|
318
|
+
display: inline-flex;
|
|
319
|
+
align-items: center;
|
|
320
|
+
gap: calc(0.25 * ${theme.base.spacing});
|
|
117
321
|
text-align: center;
|
|
118
322
|
white-space: nowrap;
|
|
119
|
-
${
|
|
323
|
+
padding-inline-start: calc(0.875 * ${theme.base.spacing});
|
|
324
|
+
padding-inline-end: calc(1.125 * ${theme.base.spacing});
|
|
325
|
+
${ellipsis &&
|
|
120
326
|
css `
|
|
121
327
|
overflow: hidden;
|
|
122
328
|
text-overflow: ellipsis;
|
|
@@ -124,6 +330,10 @@ export const StyledInnerStage = styled.span(props => {
|
|
|
124
330
|
`;
|
|
125
331
|
});
|
|
126
332
|
StyledInnerStage.defaultProps = defaultThemeProp;
|
|
333
|
+
/**
|
|
334
|
+
* Clickable `<button>` for a single stage. Renders the chevron clip-path shape and
|
|
335
|
+
* applies status-based background and foreground colours.
|
|
336
|
+
*/
|
|
127
337
|
export const StyledStage = styled.button(({ theme: { base: { palette, 'hit-area': hitArea, transparency, 'font-weight': fontWeight }, components: { 'case-view': { stages } } }, status, readOnly }) => {
|
|
128
338
|
const stageForeground = calculateForegroundColor(stages.status[status].background, stages.status[status]['foreground-color']);
|
|
129
339
|
return css `
|
|
@@ -138,7 +348,7 @@ export const StyledStage = styled.button(({ theme: { base: { palette, 'hit-area'
|
|
|
138
348
|
/* Browsers do not reliably apply flex align-items: stretch to <button> elements.
|
|
139
349
|
* Adding 0.0625rem (1px at default font size) to min-height compensates so the button fills its <li> container,
|
|
140
350
|
* keeping the clipped chevron background flush with the top and bottom borders. */
|
|
141
|
-
min-height: calc(
|
|
351
|
+
min-height: calc(5 * var(--chevron-spacing) + 0.0625rem);
|
|
142
352
|
padding-inline-start: calc(2 * var(--chevron-spacing));
|
|
143
353
|
padding-inline-end: var(--chevron-spacing);
|
|
144
354
|
margin-inline-start: 0;
|
|
@@ -146,12 +356,12 @@ export const StyledStage = styled.button(({ theme: { base: { palette, 'hit-area'
|
|
|
146
356
|
width: calc(100% + ${chevronConfig.width});
|
|
147
357
|
--stage-chevron-width: ${chevronConfig.width};
|
|
148
358
|
|
|
149
|
-
${
|
|
359
|
+
${StyledInnerStage} {
|
|
150
360
|
transform: translateX(calc(-0.25 * var(--chevron-spacing)));
|
|
361
|
+
opacity: ${transparency['transparent-2']};
|
|
151
362
|
}
|
|
152
363
|
${stageClipPath(true, true)}
|
|
153
364
|
|
|
154
|
-
[dir='rtl'] & ${StyledIcon},
|
|
155
365
|
[dir='rtl'] & ${StyledInnerStage} {
|
|
156
366
|
transform: translateX(calc(0.25 * var(--chevron-spacing)));
|
|
157
367
|
}
|
|
@@ -201,19 +411,12 @@ export const StyledStage = styled.button(({ theme: { base: { palette, 'hit-area'
|
|
|
201
411
|
width: calc(100% + ${chevronConfig.coarseWidth});
|
|
202
412
|
--stage-chevron-width: ${chevronConfig.coarseWidth};
|
|
203
413
|
}
|
|
204
|
-
|
|
205
|
-
${StyledIcon} {
|
|
206
|
-
& ~ ${StyledInnerStage} {
|
|
207
|
-
margin-inline-start: 0.25rem;
|
|
208
|
-
}
|
|
209
|
-
}
|
|
210
|
-
|
|
211
|
-
${StyledInnerStage} {
|
|
212
|
-
opacity: ${transparency['transparent-2']};
|
|
213
|
-
}
|
|
214
414
|
`;
|
|
215
415
|
});
|
|
216
416
|
StyledStage.defaultProps = defaultThemeProp;
|
|
417
|
+
/**
|
|
418
|
+
* Checkmark icon shown inside completed stages, tinted to match the stage foreground colour.
|
|
419
|
+
*/
|
|
217
420
|
export const StyledStageCompleteIcon = styled(Icon)(({ theme: { components: { 'case-view': { stages: { status: { completed: { 'foreground-color': foregroundColor, background } } } } } } }) => {
|
|
218
421
|
const stageForeground = calculateForegroundColor(background, foregroundColor);
|
|
219
422
|
return css `
|
|
@@ -221,17 +424,24 @@ export const StyledStageCompleteIcon = styled(Icon)(({ theme: { components: { 'c
|
|
|
221
424
|
`;
|
|
222
425
|
});
|
|
223
426
|
StyledStageCompleteIcon.defaultProps = defaultThemeProp;
|
|
427
|
+
/**
|
|
428
|
+
* Stage label text. Renders in bold weight when the stage is the current active stage.
|
|
429
|
+
*/
|
|
224
430
|
export const StyledStageText = styled(Text)(({ theme, isCurrent }) => css `
|
|
225
431
|
font-weight: ${isCurrent ? theme.base['font-weight'].bold : theme.base['font-weight'].normal};
|
|
226
432
|
`);
|
|
227
433
|
StyledStageText.defaultProps = defaultThemeProp;
|
|
434
|
+
/**
|
|
435
|
+
* `<li>` container for a single stage item. Manages negative-margin chevron overlap,
|
|
436
|
+
* pseudo-element positioning, and z-index stacking for interactive states.
|
|
437
|
+
*/
|
|
228
438
|
export const StyledStageContainer = styled.li(({ theme: { base: { palette }, components: { card: { 'border-radius': borderRadius } } }, readOnly }) => {
|
|
229
439
|
return css `
|
|
230
440
|
display: flex;
|
|
231
441
|
position: relative;
|
|
232
442
|
margin-inline-start: calc(-1 * ${chevronConfig.width});
|
|
233
443
|
|
|
234
|
-
&:
|
|
444
|
+
&:nth-of-type(2) {
|
|
235
445
|
margin-inline-start: 0;
|
|
236
446
|
}
|
|
237
447
|
|
|
@@ -239,8 +449,9 @@ export const StyledStageContainer = styled.li(({ theme: { base: { palette }, com
|
|
|
239
449
|
* All non-last <li>s have z-index:1 so the later (right) <li>'s ::before paints on top
|
|
240
450
|
* at internal boundaries; the last <li> has no z-index so its left neighbor's ::after
|
|
241
451
|
* wins at the final boundary. On hover/focus/active, the interacting <li> gains z:2/3
|
|
242
|
-
* and its own pseudo-element surfaces for that boundary, regardless of which side.
|
|
243
|
-
|
|
452
|
+
* and its own pseudo-element surfaces for that boundary, regardless of which side.
|
|
453
|
+
*/
|
|
454
|
+
&:not(:nth-last-of-type(-n + 2)) {
|
|
244
455
|
z-index: 1;
|
|
245
456
|
}
|
|
246
457
|
|
|
@@ -260,7 +471,7 @@ export const StyledStageContainer = styled.li(({ theme: { base: { palette }, com
|
|
|
260
471
|
margin-inline-start: calc(-1 * ${chevronConfig.coarseWidth});
|
|
261
472
|
}
|
|
262
473
|
|
|
263
|
-
&:not(:
|
|
474
|
+
&:not(:nth-of-type(-n + 2))::before {
|
|
264
475
|
${createChevronPseudo('calc(2 * var(--chevron-border-thickness))', palette['border-line'], chevronConfig.squareSize)}
|
|
265
476
|
/* Elevate ::before above the button so it renders via the same pathway as ::after.
|
|
266
477
|
* Without z-index, ::before (first in DOM) is painted first and then covered by the
|
|
@@ -268,16 +479,18 @@ export const StyledStageContainer = styled.li(({ theme: { base: { palette }, com
|
|
|
268
479
|
* causes thicker interactive-state borders (3×) to look thinner on the left boundary
|
|
269
480
|
* than on the right (::after, which paints last and is always fully visible).
|
|
270
481
|
* The ::before tip's rightmost extent is at --stage-chevron-width from the <li> start,
|
|
271
|
-
* which is before the stage text (padding-inline-start: 2 × spacing), so no content overlap.
|
|
482
|
+
* which is before the stage text (padding-inline-start: 2 × spacing), so no content overlap.
|
|
483
|
+
*/
|
|
272
484
|
z-index: 1;
|
|
273
485
|
}
|
|
274
486
|
|
|
275
|
-
&:not(:last-of-type)::after {
|
|
487
|
+
&:not(:nth-last-of-type(-n + 2))::after {
|
|
276
488
|
${createChevronPseudo('calc(2 * var(--chevron-border-thickness))', palette['border-line'], chevronConfig.squareSize)}
|
|
277
489
|
}
|
|
278
490
|
|
|
279
491
|
/* Chevron positioning: 45° rotated squares create visual tips via offsets:
|
|
280
|
-
* left ≈ 0.
|
|
492
|
+
* left ≈ 0.86 × spacing, right ≈ 1.445 × spacing (accounts for skew correction)
|
|
493
|
+
*/
|
|
281
494
|
|
|
282
495
|
[dir='rtl'] &::before,
|
|
283
496
|
[dir='rtl'] &::after {
|
|
@@ -285,19 +498,18 @@ export const StyledStageContainer = styled.li(({ theme: { base: { palette }, com
|
|
|
285
498
|
}
|
|
286
499
|
|
|
287
500
|
/* Thicken chevrons to visually match button top/bottom border on any colored state.
|
|
288
|
-
*
|
|
501
|
+
* At 45° rotation, border appears 1/sin(45°) ≈ 0.707× thinner, so 2× border ≈ 1.4× horizontal border weight.
|
|
502
|
+
*/
|
|
289
503
|
${createChevronBaseStyles(chevronConfig, 'var(--chevron-border-thickness)')}
|
|
290
504
|
${createChevronInteractiveStates(chevronConfig, 'var(--chevron-border-thickness)', !readOnly)}
|
|
291
|
-
|
|
292
|
-
${!readOnly &&
|
|
505
|
+
${!readOnly &&
|
|
293
506
|
css `
|
|
294
507
|
&:has(button:hover)::before,
|
|
295
508
|
&:has(button:hover)::after {
|
|
296
509
|
border-color: ${palette['border-line']};
|
|
297
510
|
}
|
|
298
511
|
`}
|
|
299
|
-
|
|
300
|
-
&:has(button:focus-visible)::before,
|
|
512
|
+
&:has(button:focus-visible)::before,
|
|
301
513
|
&:has(button:focus-visible)::after {
|
|
302
514
|
border-color: ${palette.interactive};
|
|
303
515
|
}
|
|
@@ -308,27 +520,27 @@ export const StyledStageContainer = styled.li(({ theme: { base: { palette }, com
|
|
|
308
520
|
}
|
|
309
521
|
|
|
310
522
|
@media (pointer: coarse) {
|
|
311
|
-
&:not(:
|
|
312
|
-
&:not(:last-of-type)::after {
|
|
523
|
+
&:not(:nth-of-type(-n + 2))::before,
|
|
524
|
+
&:not(:nth-last-of-type(-n + 2))::after {
|
|
313
525
|
inset-block-start: calc(50% - ${chevronConfig.coarseSquareSize} / 2);
|
|
314
526
|
width: ${chevronConfig.coarseSquareSize};
|
|
315
527
|
height: ${chevronConfig.coarseSquareSize};
|
|
316
528
|
}
|
|
317
529
|
|
|
318
|
-
&:not(:
|
|
530
|
+
&:not(:nth-of-type(-n + 2))::before {
|
|
319
531
|
inset-inline-start: calc(
|
|
320
532
|
-1 * ${chevronConfig.coarseWidth} - ${chevronConfig.coarseOffsetLeft}
|
|
321
533
|
);
|
|
322
534
|
}
|
|
323
535
|
|
|
324
|
-
&:not(:last-of-type)::after {
|
|
536
|
+
&:not(:nth-last-of-type(-n + 2))::after {
|
|
325
537
|
inset-inline-end: calc(
|
|
326
538
|
-1 * ${chevronConfig.coarseWidth} + ${chevronConfig.coarseOffsetRight}
|
|
327
539
|
);
|
|
328
540
|
}
|
|
329
541
|
}
|
|
330
542
|
|
|
331
|
-
&:
|
|
543
|
+
&:nth-of-type(2):not(:nth-last-of-type(2)) > ${StyledStage} {
|
|
332
544
|
--stage-chevron-width: ${chevronConfig.width};
|
|
333
545
|
border-start-start-radius: ${borderRadius};
|
|
334
546
|
border-end-start-radius: ${borderRadius};
|
|
@@ -365,30 +577,77 @@ export const StyledStageContainer = styled.li(({ theme: { base: { palette }, com
|
|
|
365
577
|
}
|
|
366
578
|
}
|
|
367
579
|
|
|
368
|
-
&:last-of-type > ${StyledStage} {
|
|
580
|
+
&:nth-last-of-type(2):not(:nth-of-type(2)) > ${StyledStage} {
|
|
369
581
|
--stage-chevron-width: ${chevronConfig.width};
|
|
370
582
|
border-start-end-radius: ${borderRadius};
|
|
371
583
|
border-end-end-radius: ${borderRadius};
|
|
372
|
-
border-inline-end-width: calc(2 * var(--chevron-border-thickness));
|
|
373
584
|
padding-inline-end: 0;
|
|
374
585
|
width: 100%;
|
|
375
586
|
${stageClipPath(true, false)}
|
|
376
587
|
|
|
588
|
+
${!readOnly &&
|
|
589
|
+
css `
|
|
590
|
+
/* Inline-end interactive indicator via inset shadow — avoids border-color bleeding through gradient backgrounds */
|
|
591
|
+
&:hover {
|
|
592
|
+
box-shadow: inset calc(-2 * var(--chevron-border-thickness)) 0 0
|
|
593
|
+
${palette['border-line']};
|
|
594
|
+
|
|
595
|
+
[dir='rtl'] & {
|
|
596
|
+
box-shadow: inset calc(2 * var(--chevron-border-thickness)) 0 0
|
|
597
|
+
${palette['border-line']};
|
|
598
|
+
}
|
|
599
|
+
}
|
|
600
|
+
`}
|
|
601
|
+
|
|
602
|
+
&:focus-visible,
|
|
603
|
+
&:active {
|
|
604
|
+
box-shadow: inset calc(-2 * var(--chevron-border-thickness)) 0 0 ${palette.interactive};
|
|
605
|
+
|
|
606
|
+
[dir='rtl'] & {
|
|
607
|
+
box-shadow: inset calc(2 * var(--chevron-border-thickness)) 0 0 ${palette.interactive};
|
|
608
|
+
}
|
|
609
|
+
}
|
|
610
|
+
|
|
377
611
|
@media (pointer: coarse) {
|
|
378
612
|
--stage-chevron-width: ${chevronConfig.coarseWidth};
|
|
379
613
|
}
|
|
380
614
|
}
|
|
381
615
|
|
|
382
|
-
[dir='rtl'] &:
|
|
616
|
+
[dir='rtl'] &:nth-of-type(2):not(:nth-last-of-type(2)) > ${StyledStage} {
|
|
383
617
|
${stageClipPath(true, false, true)}
|
|
384
618
|
}
|
|
385
619
|
|
|
386
|
-
[dir='rtl'] &:last-of-type > ${StyledStage} {
|
|
620
|
+
[dir='rtl'] &:nth-last-of-type(2):not(:nth-of-type(2)) > ${StyledStage} {
|
|
387
621
|
${stageClipPath(false, true, true)}
|
|
388
622
|
}
|
|
623
|
+
|
|
624
|
+
&:nth-of-type(2):nth-last-of-type(2) > ${StyledStage} {
|
|
625
|
+
border-radius: ${borderRadius};
|
|
626
|
+
width: 100%;
|
|
627
|
+
${stageClipPath(false, false)}
|
|
628
|
+
|
|
629
|
+
${!readOnly &&
|
|
630
|
+
css `
|
|
631
|
+
&:hover {
|
|
632
|
+
box-shadow:
|
|
633
|
+
inset calc(2 * var(--chevron-border-thickness)) 0 0 ${palette['border-line']},
|
|
634
|
+
inset calc(-2 * var(--chevron-border-thickness)) 0 0 ${palette['border-line']};
|
|
635
|
+
}
|
|
636
|
+
`}
|
|
637
|
+
|
|
638
|
+
&:focus-visible,
|
|
639
|
+
&:active {
|
|
640
|
+
box-shadow:
|
|
641
|
+
inset calc(2 * var(--chevron-border-thickness)) 0 0 ${palette.interactive},
|
|
642
|
+
inset calc(-2 * var(--chevron-border-thickness)) 0 0 ${palette.interactive};
|
|
643
|
+
}
|
|
644
|
+
}
|
|
389
645
|
`;
|
|
390
646
|
});
|
|
391
647
|
StyledStageContainer.defaultProps = defaultThemeProp;
|
|
648
|
+
/**
|
|
649
|
+
* `<ol>` list of sub-step items displayed below the stages bar when a stage is expanded.
|
|
650
|
+
*/
|
|
392
651
|
export const StyledStepsContainer = styled.ol(({ theme }) => {
|
|
393
652
|
return css `
|
|
394
653
|
list-style-type: none;
|
|
@@ -400,6 +659,9 @@ export const StyledStepsContainer = styled.ol(({ theme }) => {
|
|
|
400
659
|
`;
|
|
401
660
|
});
|
|
402
661
|
StyledStepsContainer.defaultProps = defaultThemeProp;
|
|
662
|
+
/**
|
|
663
|
+
* Individual step `<li>` within a stage. Dims text and icon at reduced opacity when completed.
|
|
664
|
+
*/
|
|
403
665
|
export const StyledStep = styled.li(({ completed, theme }) => {
|
|
404
666
|
const textOpacity = completed ? theme.base.transparency['transparent-2'] : 1;
|
|
405
667
|
return css `
|
|
@@ -421,6 +683,10 @@ export const StyledStep = styled.li(({ completed, theme }) => {
|
|
|
421
683
|
`;
|
|
422
684
|
});
|
|
423
685
|
StyledStep.defaultProps = defaultThemeProp;
|
|
686
|
+
/**
|
|
687
|
+
* Small datetime label rendered beneath a step. Displayed at the `xs` font size
|
|
688
|
+
* and reduced opacity.
|
|
689
|
+
*/
|
|
424
690
|
export const StyledDateTimeDisplay = styled(DateTimeDisplay)(({ theme }) => {
|
|
425
691
|
const fontSize = calculateFontSize(theme.base['font-size'], theme.base['font-scale']);
|
|
426
692
|
return css `
|
|
@@ -429,12 +695,19 @@ export const StyledDateTimeDisplay = styled(DateTimeDisplay)(({ theme }) => {
|
|
|
429
695
|
`;
|
|
430
696
|
});
|
|
431
697
|
StyledDateTimeDisplay.defaultProps = defaultThemeProp;
|
|
698
|
+
/**
|
|
699
|
+
* Container `<div>` for the stage glimpse preview panel, constrained to a small max-width.
|
|
700
|
+
*/
|
|
432
701
|
export const StyledStageGlimpse = styled.div(({ theme }) => {
|
|
433
702
|
return css `
|
|
434
703
|
max-width: ${theme.base['content-width'].sm};
|
|
435
704
|
`;
|
|
436
705
|
});
|
|
437
706
|
StyledStageGlimpse.defaultProps = defaultThemeProp;
|
|
707
|
+
/**
|
|
708
|
+
* Visually hidden `<p>` providing an accessible description for the stages list,
|
|
709
|
+
* announced by screen readers but not displayed on screen.
|
|
710
|
+
*/
|
|
438
711
|
export const StyledStagesDescription = styled.p `
|
|
439
712
|
display: none;
|
|
440
713
|
`;
|