@pega/cosmos-react-work 10.0.0-build.4.2 → 10.0.0-build.4.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.
- package/lib/components/AppAnnouncement/AppAnnouncement.d.ts.map +1 -1
- package/lib/components/AppAnnouncement/AppAnnouncement.js +30 -2
- package/lib/components/AppAnnouncement/AppAnnouncement.js.map +1 -1
- package/lib/components/Article/ArticleRating.d.ts.map +1 -1
- package/lib/components/Article/ArticleRating.js +2 -2
- package/lib/components/Article/ArticleRating.js.map +1 -1
- package/lib/components/ArticleList/ArticleFeedback.d.ts.map +1 -1
- package/lib/components/ArticleList/ArticleFeedback.js +2 -2
- package/lib/components/ArticleList/ArticleFeedback.js.map +1 -1
- package/lib/components/CaseView/CaseHeader/CaseHeader.d.ts.map +1 -1
- package/lib/components/CaseView/CaseHeader/CaseHeader.js +1 -1
- package/lib/components/CaseView/CaseHeader/CaseHeader.js.map +1 -1
- package/lib/components/CaseView/CaseView.styles.d.ts.map +1 -1
- package/lib/components/CaseView/CaseView.styles.js +4 -2
- package/lib/components/CaseView/CaseView.styles.js.map +1 -1
- package/lib/components/CaseView/CaseView.types.d.ts +1 -0
- package/lib/components/CaseView/CaseView.types.d.ts.map +1 -1
- package/lib/components/CaseView/CaseView.types.js.map +1 -1
- package/lib/components/Details/DetailsList.d.ts.map +1 -1
- package/lib/components/Details/DetailsList.js +2 -2
- package/lib/components/Details/DetailsList.js.map +1 -1
- package/lib/components/GenAICoach/ActiveCases.d.ts.map +1 -1
- package/lib/components/GenAICoach/ActiveCases.js +2 -1
- package/lib/components/GenAICoach/ActiveCases.js.map +1 -1
- package/lib/components/GenAICoach/GenAICoach.js +2 -2
- package/lib/components/GenAICoach/GenAICoach.js.map +1 -1
- package/lib/components/GenAICoach/GenAICoach.styles.d.ts +2 -0
- package/lib/components/GenAICoach/GenAICoach.styles.d.ts.map +1 -1
- package/lib/components/GenAICoach/GenAICoach.styles.js +11 -2
- package/lib/components/GenAICoach/GenAICoach.styles.js.map +1 -1
- package/lib/components/GenAICoach/GenAIMessage.d.ts.map +1 -1
- package/lib/components/GenAICoach/GenAIMessage.js +15 -2
- package/lib/components/GenAICoach/GenAIMessage.js.map +1 -1
- package/lib/components/GenAICoach/GenAIMessageFeedback.d.ts.map +1 -1
- package/lib/components/GenAICoach/GenAIMessageFeedback.js +2 -2
- package/lib/components/GenAICoach/GenAIMessageFeedback.js.map +1 -1
- package/lib/components/GenAICoach/Questionnaire.js +2 -2
- package/lib/components/GenAICoach/Questionnaire.js.map +1 -1
- package/lib/components/InteractionNotification/InteractionNotification.d.ts +1 -1
- package/lib/components/InteractionNotification/InteractionNotification.d.ts.map +1 -1
- package/lib/components/InteractionNotification/InteractionNotification.js +2 -2
- package/lib/components/InteractionNotification/InteractionNotification.js.map +1 -1
- package/lib/components/Shortcuts/Shortcuts.d.ts.map +1 -1
- package/lib/components/Shortcuts/Shortcuts.js +20 -11
- package/lib/components/Shortcuts/Shortcuts.js.map +1 -1
- package/lib/components/Shortcuts/Shortcuts.styles.d.ts +16 -3
- package/lib/components/Shortcuts/Shortcuts.styles.d.ts.map +1 -1
- package/lib/components/Shortcuts/Shortcuts.styles.js +91 -47
- package/lib/components/Shortcuts/Shortcuts.styles.js.map +1 -1
- package/lib/components/Shortcuts/Shortcuts.types.d.ts +8 -2
- 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.map +1 -1
- package/lib/components/Stages/Stages.js +59 -39
- package/lib/components/Stages/Stages.js.map +1 -1
- package/lib/components/Stages/Stages.styles.d.ts +27 -5
- package/lib/components/Stages/Stages.styles.d.ts.map +1 -1
- package/lib/components/Stages/Stages.styles.js +693 -163
- package/lib/components/Stages/Stages.styles.js.map +1 -1
- package/lib/components/Stages/Stages.types.d.ts +6 -0
- 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 -1
- package/lib/components/Stages/index.d.ts.map +1 -1
- package/lib/components/Stages/index.js.map +1 -1
- package/lib/components/Tags/Tags.d.ts.map +1 -1
- package/lib/components/Tags/Tags.js +1 -12
- package/lib/components/Tags/Tags.js.map +1 -1
- package/lib/components/Tasks/TaskCard.d.ts.map +1 -1
- package/lib/components/Tasks/TaskCard.js +5 -2
- package/lib/components/Tasks/TaskCard.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 +7 -2
- 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,6 +1,6 @@
|
|
|
1
|
-
import styled, { css } from 'styled-components';
|
|
2
|
-
import { transparentize } from 'polished';
|
|
3
|
-
import { calculateFontSize, DateTimeDisplay, defaultThemeProp, Icon, Text, StyledIcon, calculateForegroundColor } from '@pega/cosmos-react-core';
|
|
1
|
+
import styled, { css, keyframes } from 'styled-components';
|
|
2
|
+
import { transparentize, darken } from 'polished';
|
|
3
|
+
import { calculateFontSize, DateTimeDisplay, defaultThemeProp, Icon, Text, StyledIcon, calculateForegroundColor, tryCatch } from '@pega/cosmos-react-core';
|
|
4
4
|
const stageClipPath = (leftNotch, rightPoint, mirrored = false) => {
|
|
5
5
|
if (mirrored) {
|
|
6
6
|
// RTL: mirror the LTR clip-path polygon
|
|
@@ -30,6 +30,20 @@ const stageClipPath = (leftNotch, rightPoint, mirrored = false) => {
|
|
|
30
30
|
}
|
|
31
31
|
return `clip-path: polygon(${points.join(', ')});`;
|
|
32
32
|
};
|
|
33
|
+
const segmentedConfig = {
|
|
34
|
+
width: 'calc(0.8 * var(--chevron-spacing))',
|
|
35
|
+
coarseWidth: 'calc(1.0 * var(--chevron-spacing))'
|
|
36
|
+
};
|
|
37
|
+
const segmentedClipPath = (leftCut, rightCut, mirrored = false) => {
|
|
38
|
+
if (mirrored) {
|
|
39
|
+
const topRight = rightCut ? 'calc(100% - var(--segmented-width)) 0%' : '100% 0%';
|
|
40
|
+
const bottomLeft = leftCut ? 'var(--segmented-width) 100%' : '0% 100%';
|
|
41
|
+
return `clip-path: polygon(0% 0%, ${topRight}, 100% 100%, ${bottomLeft});`;
|
|
42
|
+
}
|
|
43
|
+
const topLeft = leftCut ? 'var(--segmented-width) 0%' : '0% 0%';
|
|
44
|
+
const bottomRight = rightCut ? 'calc(100% - var(--segmented-width)) 100%' : '100% 100%';
|
|
45
|
+
return `clip-path: polygon(${topLeft}, 100% 0%, ${bottomRight}, 0% 100%);`;
|
|
46
|
+
};
|
|
33
47
|
// === Chevron Configuration ===
|
|
34
48
|
// Centralizes spacing and border thickness via CSS custom properties set at StyledStages
|
|
35
49
|
const chevronConfig = {
|
|
@@ -50,8 +64,15 @@ const chevronConfig = {
|
|
|
50
64
|
// Equal to `width` so the point extends exactly one chevron-width beyond the stage boundary.
|
|
51
65
|
offsetRight: 'calc(1.445 * var(--chevron-spacing))',
|
|
52
66
|
// Coarse-pointer equivalents of offsetLeft/offsetRight, scaled to match coarseWidth/coarseSquareSize.
|
|
53
|
-
coarseOffsetLeft:
|
|
54
|
-
|
|
67
|
+
// coarseOffsetLeft must satisfy: coarseSquareSize = 2 × coarseWidth + coarseOffsetLeft
|
|
68
|
+
// (5 = 2 × 1.797 + 1.406) so that ::before and ::after co-locate on coarse devices.
|
|
69
|
+
coarseOffsetLeft: 'calc(1.406 * var(--chevron-spacing))',
|
|
70
|
+
coarseOffsetRight: 'calc(1.797 * var(--chevron-spacing))',
|
|
71
|
+
// Pre-computed flat positions for ::before notch and ::after point.
|
|
72
|
+
notchInsetStart: 'calc(-2.305 * var(--chevron-spacing))',
|
|
73
|
+
// 3.203 = exact alignment (coarseSquareSize - coarseWidth); slightly overdone default clears sub-pixel rounding on 3× displays.
|
|
74
|
+
coarseNotchInsetStart: 'calc(-1 * var(--stages-coarse-notch-correction) * var(--chevron-spacing))',
|
|
75
|
+
pointInsetEnd: '0'
|
|
55
76
|
};
|
|
56
77
|
// === Chevron Helpers ===
|
|
57
78
|
// After team discussion we decided to use logical properties throughout — `inset-block-start`
|
|
@@ -81,11 +102,11 @@ const createChevronBaseStyles = (config, borderThicknessVar) => css `
|
|
|
81
102
|
}
|
|
82
103
|
|
|
83
104
|
&:not(:nth-of-type(-n + 2))::before {
|
|
84
|
-
inset-inline-start:
|
|
105
|
+
inset-inline-start: ${config.notchInsetStart};
|
|
85
106
|
}
|
|
86
107
|
|
|
87
108
|
&:not(:nth-last-of-type(-n + 2))::after {
|
|
88
|
-
inset-inline-end:
|
|
109
|
+
inset-inline-end: ${config.pointInsetEnd};
|
|
89
110
|
}
|
|
90
111
|
`;
|
|
91
112
|
const createChevronInteractiveStates = (config, borderThicknessVar, includeHover = true) => css `
|
|
@@ -137,6 +158,14 @@ export const StyledStagesWrapper = styled.div(({ theme }) => {
|
|
|
137
158
|
--stages-wrapper-bottom-radius,
|
|
138
159
|
${theme.components.card['border-radius']}
|
|
139
160
|
);
|
|
161
|
+
-webkit-mask-image: linear-gradient(black, black),
|
|
162
|
+
linear-gradient(
|
|
163
|
+
to right,
|
|
164
|
+
transparent calc(-1 * var(--mask-edge-overhang)),
|
|
165
|
+
black var(--stages-fade-start),
|
|
166
|
+
black calc(100% - var(--stages-fade-end)),
|
|
167
|
+
transparent calc(100% + var(--mask-edge-overhang))
|
|
168
|
+
);
|
|
140
169
|
mask-image: linear-gradient(black, black),
|
|
141
170
|
linear-gradient(
|
|
142
171
|
to right,
|
|
@@ -154,6 +183,14 @@ export const StyledStagesWrapper = styled.div(({ theme }) => {
|
|
|
154
183
|
mask-repeat: no-repeat, no-repeat;
|
|
155
184
|
|
|
156
185
|
[dir='rtl'] & {
|
|
186
|
+
-webkit-mask-image: linear-gradient(black, black),
|
|
187
|
+
linear-gradient(
|
|
188
|
+
to right,
|
|
189
|
+
transparent calc(-1 * var(--mask-edge-overhang)),
|
|
190
|
+
black var(--stages-fade-end),
|
|
191
|
+
black calc(100% - var(--stages-fade-start)),
|
|
192
|
+
transparent calc(100% + var(--mask-edge-overhang))
|
|
193
|
+
);
|
|
157
194
|
mask-image: linear-gradient(black, black),
|
|
158
195
|
linear-gradient(
|
|
159
196
|
to right,
|
|
@@ -170,6 +207,13 @@ export const StyledStagesWrapper = styled.div(({ theme }) => {
|
|
|
170
207
|
|
|
171
208
|
@media (pointer: coarse) {
|
|
172
209
|
--stages-fade-width: calc(${theme.base.spacing} * 3);
|
|
210
|
+
-webkit-mask-image: linear-gradient(
|
|
211
|
+
to right,
|
|
212
|
+
transparent calc(-1 * var(--mask-edge-overhang)),
|
|
213
|
+
black var(--stages-fade-start),
|
|
214
|
+
black calc(100% - var(--stages-fade-end)),
|
|
215
|
+
transparent calc(100% + var(--mask-edge-overhang))
|
|
216
|
+
);
|
|
173
217
|
mask-image: linear-gradient(
|
|
174
218
|
to right,
|
|
175
219
|
transparent calc(-1 * var(--mask-edge-overhang)),
|
|
@@ -182,6 +226,13 @@ export const StyledStagesWrapper = styled.div(({ theme }) => {
|
|
|
182
226
|
mask-repeat: no-repeat;
|
|
183
227
|
|
|
184
228
|
[dir='rtl'] & {
|
|
229
|
+
-webkit-mask-image: linear-gradient(
|
|
230
|
+
to right,
|
|
231
|
+
transparent calc(-1 * var(--mask-edge-overhang)),
|
|
232
|
+
black var(--stages-fade-end),
|
|
233
|
+
black calc(100% - var(--stages-fade-start)),
|
|
234
|
+
transparent calc(100% + var(--mask-edge-overhang))
|
|
235
|
+
);
|
|
185
236
|
mask-image: linear-gradient(
|
|
186
237
|
to right,
|
|
187
238
|
transparent calc(-1 * var(--mask-edge-overhang)),
|
|
@@ -195,13 +246,18 @@ export const StyledStagesWrapper = styled.div(({ theme }) => {
|
|
|
195
246
|
});
|
|
196
247
|
StyledStagesWrapper.defaultProps = defaultThemeProp;
|
|
197
248
|
/**
|
|
198
|
-
* Scrollable `<ol>` containing all stage chevron items. Sets the `--chevron-spacing
|
|
199
|
-
* and `--
|
|
249
|
+
* Scrollable `<ol>` containing all stage chevron items. Sets the `--chevron-spacing`,
|
|
250
|
+
* `--chevron-border-thickness`, and `--segmented-border-thickness` custom properties
|
|
251
|
+
* consumed by child elements.
|
|
200
252
|
*/
|
|
201
|
-
export const StyledStages = styled.ol(({ theme }) => {
|
|
253
|
+
export const StyledStages = styled.ol(({ theme, variant }) => {
|
|
254
|
+
const isMilestone = variant === 'milestone';
|
|
202
255
|
return css `
|
|
203
256
|
--chevron-spacing: ${theme.base.spacing};
|
|
204
257
|
--chevron-border-thickness: ${theme.components.button['border-width']};
|
|
258
|
+
--segmented-border-thickness: calc(2 * ${theme.components.button['border-width']});
|
|
259
|
+
--segmented-width: ${segmentedConfig.width};
|
|
260
|
+
background: ${theme.components.card.background};
|
|
205
261
|
border-radius: ${theme.components.card['border-radius']};
|
|
206
262
|
display: flex;
|
|
207
263
|
padding: 0;
|
|
@@ -212,6 +268,17 @@ export const StyledStages = styled.ol(({ theme }) => {
|
|
|
212
268
|
scrollbar-width: thin;
|
|
213
269
|
scrollbar-color: transparent transparent;
|
|
214
270
|
|
|
271
|
+
${isMilestone &&
|
|
272
|
+
css `
|
|
273
|
+
--milestone-size: calc(4 * ${theme.base.spacing});
|
|
274
|
+
--milestone-pulse-min: calc(var(--milestone-size) * 0.1);
|
|
275
|
+
--milestone-pulse-start: ${transparentize(0.5, theme.base.palette.interactive)};
|
|
276
|
+
--milestone-pulse-spread: calc(var(--milestone-size) * 0.25);
|
|
277
|
+
--milestone-pulse-end: ${transparentize(0.75, theme.base.palette.interactive)};
|
|
278
|
+
padding-block: ${theme.base.spacing};
|
|
279
|
+
padding-inline: calc(var(--milestone-size) * 0.25);
|
|
280
|
+
`}
|
|
281
|
+
|
|
215
282
|
&:hover,
|
|
216
283
|
&:focus-within {
|
|
217
284
|
scrollbar-color: var(
|
|
@@ -226,6 +293,8 @@ export const StyledStages = styled.ol(({ theme }) => {
|
|
|
226
293
|
}
|
|
227
294
|
|
|
228
295
|
@media (pointer: coarse) {
|
|
296
|
+
/* 3.203 = exact alignment; slightly overdone default to clear sub-pixel rounding on 3× displays */
|
|
297
|
+
--stages-coarse-notch-correction: 3.35;
|
|
229
298
|
scrollbar-width: none;
|
|
230
299
|
|
|
231
300
|
&::-webkit-scrollbar {
|
|
@@ -299,11 +368,58 @@ export const StyledInnerStage = styled.span(({ theme, ellipsis }) => {
|
|
|
299
368
|
`;
|
|
300
369
|
});
|
|
301
370
|
StyledInnerStage.defaultProps = defaultThemeProp;
|
|
371
|
+
const stageButtonChevronStyles = (theme) => css `
|
|
372
|
+
padding-inline-start: calc(2 * var(--chevron-spacing));
|
|
373
|
+
padding-inline-end: var(--chevron-spacing);
|
|
374
|
+
width: calc(100% + ${chevronConfig.width});
|
|
375
|
+
--stage-chevron-width: ${chevronConfig.width};
|
|
376
|
+
|
|
377
|
+
${StyledInnerStage} {
|
|
378
|
+
transform: translateX(calc(-0.25 * var(--chevron-spacing)));
|
|
379
|
+
opacity: ${theme.base.transparency['transparent-2']};
|
|
380
|
+
}
|
|
381
|
+
|
|
382
|
+
${stageClipPath(true, true)}
|
|
383
|
+
|
|
384
|
+
[dir='rtl'] & ${StyledInnerStage} {
|
|
385
|
+
transform: translateX(calc(0.25 * var(--chevron-spacing)));
|
|
386
|
+
}
|
|
387
|
+
|
|
388
|
+
[dir='rtl'] & {
|
|
389
|
+
${stageClipPath(true, true, true)}
|
|
390
|
+
}
|
|
391
|
+
|
|
392
|
+
@media (pointer: coarse) {
|
|
393
|
+
padding-inline-start: calc(2.25 * var(--chevron-spacing));
|
|
394
|
+
width: calc(100% + ${chevronConfig.coarseWidth});
|
|
395
|
+
--stage-chevron-width: ${chevronConfig.coarseWidth};
|
|
396
|
+
}
|
|
397
|
+
`;
|
|
398
|
+
const stageButtonSegmentedStyles = (theme) => css `
|
|
399
|
+
width: 100%;
|
|
400
|
+
padding-inline-start: calc(var(--segmented-width) + var(--chevron-spacing));
|
|
401
|
+
padding-inline-end: calc(var(--segmented-width) + var(--chevron-spacing));
|
|
402
|
+
|
|
403
|
+
${StyledInnerStage} {
|
|
404
|
+
opacity: ${theme.base.transparency['transparent-2']};
|
|
405
|
+
}
|
|
406
|
+
|
|
407
|
+
${segmentedClipPath(true, true)}
|
|
408
|
+
|
|
409
|
+
[dir='rtl'] & {
|
|
410
|
+
${segmentedClipPath(true, true, true)}
|
|
411
|
+
}
|
|
412
|
+
`;
|
|
413
|
+
const stageButtonVariants = {
|
|
414
|
+
chevron: stageButtonChevronStyles,
|
|
415
|
+
segmented: stageButtonSegmentedStyles,
|
|
416
|
+
milestone: () => css ``
|
|
417
|
+
};
|
|
302
418
|
/**
|
|
303
419
|
* Clickable `<button>` for a single stage. Renders the chevron clip-path shape and
|
|
304
420
|
* applies status-based background and foreground colours.
|
|
305
421
|
*/
|
|
306
|
-
export const StyledStage = styled.button(({ theme: { base: { palette, 'hit-area': hitArea, transparency, 'font-weight': fontWeight }, components: { 'case-view': { stages } } }, status, readOnly }) => {
|
|
422
|
+
export const StyledStage = styled.button(({ theme, theme: { base: { palette, 'hit-area': hitArea, transparency, 'font-weight': fontWeight }, components: { 'case-view': { stages } } }, status, readOnly, variant: shape }) => {
|
|
307
423
|
const stageForeground = calculateForegroundColor(stages.status[status].background, stages.status[status]['foreground-color']);
|
|
308
424
|
return css `
|
|
309
425
|
background: ${stages.status[status].background};
|
|
@@ -318,26 +434,10 @@ export const StyledStage = styled.button(({ theme: { base: { palette, 'hit-area'
|
|
|
318
434
|
* Adding 0.0625rem (1px at default font size) to min-height compensates so the button fills its <li> container,
|
|
319
435
|
* keeping the clipped chevron background flush with the top and bottom borders. */
|
|
320
436
|
min-height: calc(5 * var(--chevron-spacing) + 0.0625rem);
|
|
321
|
-
padding-inline-start: calc(2 * var(--chevron-spacing));
|
|
322
|
-
padding-inline-end: var(--chevron-spacing);
|
|
323
437
|
margin-inline-start: 0;
|
|
324
438
|
margin-inline-end: 0;
|
|
325
|
-
width: calc(100% + ${chevronConfig.width});
|
|
326
|
-
--stage-chevron-width: ${chevronConfig.width};
|
|
327
439
|
|
|
328
|
-
${
|
|
329
|
-
transform: translateX(calc(-0.25 * var(--chevron-spacing)));
|
|
330
|
-
opacity: ${transparency['transparent-2']};
|
|
331
|
-
}
|
|
332
|
-
${stageClipPath(true, true)}
|
|
333
|
-
|
|
334
|
-
[dir='rtl'] & ${StyledInnerStage} {
|
|
335
|
-
transform: translateX(calc(0.25 * var(--chevron-spacing)));
|
|
336
|
-
}
|
|
337
|
-
|
|
338
|
-
[dir='rtl'] & {
|
|
339
|
-
${stageClipPath(true, true, true)}
|
|
340
|
-
}
|
|
440
|
+
${stageButtonVariants[shape](theme)}
|
|
341
441
|
|
|
342
442
|
${!readOnly &&
|
|
343
443
|
css `
|
|
@@ -376,9 +476,6 @@ export const StyledStage = styled.button(({ theme: { base: { palette, 'hit-area'
|
|
|
376
476
|
|
|
377
477
|
@media (pointer: coarse) {
|
|
378
478
|
min-height: ${hitArea['finger-min']};
|
|
379
|
-
padding-inline-start: calc(2.25 * var(--chevron-spacing));
|
|
380
|
-
width: calc(100% + ${chevronConfig.coarseWidth});
|
|
381
|
-
--stage-chevron-width: ${chevronConfig.coarseWidth};
|
|
382
479
|
}
|
|
383
480
|
`;
|
|
384
481
|
});
|
|
@@ -400,195 +497,439 @@ export const StyledStageText = styled(Text)(({ theme, isCurrent }) => css `
|
|
|
400
497
|
font-weight: ${isCurrent ? theme.base['font-weight'].bold : theme.base['font-weight'].normal};
|
|
401
498
|
`);
|
|
402
499
|
StyledStageText.defaultProps = defaultThemeProp;
|
|
403
|
-
|
|
404
|
-
|
|
405
|
-
* pseudo-element positioning, and z-index stacking for interactive states.
|
|
406
|
-
*/
|
|
407
|
-
export const StyledStageContainer = styled.li(({ theme: { base: { palette }, components: { card: { 'border-radius': borderRadius } } }, readOnly }) => {
|
|
500
|
+
const stageContainerChevronStyles = (theme, readOnly) => {
|
|
501
|
+
const includeHover = !readOnly;
|
|
408
502
|
return css `
|
|
409
|
-
|
|
410
|
-
|
|
411
|
-
margin-inline-start: calc(-1 * ${chevronConfig.width});
|
|
503
|
+
/* Chevron: negative-margin overlap so consecutive stages share a boundary */
|
|
504
|
+
margin-inline-start: calc(-1 * ${chevronConfig.width});
|
|
412
505
|
|
|
413
|
-
|
|
414
|
-
|
|
415
|
-
|
|
506
|
+
&:nth-of-type(2) {
|
|
507
|
+
margin-inline-start: 0;
|
|
508
|
+
}
|
|
416
509
|
|
|
417
|
-
|
|
418
|
-
|
|
419
|
-
|
|
420
|
-
|
|
421
|
-
*
|
|
510
|
+
/* Chevron boundary indicators via ::before (left notch) and ::after (right point) pseudo-elements */
|
|
511
|
+
&:not(:nth-of-type(-n + 2))::before {
|
|
512
|
+
${createChevronPseudo('calc(2 * var(--chevron-border-thickness))', theme.base.palette['border-line'], chevronConfig.squareSize)}
|
|
513
|
+
/* Elevate ::before above the button so it renders via the same pathway as ::after.
|
|
514
|
+
* Without z-index, ::before (first in DOM) is painted first and then covered by the
|
|
515
|
+
* button, making it only partially visible through the clip-path notch window. This
|
|
516
|
+
* causes thicker interactive-state borders (3×) to look thinner on the left boundary
|
|
517
|
+
* than on the right (::after, which paints last and is always fully visible).
|
|
518
|
+
* The ::before tip's rightmost extent is at --stage-chevron-width from the <li> start,
|
|
519
|
+
* which is before the stage text (padding-inline-start: 2 × spacing), so no content overlap.
|
|
422
520
|
*/
|
|
423
|
-
|
|
424
|
-
|
|
425
|
-
}
|
|
521
|
+
z-index: 1;
|
|
522
|
+
}
|
|
426
523
|
|
|
427
|
-
|
|
428
|
-
|
|
429
|
-
|
|
524
|
+
&:not(:nth-last-of-type(-n + 2))::after {
|
|
525
|
+
${createChevronPseudo('calc(2 * var(--chevron-border-thickness))', theme.base.palette['border-line'], chevronConfig.squareSize)}
|
|
526
|
+
}
|
|
527
|
+
|
|
528
|
+
[dir='rtl'] &::before,
|
|
529
|
+
[dir='rtl'] &::after {
|
|
530
|
+
transform: rotateZ(-45deg) skew(-15deg, -15deg);
|
|
531
|
+
}
|
|
532
|
+
|
|
533
|
+
/* Chevron positioning: 45° rotated squares create visual tips via offsets:
|
|
534
|
+
* left ≈ 0.86 × spacing, right ≈ 1.445 × spacing (accounts for skew correction)
|
|
535
|
+
*/
|
|
536
|
+
${createChevronBaseStyles(chevronConfig, 'var(--chevron-border-thickness)')}
|
|
537
|
+
${createChevronInteractiveStates(chevronConfig, 'var(--chevron-border-thickness)', includeHover)}
|
|
538
|
+
|
|
539
|
+
/* Thicken chevrons to visually match button top/bottom border on any colored state.
|
|
540
|
+
* At 45° rotation, border appears 1/sin(45°) ≈ 0.707× thinner, so 2× border ≈ 1.4× horizontal border weight.
|
|
541
|
+
*/
|
|
542
|
+
${includeHover &&
|
|
543
|
+
css `
|
|
544
|
+
&:has(button:hover)::before,
|
|
545
|
+
&:has(button:hover)::after {
|
|
546
|
+
border-color: ${theme.base.palette['border-line']};
|
|
430
547
|
}
|
|
548
|
+
`}
|
|
431
549
|
|
|
432
|
-
|
|
550
|
+
&:has(button:focus-visible)::before,
|
|
551
|
+
&:has(button:focus-visible)::after {
|
|
552
|
+
border-color: ${theme.base.palette.interactive};
|
|
553
|
+
}
|
|
554
|
+
|
|
555
|
+
&:has(button:active)::before,
|
|
556
|
+
&:has(button:active)::after {
|
|
557
|
+
border-color: ${theme.base.palette.interactive};
|
|
558
|
+
}
|
|
559
|
+
|
|
560
|
+
/* First stage: no left notch, extended width to cover the full left edge */
|
|
561
|
+
&:nth-of-type(2):not(:nth-last-of-type(2)) > ${StyledStage} {
|
|
562
|
+
--stage-chevron-width: ${chevronConfig.width};
|
|
563
|
+
width: calc(100% + (2 * var(--stage-chevron-width)));
|
|
564
|
+
padding-inline-start: calc(var(--chevron-spacing));
|
|
565
|
+
${stageClipPath(false, true)}
|
|
566
|
+
|
|
567
|
+
${includeHover &&
|
|
433
568
|
css `
|
|
434
|
-
|
|
435
|
-
|
|
569
|
+
/* Inline-start interactive indicator via inset shadow — avoids border-color bleeding through gradient backgrounds */
|
|
570
|
+
&:hover {
|
|
571
|
+
box-shadow: inset calc(2 * var(--chevron-border-thickness)) 0 0
|
|
572
|
+
${theme.base.palette['border-line']};
|
|
573
|
+
|
|
574
|
+
[dir='rtl'] & {
|
|
575
|
+
box-shadow: inset calc(-2 * var(--chevron-border-thickness)) 0 0
|
|
576
|
+
${theme.base.palette['border-line']};
|
|
577
|
+
}
|
|
436
578
|
}
|
|
437
579
|
`}
|
|
438
580
|
|
|
581
|
+
&:focus-visible,
|
|
582
|
+
&:active {
|
|
583
|
+
box-shadow: inset calc(2 * var(--chevron-border-thickness)) 0 0
|
|
584
|
+
${theme.base.palette.interactive};
|
|
585
|
+
|
|
586
|
+
[dir='rtl'] & {
|
|
587
|
+
box-shadow: inset calc(-2 * var(--chevron-border-thickness)) 0 0
|
|
588
|
+
${theme.base.palette.interactive};
|
|
589
|
+
}
|
|
590
|
+
}
|
|
591
|
+
|
|
439
592
|
@media (pointer: coarse) {
|
|
440
|
-
|
|
593
|
+
--stage-chevron-width: ${chevronConfig.coarseWidth};
|
|
594
|
+
width: calc(100% + (2 * var(--stage-chevron-width)));
|
|
441
595
|
}
|
|
596
|
+
}
|
|
442
597
|
|
|
443
|
-
|
|
444
|
-
|
|
445
|
-
|
|
446
|
-
|
|
447
|
-
|
|
448
|
-
|
|
449
|
-
|
|
450
|
-
|
|
451
|
-
|
|
452
|
-
|
|
453
|
-
|
|
598
|
+
/* Last stage: no right point */
|
|
599
|
+
&:nth-last-of-type(2):not(:nth-of-type(2)) > ${StyledStage} {
|
|
600
|
+
--stage-chevron-width: ${chevronConfig.width};
|
|
601
|
+
padding-inline-end: 0;
|
|
602
|
+
width: 100%;
|
|
603
|
+
${stageClipPath(true, false)}
|
|
604
|
+
|
|
605
|
+
${includeHover &&
|
|
606
|
+
css `
|
|
607
|
+
/* Inline-end interactive indicator via inset shadow — avoids border-color bleeding through gradient backgrounds */
|
|
608
|
+
&:hover {
|
|
609
|
+
box-shadow: inset calc(-2 * var(--chevron-border-thickness)) 0 0
|
|
610
|
+
${theme.base.palette['border-line']};
|
|
611
|
+
|
|
612
|
+
[dir='rtl'] & {
|
|
613
|
+
box-shadow: inset calc(2 * var(--chevron-border-thickness)) 0 0
|
|
614
|
+
${theme.base.palette['border-line']};
|
|
615
|
+
}
|
|
616
|
+
}
|
|
617
|
+
`}
|
|
618
|
+
|
|
619
|
+
&:focus-visible,
|
|
620
|
+
&:active {
|
|
621
|
+
box-shadow: inset calc(-2 * var(--chevron-border-thickness)) 0 0
|
|
622
|
+
${theme.base.palette.interactive};
|
|
623
|
+
|
|
624
|
+
[dir='rtl'] & {
|
|
625
|
+
box-shadow: inset calc(2 * var(--chevron-border-thickness)) 0 0
|
|
626
|
+
${theme.base.palette.interactive};
|
|
627
|
+
}
|
|
454
628
|
}
|
|
455
629
|
|
|
456
|
-
|
|
457
|
-
|
|
630
|
+
@media (pointer: coarse) {
|
|
631
|
+
--stage-chevron-width: ${chevronConfig.coarseWidth};
|
|
458
632
|
}
|
|
633
|
+
}
|
|
459
634
|
|
|
460
|
-
|
|
461
|
-
|
|
462
|
-
|
|
635
|
+
/* RTL: flip clip-paths for first and last stages */
|
|
636
|
+
[dir='rtl'] &:nth-of-type(2):not(:nth-last-of-type(2)) > ${StyledStage} {
|
|
637
|
+
${stageClipPath(true, false, true)}
|
|
638
|
+
}
|
|
463
639
|
|
|
464
|
-
|
|
465
|
-
|
|
466
|
-
|
|
467
|
-
}
|
|
640
|
+
[dir='rtl'] &:nth-last-of-type(2):not(:nth-of-type(2)) > ${StyledStage} {
|
|
641
|
+
${stageClipPath(false, true, true)}
|
|
642
|
+
}
|
|
468
643
|
|
|
469
|
-
|
|
470
|
-
|
|
471
|
-
|
|
472
|
-
|
|
473
|
-
|
|
474
|
-
|
|
644
|
+
/* Single stage: plain rectangle — no clip-path notch, inset shadows on both sides */
|
|
645
|
+
&:nth-of-type(2):nth-last-of-type(2) > ${StyledStage} {
|
|
646
|
+
--stage-chevron-width: ${chevronConfig.width};
|
|
647
|
+
clip-path: none;
|
|
648
|
+
padding-inline-start: calc(var(--chevron-spacing));
|
|
649
|
+
|
|
650
|
+
${includeHover &&
|
|
475
651
|
css `
|
|
476
|
-
&:
|
|
477
|
-
|
|
478
|
-
|
|
652
|
+
&:hover {
|
|
653
|
+
box-shadow:
|
|
654
|
+
inset calc(2 * var(--chevron-border-thickness)) 0 0 ${theme.base.palette['border-line']},
|
|
655
|
+
inset calc(-2 * var(--chevron-border-thickness)) 0 0
|
|
656
|
+
${theme.base.palette['border-line']};
|
|
479
657
|
}
|
|
480
658
|
`}
|
|
481
|
-
&:has(button:focus-visible)::before,
|
|
482
|
-
&:has(button:focus-visible)::after {
|
|
483
|
-
border-color: ${palette.interactive};
|
|
484
|
-
}
|
|
485
659
|
|
|
486
|
-
&:
|
|
487
|
-
&:
|
|
488
|
-
|
|
660
|
+
&:focus-visible,
|
|
661
|
+
&:active {
|
|
662
|
+
box-shadow:
|
|
663
|
+
inset calc(2 * var(--chevron-border-thickness)) 0 0 ${theme.base.palette.interactive},
|
|
664
|
+
inset calc(-2 * var(--chevron-border-thickness)) 0 0 ${theme.base.palette.interactive};
|
|
489
665
|
}
|
|
490
666
|
|
|
491
667
|
@media (pointer: coarse) {
|
|
492
|
-
|
|
493
|
-
|
|
494
|
-
|
|
495
|
-
width: ${chevronConfig.coarseSquareSize};
|
|
496
|
-
height: ${chevronConfig.coarseSquareSize};
|
|
497
|
-
}
|
|
668
|
+
--stage-chevron-width: ${chevronConfig.coarseWidth};
|
|
669
|
+
}
|
|
670
|
+
}
|
|
498
671
|
|
|
499
|
-
|
|
500
|
-
|
|
501
|
-
-1 * ${chevronConfig.coarseWidth} - ${chevronConfig.coarseOffsetLeft}
|
|
502
|
-
);
|
|
503
|
-
}
|
|
672
|
+
@media (pointer: coarse) {
|
|
673
|
+
margin-inline-start: calc(-1 * ${chevronConfig.coarseWidth});
|
|
504
674
|
|
|
505
|
-
|
|
506
|
-
|
|
507
|
-
|
|
508
|
-
|
|
509
|
-
}
|
|
675
|
+
&:not(:nth-of-type(-n + 2))::before,
|
|
676
|
+
&:not(:nth-last-of-type(-n + 2))::after {
|
|
677
|
+
inset-block-start: calc(50% - ${chevronConfig.coarseSquareSize} / 2);
|
|
678
|
+
width: ${chevronConfig.coarseSquareSize};
|
|
679
|
+
height: ${chevronConfig.coarseSquareSize};
|
|
680
|
+
border-inline-end-width: calc(2 * var(--chevron-border-thickness));
|
|
681
|
+
border-block-start-width: calc(2 * var(--chevron-border-thickness));
|
|
510
682
|
}
|
|
511
683
|
|
|
512
|
-
&:nth-of-type(2)
|
|
513
|
-
|
|
514
|
-
|
|
515
|
-
border-end-start-radius: ${borderRadius};
|
|
516
|
-
width: calc(100% + (2 * var(--stage-chevron-width)));
|
|
517
|
-
padding-inline-start: calc(var(--chevron-spacing));
|
|
518
|
-
${stageClipPath(false, true)}
|
|
684
|
+
&:not(:nth-of-type(-n + 2))::before {
|
|
685
|
+
inset-inline-start: ${chevronConfig.coarseNotchInsetStart};
|
|
686
|
+
}
|
|
519
687
|
|
|
520
|
-
|
|
688
|
+
&:not(:nth-last-of-type(-n + 2))::after {
|
|
689
|
+
inset-inline-end: 0;
|
|
690
|
+
}
|
|
691
|
+
}
|
|
692
|
+
`;
|
|
693
|
+
};
|
|
694
|
+
const stageContainerSegmentedStyles = (theme, readOnly) => {
|
|
695
|
+
const includeHover = !readOnly;
|
|
696
|
+
return css `
|
|
697
|
+
--segmented-edge-thickness: var(--chevron-border-thickness);
|
|
698
|
+
|
|
699
|
+
/* Segmented: stages overlap by --segmented-width so parallelogram edges meet flush */
|
|
700
|
+
margin-inline-start: calc(-1 * var(--segmented-width));
|
|
701
|
+
|
|
702
|
+
&:nth-of-type(2) {
|
|
703
|
+
margin-inline-start: 0;
|
|
704
|
+
}
|
|
705
|
+
|
|
706
|
+
/* Left segmented border strip: diagonal clip-path on each stage's inline-start edge (stages 2..N).
|
|
707
|
+
* The strip goes from (segmented-width, 0%) at top to (0%, 100%) at bottom of the pseudo,
|
|
708
|
+
* matching the parallelogram's inline-start clip edge exactly.
|
|
709
|
+
*/
|
|
710
|
+
&:not(:nth-of-type(-n + 2))::before {
|
|
711
|
+
content: '';
|
|
712
|
+
position: absolute;
|
|
713
|
+
inset-block: 0;
|
|
714
|
+
inset-inline-start: 0;
|
|
715
|
+
width: calc(var(--segmented-width) + var(--segmented-edge-thickness));
|
|
716
|
+
clip-path: polygon(
|
|
717
|
+
var(--segmented-width) 0%,
|
|
718
|
+
calc(var(--segmented-width) + var(--segmented-edge-thickness)) 0%,
|
|
719
|
+
var(--segmented-edge-thickness) 100%,
|
|
720
|
+
0% 100%
|
|
721
|
+
);
|
|
722
|
+
background: ${theme.base.palette['border-line']};
|
|
723
|
+
pointer-events: none;
|
|
724
|
+
z-index: 1;
|
|
725
|
+
}
|
|
726
|
+
|
|
727
|
+
/* Right segmented border strip: diagonal clip-path on each stage's inline-end edge (stages 1..N-1). */
|
|
728
|
+
&:not(:nth-last-of-type(-n + 2))::after {
|
|
729
|
+
content: '';
|
|
730
|
+
position: absolute;
|
|
731
|
+
inset-block: 0;
|
|
732
|
+
inset-inline-end: 0;
|
|
733
|
+
width: calc(var(--segmented-width) + var(--segmented-edge-thickness));
|
|
734
|
+
clip-path: polygon(
|
|
735
|
+
var(--segmented-width) 0%,
|
|
736
|
+
calc(var(--segmented-width) + var(--segmented-edge-thickness)) 0%,
|
|
737
|
+
var(--segmented-edge-thickness) 100%,
|
|
738
|
+
0% 100%
|
|
739
|
+
);
|
|
740
|
+
background: ${theme.base.palette['border-line']};
|
|
741
|
+
pointer-events: none;
|
|
742
|
+
z-index: 2;
|
|
743
|
+
}
|
|
744
|
+
|
|
745
|
+
/* Interactive states: update pseudo background to signal hover/focus/active */
|
|
746
|
+
${includeHover &&
|
|
521
747
|
css `
|
|
522
|
-
|
|
523
|
-
|
|
524
|
-
|
|
525
|
-
${palette['border-line']};
|
|
748
|
+
&:has(button:hover) {
|
|
749
|
+
--segmented-edge-thickness: var(--segmented-border-thickness);
|
|
750
|
+
}
|
|
526
751
|
|
|
527
|
-
|
|
528
|
-
|
|
529
|
-
|
|
530
|
-
|
|
531
|
-
|
|
532
|
-
`}
|
|
752
|
+
&:has(button:hover)::before,
|
|
753
|
+
&:has(button:hover)::after {
|
|
754
|
+
background: ${theme.base.palette['border-line']};
|
|
755
|
+
}
|
|
756
|
+
`}
|
|
533
757
|
|
|
534
|
-
|
|
535
|
-
|
|
536
|
-
|
|
758
|
+
&:has(button:focus-visible),
|
|
759
|
+
&:has(button:active) {
|
|
760
|
+
--segmented-edge-thickness: var(--segmented-border-thickness);
|
|
761
|
+
}
|
|
762
|
+
|
|
763
|
+
&:has(button:focus-visible)::before,
|
|
764
|
+
&:has(button:focus-visible)::after,
|
|
765
|
+
&:has(button:active)::before,
|
|
766
|
+
&:has(button:active)::after {
|
|
767
|
+
background: ${theme.base.palette.interactive};
|
|
768
|
+
}
|
|
769
|
+
|
|
770
|
+
/* First stage (no inline-start cut): flat left edge + inset shadow edge indicator */
|
|
771
|
+
&:nth-of-type(2):not(:nth-last-of-type(2)) > ${StyledStage} {
|
|
772
|
+
${segmentedClipPath(false, true)}
|
|
773
|
+
|
|
774
|
+
${includeHover &&
|
|
775
|
+
css `
|
|
776
|
+
&:hover {
|
|
777
|
+
box-shadow: inset var(--segmented-border-thickness) 0 0
|
|
778
|
+
${theme.base.palette['border-line']};
|
|
537
779
|
|
|
538
780
|
[dir='rtl'] & {
|
|
539
|
-
box-shadow: inset calc(-
|
|
781
|
+
box-shadow: inset calc(-1 * var(--segmented-border-thickness)) 0 0
|
|
782
|
+
${theme.base.palette['border-line']};
|
|
540
783
|
}
|
|
541
784
|
}
|
|
785
|
+
`}
|
|
786
|
+
|
|
787
|
+
&:focus-visible,
|
|
788
|
+
&:active {
|
|
789
|
+
box-shadow: inset var(--segmented-border-thickness) 0 0 ${theme.base.palette.interactive};
|
|
542
790
|
|
|
543
|
-
|
|
544
|
-
--
|
|
545
|
-
|
|
791
|
+
[dir='rtl'] & {
|
|
792
|
+
box-shadow: inset calc(-1 * var(--segmented-border-thickness)) 0 0
|
|
793
|
+
${theme.base.palette.interactive};
|
|
546
794
|
}
|
|
547
795
|
}
|
|
796
|
+
}
|
|
548
797
|
|
|
549
|
-
|
|
550
|
-
|
|
551
|
-
|
|
552
|
-
border-end-end-radius: ${borderRadius};
|
|
553
|
-
padding-inline-end: 0;
|
|
554
|
-
width: 100%;
|
|
555
|
-
${stageClipPath(true, false)}
|
|
798
|
+
/* Last stage (no inline-end cut): flat right edge + inset shadow edge indicator */
|
|
799
|
+
&:nth-last-of-type(2):not(:nth-of-type(2)) > ${StyledStage} {
|
|
800
|
+
${segmentedClipPath(true, false)}
|
|
556
801
|
|
|
557
|
-
|
|
802
|
+
${includeHover &&
|
|
558
803
|
css `
|
|
559
|
-
|
|
560
|
-
|
|
561
|
-
|
|
562
|
-
${palette['border-line']};
|
|
804
|
+
&:hover {
|
|
805
|
+
box-shadow: inset calc(-1 * var(--segmented-border-thickness)) 0 0
|
|
806
|
+
${theme.base.palette['border-line']};
|
|
563
807
|
|
|
564
|
-
|
|
565
|
-
|
|
566
|
-
|
|
567
|
-
}
|
|
808
|
+
[dir='rtl'] & {
|
|
809
|
+
box-shadow: inset var(--segmented-border-thickness) 0 0
|
|
810
|
+
${theme.base.palette['border-line']};
|
|
568
811
|
}
|
|
569
|
-
|
|
812
|
+
}
|
|
813
|
+
`}
|
|
570
814
|
|
|
571
|
-
|
|
572
|
-
|
|
573
|
-
|
|
815
|
+
&:focus-visible,
|
|
816
|
+
&:active {
|
|
817
|
+
box-shadow: inset calc(-1 * var(--segmented-border-thickness)) 0 0
|
|
818
|
+
${theme.base.palette.interactive};
|
|
574
819
|
|
|
575
|
-
|
|
576
|
-
|
|
577
|
-
}
|
|
820
|
+
[dir='rtl'] & {
|
|
821
|
+
box-shadow: inset var(--segmented-border-thickness) 0 0 ${theme.base.palette.interactive};
|
|
578
822
|
}
|
|
823
|
+
}
|
|
824
|
+
}
|
|
825
|
+
|
|
826
|
+
/* RTL: flip clip-paths for first and last stage buttons */
|
|
827
|
+
[dir='rtl'] &:nth-of-type(2):not(:nth-last-of-type(2)) > ${StyledStage} {
|
|
828
|
+
${segmentedClipPath(true, false, true)}
|
|
829
|
+
}
|
|
830
|
+
|
|
831
|
+
[dir='rtl'] &:nth-last-of-type(2):not(:nth-of-type(2)) > ${StyledStage} {
|
|
832
|
+
${segmentedClipPath(false, true, true)}
|
|
833
|
+
}
|
|
834
|
+
|
|
835
|
+
/* Single stage: plain rectangle — no diagonal cuts, inset shadows on both sides */
|
|
836
|
+
&:nth-of-type(2):nth-last-of-type(2) > ${StyledStage} {
|
|
837
|
+
clip-path: none;
|
|
838
|
+
padding-inline-start: calc(var(--chevron-spacing));
|
|
839
|
+
padding-inline-end: calc(var(--chevron-spacing));
|
|
840
|
+
|
|
841
|
+
${includeHover &&
|
|
842
|
+
css `
|
|
843
|
+
&:hover {
|
|
844
|
+
box-shadow:
|
|
845
|
+
inset var(--segmented-border-thickness) 0 0 ${theme.base.palette['border-line']},
|
|
846
|
+
inset calc(-1 * var(--segmented-border-thickness)) 0 0
|
|
847
|
+
${theme.base.palette['border-line']};
|
|
848
|
+
}
|
|
849
|
+
`}
|
|
850
|
+
|
|
851
|
+
&:focus-visible,
|
|
852
|
+
&:active {
|
|
853
|
+
box-shadow:
|
|
854
|
+
inset var(--segmented-border-thickness) 0 0 ${theme.base.palette.interactive},
|
|
855
|
+
inset calc(-1 * var(--segmented-border-thickness)) 0 0 ${theme.base.palette.interactive};
|
|
856
|
+
}
|
|
857
|
+
}
|
|
858
|
+
|
|
859
|
+
/* RTL: mirror the pseudo clip-paths.
|
|
860
|
+
* In LTR the strip goes top-right → bottom-left (polygon A 0%, A+B 0%, B 100%, 0% 100%).
|
|
861
|
+
* In RTL the pseudo is positioned at the opposite physical edge via logical inset properties,
|
|
862
|
+
* so the strip must go top-left → bottom-right to stay aligned with the flipped slant.
|
|
863
|
+
*/
|
|
864
|
+
[dir='rtl'] &:not(:nth-of-type(-n + 2))::before,
|
|
865
|
+
[dir='rtl'] &:not(:nth-last-of-type(-n + 2))::after {
|
|
866
|
+
clip-path: polygon(
|
|
867
|
+
0% 0%,
|
|
868
|
+
var(--segmented-edge-thickness) 0%,
|
|
869
|
+
calc(var(--segmented-width) + var(--segmented-edge-thickness)) 100%,
|
|
870
|
+
var(--segmented-width) 100%
|
|
871
|
+
);
|
|
872
|
+
}
|
|
873
|
+
|
|
874
|
+
@media (pointer: coarse) {
|
|
875
|
+
/* A single CSS custom property update propagates to all margin and clip-path consumers */
|
|
876
|
+
--segmented-width: ${segmentedConfig.coarseWidth};
|
|
877
|
+
}
|
|
878
|
+
`;
|
|
879
|
+
};
|
|
880
|
+
const stageContainerVariants = {
|
|
881
|
+
chevron: stageContainerChevronStyles,
|
|
882
|
+
segmented: stageContainerSegmentedStyles,
|
|
883
|
+
milestone: () => css ``
|
|
884
|
+
};
|
|
885
|
+
/**
|
|
886
|
+
* `<li>` container for a single stage item. Manages negative-margin chevron overlap,
|
|
887
|
+
* pseudo-element positioning, and z-index stacking for interactive states.
|
|
888
|
+
*/
|
|
889
|
+
export const StyledStageContainer = styled.li(({ theme, theme: { components: { card: { 'border-radius': borderRadius } } }, readOnly, variant: shape }) => {
|
|
890
|
+
return css `
|
|
891
|
+
display: flex;
|
|
892
|
+
position: relative;
|
|
893
|
+
|
|
894
|
+
/* Resting z-index: for same-z siblings, DOM order determines paint order.
|
|
895
|
+
* All non-last <li>s have z-index:1 so the later (right) <li>'s ::before paints on top
|
|
896
|
+
* at internal boundaries; the last <li> has no z-index so its left neighbor's ::after
|
|
897
|
+
* wins at the final boundary. On hover/focus/active, the interacting <li> gains z:2/3
|
|
898
|
+
* and its own pseudo-element surfaces for that boundary, regardless of which side.
|
|
899
|
+
*/
|
|
900
|
+
&:not(:nth-last-of-type(-n + 2)) {
|
|
901
|
+
z-index: 1;
|
|
902
|
+
}
|
|
579
903
|
|
|
580
|
-
|
|
581
|
-
|
|
904
|
+
&:has(button:focus-visible),
|
|
905
|
+
&:has(button:active) {
|
|
906
|
+
z-index: 2;
|
|
907
|
+
}
|
|
908
|
+
|
|
909
|
+
${!readOnly &&
|
|
910
|
+
css `
|
|
911
|
+
&:has(button:hover) {
|
|
912
|
+
z-index: 3;
|
|
582
913
|
}
|
|
914
|
+
`}
|
|
915
|
+
|
|
916
|
+
/* Corner radii are shared across all shape variants */
|
|
917
|
+
&:nth-of-type(2):not(:nth-last-of-type(2)) > ${StyledStage} {
|
|
918
|
+
border-start-start-radius: ${borderRadius};
|
|
919
|
+
border-end-start-radius: ${borderRadius};
|
|
583
920
|
}
|
|
584
921
|
|
|
585
|
-
|
|
586
|
-
${
|
|
922
|
+
&:nth-last-of-type(2):not(:nth-of-type(2)) > ${StyledStage} {
|
|
923
|
+
border-start-end-radius: ${borderRadius};
|
|
924
|
+
border-end-end-radius: ${borderRadius};
|
|
587
925
|
}
|
|
588
926
|
|
|
589
|
-
|
|
590
|
-
${
|
|
927
|
+
&:nth-of-type(2):nth-last-of-type(2) > ${StyledStage} {
|
|
928
|
+
border-radius: ${borderRadius};
|
|
929
|
+
width: 100%;
|
|
591
930
|
}
|
|
931
|
+
|
|
932
|
+
${stageContainerVariants[shape](theme, readOnly)}
|
|
592
933
|
`;
|
|
593
934
|
});
|
|
594
935
|
StyledStageContainer.defaultProps = defaultThemeProp;
|
|
@@ -651,6 +992,195 @@ export const StyledStageGlimpse = styled.div(({ theme }) => {
|
|
|
651
992
|
`;
|
|
652
993
|
});
|
|
653
994
|
StyledStageGlimpse.defaultProps = defaultThemeProp;
|
|
995
|
+
const milestonePulse = keyframes `
|
|
996
|
+
0%, 100% {
|
|
997
|
+
box-shadow: 0 0 0 var(--milestone-pulse-min) var(--milestone-pulse-start);
|
|
998
|
+
}
|
|
999
|
+
60% {
|
|
1000
|
+
box-shadow: 0 0 0 var(--milestone-pulse-spread) var(--milestone-pulse-end);
|
|
1001
|
+
}
|
|
1002
|
+
`;
|
|
1003
|
+
export const StyledMilestoneLabel = styled.span(({ theme }) => {
|
|
1004
|
+
return css `
|
|
1005
|
+
color: ${theme.base.palette['foreground-color']};
|
|
1006
|
+
line-height: ${theme.base['line-height']};
|
|
1007
|
+
text-align: center;
|
|
1008
|
+
align-self: stretch;
|
|
1009
|
+
overflow-wrap: break-word;
|
|
1010
|
+
padding-inline: calc(0.25 * ${theme.base.spacing});
|
|
1011
|
+
`;
|
|
1012
|
+
});
|
|
1013
|
+
StyledMilestoneLabel.defaultProps = defaultThemeProp;
|
|
1014
|
+
/**
|
|
1015
|
+
* `<li>` container for a single stage item in the 'milestone' shape variant.
|
|
1016
|
+
* Renders column-flex layout (milestone above, label below) and draws the
|
|
1017
|
+
* horizontal connector as a single line from this milestone's centre to the next
|
|
1018
|
+
* milestone's centre (::after), sized so every connector has an identical length.
|
|
1019
|
+
*/
|
|
1020
|
+
export const StyledMilestoneStageContainer = styled.li(({ theme, nextCompleted, status }) => {
|
|
1021
|
+
const { base: { palette: { interactive, 'border-line': borderLine }, spacing } } = theme;
|
|
1022
|
+
const fontSize = calculateFontSize(theme.base['font-size'], theme.base['font-scale']);
|
|
1023
|
+
const connectorFilled = nextCompleted;
|
|
1024
|
+
return css `
|
|
1025
|
+
--connector-height: ${connectorFilled ? '0.25rem' : '0.125rem'};
|
|
1026
|
+
--connector-display: block;
|
|
1027
|
+
--connector-start: 50%;
|
|
1028
|
+
--connector-width: 100%;
|
|
1029
|
+
--connector-bg: ${connectorFilled ? interactive : borderLine};
|
|
1030
|
+
--connector-forced-bg: ${connectorFilled ? 'Highlight' : 'CanvasText'};
|
|
1031
|
+
display: flex;
|
|
1032
|
+
flex-direction: column;
|
|
1033
|
+
align-items: center;
|
|
1034
|
+
flex: 1 0 0;
|
|
1035
|
+
font-size: ${fontSize.xs};
|
|
1036
|
+
font-weight: ${status === 'current'
|
|
1037
|
+
? theme.base['font-weight']['semi-bold']
|
|
1038
|
+
: theme.base['font-weight'].normal};
|
|
1039
|
+
min-width: 15ch;
|
|
1040
|
+
position: relative;
|
|
1041
|
+
gap: ${spacing};
|
|
1042
|
+
z-index: 1;
|
|
1043
|
+
|
|
1044
|
+
&:nth-of-type(2):not(:nth-last-of-type(2)) {
|
|
1045
|
+
--connector-start: calc(var(--milestone-size) / 2);
|
|
1046
|
+
--connector-width: calc(200% - var(--milestone-size));
|
|
1047
|
+
align-items: flex-start;
|
|
1048
|
+
flex: 0.5 0 calc(var(--milestone-size) / 2);
|
|
1049
|
+
min-width: calc(7.5ch + var(--milestone-size) / 2);
|
|
1050
|
+
|
|
1051
|
+
${StyledMilestoneLabel} {
|
|
1052
|
+
text-align: start;
|
|
1053
|
+
}
|
|
1054
|
+
}
|
|
1055
|
+
|
|
1056
|
+
&:nth-last-of-type(2):not(:nth-of-type(2)) {
|
|
1057
|
+
--connector-display: none;
|
|
1058
|
+
align-items: flex-end;
|
|
1059
|
+
flex: 0.5 0 calc(var(--milestone-size) / 2);
|
|
1060
|
+
min-width: calc(7.5ch + var(--milestone-size) / 2);
|
|
1061
|
+
|
|
1062
|
+
${StyledMilestoneLabel} {
|
|
1063
|
+
text-align: end;
|
|
1064
|
+
}
|
|
1065
|
+
}
|
|
1066
|
+
|
|
1067
|
+
&:nth-of-type(2):nth-last-of-type(2) {
|
|
1068
|
+
--connector-display: none;
|
|
1069
|
+
align-items: center;
|
|
1070
|
+
flex: 1 0 0;
|
|
1071
|
+
}
|
|
1072
|
+
|
|
1073
|
+
&::after {
|
|
1074
|
+
content: '';
|
|
1075
|
+
display: var(--connector-display);
|
|
1076
|
+
position: absolute;
|
|
1077
|
+
inset-block-start: calc(var(--milestone-size) / 2 - var(--connector-height) / 2);
|
|
1078
|
+
inset-inline-start: var(--connector-start);
|
|
1079
|
+
width: var(--connector-width);
|
|
1080
|
+
height: var(--connector-height);
|
|
1081
|
+
background: var(--connector-bg);
|
|
1082
|
+
pointer-events: none;
|
|
1083
|
+
|
|
1084
|
+
@media (forced-colors: active) {
|
|
1085
|
+
background: var(--connector-forced-bg);
|
|
1086
|
+
}
|
|
1087
|
+
}
|
|
1088
|
+
`;
|
|
1089
|
+
});
|
|
1090
|
+
StyledMilestoneStageContainer.defaultProps = defaultThemeProp;
|
|
1091
|
+
export const StyledMilestoneButton = styled.button(({ theme, status, readOnly }) => {
|
|
1092
|
+
const { base: { 'hit-area': hitArea, animation: { speed: animationSpeed, timing: { ease: animationTiming } }, shadow: { focus: focusShadow } }, components: { button: { 'border-width': borderWidth }, 'case-view': { stages } } } = theme;
|
|
1093
|
+
const stageForeground = calculateForegroundColor(stages.status[status].background, stages.status[status]['foreground-color']);
|
|
1094
|
+
const fontSize = calculateFontSize(theme.base['font-size'], theme.base['font-scale']);
|
|
1095
|
+
const completedBorderColor = status === 'completed'
|
|
1096
|
+
? tryCatch(() => darken(0.12, stages.status.completed.background), () => 'transparent')
|
|
1097
|
+
: '';
|
|
1098
|
+
return css `
|
|
1099
|
+
position: relative;
|
|
1100
|
+
z-index: 1;
|
|
1101
|
+
display: flex;
|
|
1102
|
+
align-items: center;
|
|
1103
|
+
justify-content: center;
|
|
1104
|
+
flex-shrink: 0;
|
|
1105
|
+
border-radius: 50%;
|
|
1106
|
+
width: var(--milestone-size);
|
|
1107
|
+
height: var(--milestone-size);
|
|
1108
|
+
background: ${stages.status[status].background};
|
|
1109
|
+
color: ${stageForeground};
|
|
1110
|
+
font-size: ${fontSize.s};
|
|
1111
|
+
font-weight: ${status === 'current'
|
|
1112
|
+
? theme.base['font-weight']['semi-bold']
|
|
1113
|
+
: theme.base['font-weight'].normal};
|
|
1114
|
+
outline: none;
|
|
1115
|
+
border: none;
|
|
1116
|
+
cursor: ${readOnly ? 'default' : 'pointer'};
|
|
1117
|
+
transition: box-shadow calc(2 * ${animationSpeed}) ${animationTiming};
|
|
1118
|
+
|
|
1119
|
+
${status === 'completed' &&
|
|
1120
|
+
css `
|
|
1121
|
+
box-shadow: inset 0 0 0 calc(2 * ${borderWidth}) ${completedBorderColor};
|
|
1122
|
+
`}
|
|
1123
|
+
|
|
1124
|
+
&:focus-visible {
|
|
1125
|
+
box-shadow: ${focusShadow};
|
|
1126
|
+
|
|
1127
|
+
@media (forced-colors: active) {
|
|
1128
|
+
outline: 0.125rem solid Highlight;
|
|
1129
|
+
outline-offset: 0.125rem;
|
|
1130
|
+
}
|
|
1131
|
+
}
|
|
1132
|
+
|
|
1133
|
+
${!readOnly &&
|
|
1134
|
+
css `
|
|
1135
|
+
&:hover {
|
|
1136
|
+
filter: brightness(0.85);
|
|
1137
|
+
}
|
|
1138
|
+
|
|
1139
|
+
&:active {
|
|
1140
|
+
filter: brightness(0.85);
|
|
1141
|
+
}
|
|
1142
|
+
`}
|
|
1143
|
+
|
|
1144
|
+
${status === 'current' &&
|
|
1145
|
+
!readOnly &&
|
|
1146
|
+
css `
|
|
1147
|
+
&::before {
|
|
1148
|
+
content: '';
|
|
1149
|
+
position: absolute;
|
|
1150
|
+
inset: 0;
|
|
1151
|
+
border-radius: 50%;
|
|
1152
|
+
pointer-events: none;
|
|
1153
|
+
animation: ${milestonePulse} 2s ease-out infinite;
|
|
1154
|
+
|
|
1155
|
+
@media (prefers-reduced-motion: reduce) {
|
|
1156
|
+
animation: none;
|
|
1157
|
+
}
|
|
1158
|
+
}
|
|
1159
|
+
`}
|
|
1160
|
+
|
|
1161
|
+
/* Expanded hit area */
|
|
1162
|
+
&::after {
|
|
1163
|
+
content: '';
|
|
1164
|
+
position: absolute;
|
|
1165
|
+
width: ${hitArea['mouse-min']};
|
|
1166
|
+
height: ${hitArea['mouse-min']};
|
|
1167
|
+
inset-block-start: calc((${hitArea['mouse-min']} - var(--milestone-size)) / -2);
|
|
1168
|
+
inset-inline-start: calc((${hitArea['mouse-min']} - var(--milestone-size)) / -2);
|
|
1169
|
+
|
|
1170
|
+
@media (pointer: coarse) {
|
|
1171
|
+
width: ${hitArea['finger-min']};
|
|
1172
|
+
height: ${hitArea['finger-min']};
|
|
1173
|
+
inset-block-start: calc((${hitArea['finger-min']} - var(--milestone-size)) / -2);
|
|
1174
|
+
inset-inline-start: calc((${hitArea['finger-min']} - var(--milestone-size)) / -2);
|
|
1175
|
+
}
|
|
1176
|
+
}
|
|
1177
|
+
|
|
1178
|
+
@media (forced-colors: active) {
|
|
1179
|
+
border: 0.125rem solid ButtonText;
|
|
1180
|
+
}
|
|
1181
|
+
`;
|
|
1182
|
+
});
|
|
1183
|
+
StyledMilestoneButton.defaultProps = defaultThemeProp;
|
|
654
1184
|
/**
|
|
655
1185
|
* Visually hidden `<p>` providing an accessible description for the stages list,
|
|
656
1186
|
* announced by screen readers but not displayed on screen.
|