@pega/cosmos-react-work 9.12.0 → 9.14.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/Details/Details.d.ts.map +1 -1
- package/lib/components/Details/Details.js +8 -3
- package/lib/components/Details/Details.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/GenAICoach.types.d.ts +2 -0
- package/lib/components/GenAICoach/GenAICoach.types.d.ts.map +1 -1
- package/lib/components/GenAICoach/GenAICoach.types.js.map +1 -1
- package/lib/components/GenAICoach/GenAIMessage.d.ts.map +1 -1
- package/lib/components/GenAICoach/GenAIMessage.js +4 -4
- package/lib/components/GenAICoach/GenAIMessage.js.map +1 -1
- package/lib/components/Stages/Stages.d.ts.map +1 -1
- package/lib/components/Stages/Stages.js +55 -36
- package/lib/components/Stages/Stages.js.map +1 -1
- package/lib/components/Stages/Stages.styles.d.ts +25 -3
- package/lib/components/Stages/Stages.styles.d.ts.map +1 -1
- package/lib/components/Stages/Stages.styles.js +594 -212
- 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/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 = {
|
|
@@ -137,14 +151,6 @@ export const StyledStagesWrapper = styled.div(({ theme }) => {
|
|
|
137
151
|
--stages-wrapper-bottom-radius,
|
|
138
152
|
${theme.components.card['border-radius']}
|
|
139
153
|
);
|
|
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
154
|
mask-image: linear-gradient(black, black),
|
|
149
155
|
linear-gradient(
|
|
150
156
|
to right,
|
|
@@ -162,14 +168,6 @@ export const StyledStagesWrapper = styled.div(({ theme }) => {
|
|
|
162
168
|
mask-repeat: no-repeat, no-repeat;
|
|
163
169
|
|
|
164
170
|
[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
171
|
mask-image: linear-gradient(black, black),
|
|
174
172
|
linear-gradient(
|
|
175
173
|
to right,
|
|
@@ -186,13 +184,6 @@ export const StyledStagesWrapper = styled.div(({ theme }) => {
|
|
|
186
184
|
|
|
187
185
|
@media (pointer: coarse) {
|
|
188
186
|
--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
187
|
mask-image: linear-gradient(
|
|
197
188
|
to right,
|
|
198
189
|
transparent calc(-1 * var(--mask-edge-overhang)),
|
|
@@ -205,13 +196,6 @@ export const StyledStagesWrapper = styled.div(({ theme }) => {
|
|
|
205
196
|
mask-repeat: no-repeat;
|
|
206
197
|
|
|
207
198
|
[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
199
|
mask-image: linear-gradient(
|
|
216
200
|
to right,
|
|
217
201
|
transparent calc(-1 * var(--mask-edge-overhang)),
|
|
@@ -225,14 +209,17 @@ export const StyledStagesWrapper = styled.div(({ theme }) => {
|
|
|
225
209
|
});
|
|
226
210
|
StyledStagesWrapper.defaultProps = defaultThemeProp;
|
|
227
211
|
/**
|
|
228
|
-
* Scrollable `<ol>` containing all stage chevron items. Sets the `--chevron-spacing
|
|
229
|
-
* and `--
|
|
212
|
+
* Scrollable `<ol>` containing all stage chevron items. Sets the `--chevron-spacing`,
|
|
213
|
+
* `--chevron-border-thickness`, and `--segmented-border-thickness` custom properties
|
|
214
|
+
* consumed by child elements.
|
|
230
215
|
*/
|
|
231
|
-
export const StyledStages = styled.ol(({ theme }) => {
|
|
216
|
+
export const StyledStages = styled.ol(({ theme, variant }) => {
|
|
217
|
+
const isMilestone = variant === 'milestone';
|
|
232
218
|
return css `
|
|
233
219
|
--chevron-spacing: ${theme.base.spacing};
|
|
234
220
|
--chevron-border-thickness: ${theme.components.button['border-width']};
|
|
235
|
-
|
|
221
|
+
--segmented-border-thickness: calc(2 * ${theme.components.button['border-width']});
|
|
222
|
+
--segmented-width: ${segmentedConfig.width};
|
|
236
223
|
border-radius: ${theme.components.card['border-radius']};
|
|
237
224
|
display: flex;
|
|
238
225
|
padding: 0;
|
|
@@ -243,6 +230,17 @@ export const StyledStages = styled.ol(({ theme }) => {
|
|
|
243
230
|
scrollbar-width: thin;
|
|
244
231
|
scrollbar-color: transparent transparent;
|
|
245
232
|
|
|
233
|
+
${isMilestone &&
|
|
234
|
+
css `
|
|
235
|
+
--milestone-size: calc(4 * ${theme.base.spacing});
|
|
236
|
+
--milestone-pulse-min: calc(var(--milestone-size) * 0.1);
|
|
237
|
+
--milestone-pulse-start: ${transparentize(0.5, theme.base.palette.interactive)};
|
|
238
|
+
--milestone-pulse-spread: calc(var(--milestone-size) * 0.25);
|
|
239
|
+
--milestone-pulse-end: ${transparentize(0.75, theme.base.palette.interactive)};
|
|
240
|
+
padding-block: ${theme.base.spacing};
|
|
241
|
+
padding-inline: calc(var(--milestone-size) * 0.25);
|
|
242
|
+
`}
|
|
243
|
+
|
|
246
244
|
&:hover,
|
|
247
245
|
&:focus-within {
|
|
248
246
|
scrollbar-color: var(
|
|
@@ -330,11 +328,58 @@ export const StyledInnerStage = styled.span(({ theme, ellipsis }) => {
|
|
|
330
328
|
`;
|
|
331
329
|
});
|
|
332
330
|
StyledInnerStage.defaultProps = defaultThemeProp;
|
|
331
|
+
const stageButtonChevronStyles = (theme) => css `
|
|
332
|
+
padding-inline-start: calc(2 * var(--chevron-spacing));
|
|
333
|
+
padding-inline-end: var(--chevron-spacing);
|
|
334
|
+
width: calc(100% + ${chevronConfig.width});
|
|
335
|
+
--stage-chevron-width: ${chevronConfig.width};
|
|
336
|
+
|
|
337
|
+
${StyledInnerStage} {
|
|
338
|
+
transform: translateX(calc(-0.25 * var(--chevron-spacing)));
|
|
339
|
+
opacity: ${theme.base.transparency['transparent-2']};
|
|
340
|
+
}
|
|
341
|
+
|
|
342
|
+
${stageClipPath(true, true)}
|
|
343
|
+
|
|
344
|
+
[dir='rtl'] & ${StyledInnerStage} {
|
|
345
|
+
transform: translateX(calc(0.25 * var(--chevron-spacing)));
|
|
346
|
+
}
|
|
347
|
+
|
|
348
|
+
[dir='rtl'] & {
|
|
349
|
+
${stageClipPath(true, true, true)}
|
|
350
|
+
}
|
|
351
|
+
|
|
352
|
+
@media (pointer: coarse) {
|
|
353
|
+
padding-inline-start: calc(2.25 * var(--chevron-spacing));
|
|
354
|
+
width: calc(100% + ${chevronConfig.coarseWidth});
|
|
355
|
+
--stage-chevron-width: ${chevronConfig.coarseWidth};
|
|
356
|
+
}
|
|
357
|
+
`;
|
|
358
|
+
const stageButtonSegmentedStyles = (theme) => css `
|
|
359
|
+
width: 100%;
|
|
360
|
+
padding-inline-start: calc(var(--segmented-width) + var(--chevron-spacing));
|
|
361
|
+
padding-inline-end: calc(var(--segmented-width) + var(--chevron-spacing));
|
|
362
|
+
|
|
363
|
+
${StyledInnerStage} {
|
|
364
|
+
opacity: ${theme.base.transparency['transparent-2']};
|
|
365
|
+
}
|
|
366
|
+
|
|
367
|
+
${segmentedClipPath(true, true)}
|
|
368
|
+
|
|
369
|
+
[dir='rtl'] & {
|
|
370
|
+
${segmentedClipPath(true, true, true)}
|
|
371
|
+
}
|
|
372
|
+
`;
|
|
373
|
+
const stageButtonVariants = {
|
|
374
|
+
chevron: stageButtonChevronStyles,
|
|
375
|
+
segmented: stageButtonSegmentedStyles,
|
|
376
|
+
milestone: () => css ``
|
|
377
|
+
};
|
|
333
378
|
/**
|
|
334
379
|
* Clickable `<button>` for a single stage. Renders the chevron clip-path shape and
|
|
335
380
|
* applies status-based background and foreground colours.
|
|
336
381
|
*/
|
|
337
|
-
export const StyledStage = styled.button(({ theme: { base: { palette, 'hit-area': hitArea, transparency, 'font-weight': fontWeight }, components: { 'case-view': { stages } } }, status, readOnly }) => {
|
|
382
|
+
export const StyledStage = styled.button(({ theme, theme: { base: { palette, 'hit-area': hitArea, transparency, 'font-weight': fontWeight }, components: { 'case-view': { stages } } }, status, readOnly, variant: shape }) => {
|
|
338
383
|
const stageForeground = calculateForegroundColor(stages.status[status].background, stages.status[status]['foreground-color']);
|
|
339
384
|
return css `
|
|
340
385
|
background: ${stages.status[status].background};
|
|
@@ -349,26 +394,10 @@ export const StyledStage = styled.button(({ theme: { base: { palette, 'hit-area'
|
|
|
349
394
|
* Adding 0.0625rem (1px at default font size) to min-height compensates so the button fills its <li> container,
|
|
350
395
|
* keeping the clipped chevron background flush with the top and bottom borders. */
|
|
351
396
|
min-height: calc(5 * var(--chevron-spacing) + 0.0625rem);
|
|
352
|
-
padding-inline-start: calc(2 * var(--chevron-spacing));
|
|
353
|
-
padding-inline-end: var(--chevron-spacing);
|
|
354
397
|
margin-inline-start: 0;
|
|
355
398
|
margin-inline-end: 0;
|
|
356
|
-
width: calc(100% + ${chevronConfig.width});
|
|
357
|
-
--stage-chevron-width: ${chevronConfig.width};
|
|
358
|
-
|
|
359
|
-
${StyledInnerStage} {
|
|
360
|
-
transform: translateX(calc(-0.25 * var(--chevron-spacing)));
|
|
361
|
-
opacity: ${transparency['transparent-2']};
|
|
362
|
-
}
|
|
363
|
-
${stageClipPath(true, true)}
|
|
364
|
-
|
|
365
|
-
[dir='rtl'] & ${StyledInnerStage} {
|
|
366
|
-
transform: translateX(calc(0.25 * var(--chevron-spacing)));
|
|
367
|
-
}
|
|
368
399
|
|
|
369
|
-
[
|
|
370
|
-
${stageClipPath(true, true, true)}
|
|
371
|
-
}
|
|
400
|
+
${stageButtonVariants[shape](theme)}
|
|
372
401
|
|
|
373
402
|
${!readOnly &&
|
|
374
403
|
css `
|
|
@@ -407,9 +436,6 @@ export const StyledStage = styled.button(({ theme: { base: { palette, 'hit-area'
|
|
|
407
436
|
|
|
408
437
|
@media (pointer: coarse) {
|
|
409
438
|
min-height: ${hitArea['finger-min']};
|
|
410
|
-
padding-inline-start: calc(2.25 * var(--chevron-spacing));
|
|
411
|
-
width: calc(100% + ${chevronConfig.coarseWidth});
|
|
412
|
-
--stage-chevron-width: ${chevronConfig.coarseWidth};
|
|
413
439
|
}
|
|
414
440
|
`;
|
|
415
441
|
});
|
|
@@ -431,217 +457,384 @@ export const StyledStageText = styled(Text)(({ theme, isCurrent }) => css `
|
|
|
431
457
|
font-weight: ${isCurrent ? theme.base['font-weight'].bold : theme.base['font-weight'].normal};
|
|
432
458
|
`);
|
|
433
459
|
StyledStageText.defaultProps = defaultThemeProp;
|
|
434
|
-
|
|
435
|
-
|
|
436
|
-
* pseudo-element positioning, and z-index stacking for interactive states.
|
|
437
|
-
*/
|
|
438
|
-
export const StyledStageContainer = styled.li(({ theme: { base: { palette }, components: { card: { 'border-radius': borderRadius } } }, readOnly }) => {
|
|
460
|
+
const stageContainerChevronStyles = (theme, readOnly) => {
|
|
461
|
+
const includeHover = !readOnly;
|
|
439
462
|
return css `
|
|
440
|
-
|
|
441
|
-
|
|
442
|
-
margin-inline-start: calc(-1 * ${chevronConfig.width});
|
|
463
|
+
/* Chevron: negative-margin overlap so consecutive stages share a boundary */
|
|
464
|
+
margin-inline-start: calc(-1 * ${chevronConfig.width});
|
|
443
465
|
|
|
444
|
-
|
|
445
|
-
|
|
446
|
-
|
|
466
|
+
&:nth-of-type(2) {
|
|
467
|
+
margin-inline-start: 0;
|
|
468
|
+
}
|
|
447
469
|
|
|
448
|
-
|
|
449
|
-
|
|
450
|
-
|
|
451
|
-
|
|
452
|
-
*
|
|
470
|
+
/* Chevron boundary indicators via ::before (left notch) and ::after (right point) pseudo-elements */
|
|
471
|
+
&:not(:nth-of-type(-n + 2))::before {
|
|
472
|
+
${createChevronPseudo('calc(2 * var(--chevron-border-thickness))', theme.base.palette['border-line'], chevronConfig.squareSize)}
|
|
473
|
+
/* Elevate ::before above the button so it renders via the same pathway as ::after.
|
|
474
|
+
* Without z-index, ::before (first in DOM) is painted first and then covered by the
|
|
475
|
+
* button, making it only partially visible through the clip-path notch window. This
|
|
476
|
+
* causes thicker interactive-state borders (3×) to look thinner on the left boundary
|
|
477
|
+
* than on the right (::after, which paints last and is always fully visible).
|
|
478
|
+
* The ::before tip's rightmost extent is at --stage-chevron-width from the <li> start,
|
|
479
|
+
* which is before the stage text (padding-inline-start: 2 × spacing), so no content overlap.
|
|
453
480
|
*/
|
|
454
|
-
|
|
455
|
-
|
|
456
|
-
}
|
|
481
|
+
z-index: 1;
|
|
482
|
+
}
|
|
457
483
|
|
|
458
|
-
|
|
459
|
-
|
|
460
|
-
|
|
484
|
+
&:not(:nth-last-of-type(-n + 2))::after {
|
|
485
|
+
${createChevronPseudo('calc(2 * var(--chevron-border-thickness))', theme.base.palette['border-line'], chevronConfig.squareSize)}
|
|
486
|
+
}
|
|
487
|
+
|
|
488
|
+
[dir='rtl'] &::before,
|
|
489
|
+
[dir='rtl'] &::after {
|
|
490
|
+
transform: rotateZ(-45deg) skew(-15deg, -15deg);
|
|
491
|
+
}
|
|
492
|
+
|
|
493
|
+
/* Chevron positioning: 45° rotated squares create visual tips via offsets:
|
|
494
|
+
* left ≈ 0.86 × spacing, right ≈ 1.445 × spacing (accounts for skew correction)
|
|
495
|
+
*/
|
|
496
|
+
${createChevronBaseStyles(chevronConfig, 'var(--chevron-border-thickness)')}
|
|
497
|
+
${createChevronInteractiveStates(chevronConfig, 'var(--chevron-border-thickness)', includeHover)}
|
|
498
|
+
|
|
499
|
+
/* Thicken chevrons to visually match button top/bottom border on any colored state.
|
|
500
|
+
* At 45° rotation, border appears 1/sin(45°) ≈ 0.707× thinner, so 2× border ≈ 1.4× horizontal border weight.
|
|
501
|
+
*/
|
|
502
|
+
${includeHover &&
|
|
503
|
+
css `
|
|
504
|
+
&:has(button:hover)::before,
|
|
505
|
+
&:has(button:hover)::after {
|
|
506
|
+
border-color: ${theme.base.palette['border-line']};
|
|
461
507
|
}
|
|
508
|
+
`}
|
|
462
509
|
|
|
463
|
-
|
|
510
|
+
&:has(button:focus-visible)::before,
|
|
511
|
+
&:has(button:focus-visible)::after {
|
|
512
|
+
border-color: ${theme.base.palette.interactive};
|
|
513
|
+
}
|
|
514
|
+
|
|
515
|
+
&:has(button:active)::before,
|
|
516
|
+
&:has(button:active)::after {
|
|
517
|
+
border-color: ${theme.base.palette.interactive};
|
|
518
|
+
}
|
|
519
|
+
|
|
520
|
+
/* First stage: no left notch, extended width to cover the full left edge */
|
|
521
|
+
&:nth-of-type(2) > ${StyledStage} {
|
|
522
|
+
--stage-chevron-width: ${chevronConfig.width};
|
|
523
|
+
width: calc(100% + (2 * var(--stage-chevron-width)));
|
|
524
|
+
padding-inline-start: calc(var(--chevron-spacing));
|
|
525
|
+
${stageClipPath(false, true)}
|
|
526
|
+
|
|
527
|
+
${includeHover &&
|
|
464
528
|
css `
|
|
465
|
-
|
|
466
|
-
|
|
529
|
+
/* Inline-start interactive indicator via inset shadow — avoids border-color bleeding through gradient backgrounds */
|
|
530
|
+
&:hover {
|
|
531
|
+
box-shadow: inset calc(2 * var(--chevron-border-thickness)) 0 0
|
|
532
|
+
${theme.base.palette['border-line']};
|
|
533
|
+
|
|
534
|
+
[dir='rtl'] & {
|
|
535
|
+
box-shadow: inset calc(-2 * var(--chevron-border-thickness)) 0 0
|
|
536
|
+
${theme.base.palette['border-line']};
|
|
537
|
+
}
|
|
467
538
|
}
|
|
468
539
|
`}
|
|
469
540
|
|
|
470
|
-
|
|
471
|
-
|
|
472
|
-
|
|
541
|
+
&:focus-visible,
|
|
542
|
+
&:active {
|
|
543
|
+
box-shadow: inset calc(2 * var(--chevron-border-thickness)) 0 0
|
|
544
|
+
${theme.base.palette.interactive};
|
|
473
545
|
|
|
474
|
-
|
|
475
|
-
|
|
476
|
-
|
|
477
|
-
|
|
478
|
-
* button, making it only partially visible through the clip-path notch window. This
|
|
479
|
-
* causes thicker interactive-state borders (3×) to look thinner on the left boundary
|
|
480
|
-
* than on the right (::after, which paints last and is always fully visible).
|
|
481
|
-
* The ::before tip's rightmost extent is at --stage-chevron-width from the <li> start,
|
|
482
|
-
* which is before the stage text (padding-inline-start: 2 × spacing), so no content overlap.
|
|
483
|
-
*/
|
|
484
|
-
z-index: 1;
|
|
546
|
+
[dir='rtl'] & {
|
|
547
|
+
box-shadow: inset calc(-2 * var(--chevron-border-thickness)) 0 0
|
|
548
|
+
${theme.base.palette.interactive};
|
|
549
|
+
}
|
|
485
550
|
}
|
|
486
551
|
|
|
487
|
-
|
|
488
|
-
|
|
552
|
+
@media (pointer: coarse) {
|
|
553
|
+
--stage-chevron-width: ${chevronConfig.coarseWidth};
|
|
554
|
+
width: calc(100% + (2 * var(--stage-chevron-width)));
|
|
489
555
|
}
|
|
556
|
+
}
|
|
490
557
|
|
|
491
|
-
|
|
492
|
-
|
|
493
|
-
|
|
494
|
-
|
|
495
|
-
|
|
496
|
-
|
|
497
|
-
transform: rotateZ(-45deg) skew(-15deg, -15deg);
|
|
498
|
-
}
|
|
558
|
+
/* Last stage: no right point */
|
|
559
|
+
&:nth-last-of-type(2) > ${StyledStage} {
|
|
560
|
+
--stage-chevron-width: ${chevronConfig.width};
|
|
561
|
+
padding-inline-end: 0;
|
|
562
|
+
width: 100%;
|
|
563
|
+
${stageClipPath(true, false)}
|
|
499
564
|
|
|
500
|
-
|
|
501
|
-
* At 45° rotation, border appears 1/sin(45°) ≈ 0.707× thinner, so 2× border ≈ 1.4× horizontal border weight.
|
|
502
|
-
*/
|
|
503
|
-
${createChevronBaseStyles(chevronConfig, 'var(--chevron-border-thickness)')}
|
|
504
|
-
${createChevronInteractiveStates(chevronConfig, 'var(--chevron-border-thickness)', !readOnly)}
|
|
505
|
-
${!readOnly &&
|
|
565
|
+
${includeHover &&
|
|
506
566
|
css `
|
|
507
|
-
|
|
508
|
-
&:
|
|
509
|
-
|
|
567
|
+
/* Inline-end interactive indicator via inset shadow — avoids border-color bleeding through gradient backgrounds */
|
|
568
|
+
&:hover {
|
|
569
|
+
box-shadow: inset calc(-2 * var(--chevron-border-thickness)) 0 0
|
|
570
|
+
${theme.base.palette['border-line']};
|
|
571
|
+
|
|
572
|
+
[dir='rtl'] & {
|
|
573
|
+
box-shadow: inset calc(2 * var(--chevron-border-thickness)) 0 0
|
|
574
|
+
${theme.base.palette['border-line']};
|
|
575
|
+
}
|
|
510
576
|
}
|
|
511
577
|
`}
|
|
512
|
-
&:has(button:focus-visible)::before,
|
|
513
|
-
&:has(button:focus-visible)::after {
|
|
514
|
-
border-color: ${palette.interactive};
|
|
515
|
-
}
|
|
516
578
|
|
|
517
|
-
&:
|
|
518
|
-
&:
|
|
519
|
-
|
|
579
|
+
&:focus-visible,
|
|
580
|
+
&:active {
|
|
581
|
+
box-shadow: inset calc(-2 * var(--chevron-border-thickness)) 0 0
|
|
582
|
+
${theme.base.palette.interactive};
|
|
583
|
+
|
|
584
|
+
[dir='rtl'] & {
|
|
585
|
+
box-shadow: inset calc(2 * var(--chevron-border-thickness)) 0 0
|
|
586
|
+
${theme.base.palette.interactive};
|
|
587
|
+
}
|
|
520
588
|
}
|
|
521
589
|
|
|
522
590
|
@media (pointer: coarse) {
|
|
523
|
-
|
|
524
|
-
|
|
525
|
-
|
|
526
|
-
width: ${chevronConfig.coarseSquareSize};
|
|
527
|
-
height: ${chevronConfig.coarseSquareSize};
|
|
528
|
-
}
|
|
591
|
+
--stage-chevron-width: ${chevronConfig.coarseWidth};
|
|
592
|
+
}
|
|
593
|
+
}
|
|
529
594
|
|
|
530
|
-
|
|
531
|
-
|
|
532
|
-
|
|
533
|
-
|
|
534
|
-
}
|
|
595
|
+
/* RTL: flip clip-paths for first and last stages */
|
|
596
|
+
[dir='rtl'] &:nth-of-type(2) > ${StyledStage} {
|
|
597
|
+
${stageClipPath(true, false, true)}
|
|
598
|
+
}
|
|
535
599
|
|
|
536
|
-
|
|
537
|
-
|
|
538
|
-
|
|
539
|
-
|
|
540
|
-
|
|
600
|
+
[dir='rtl'] &:nth-last-of-type(2) > ${StyledStage} {
|
|
601
|
+
${stageClipPath(false, true, true)}
|
|
602
|
+
}
|
|
603
|
+
|
|
604
|
+
@media (pointer: coarse) {
|
|
605
|
+
margin-inline-start: calc(-1 * ${chevronConfig.coarseWidth});
|
|
606
|
+
|
|
607
|
+
&:not(:nth-of-type(-n + 2))::before,
|
|
608
|
+
&:not(:nth-last-of-type(-n + 2))::after {
|
|
609
|
+
inset-block-start: calc(50% - ${chevronConfig.coarseSquareSize} / 2);
|
|
610
|
+
width: ${chevronConfig.coarseSquareSize};
|
|
611
|
+
height: ${chevronConfig.coarseSquareSize};
|
|
541
612
|
}
|
|
542
613
|
|
|
543
|
-
&:
|
|
544
|
-
|
|
545
|
-
|
|
546
|
-
|
|
547
|
-
|
|
548
|
-
padding-inline-start: calc(var(--chevron-spacing));
|
|
549
|
-
${stageClipPath(false, true)}
|
|
614
|
+
&:not(:nth-of-type(-n + 2))::before {
|
|
615
|
+
inset-inline-start: calc(
|
|
616
|
+
-1 * ${chevronConfig.coarseWidth} - ${chevronConfig.coarseOffsetLeft}
|
|
617
|
+
);
|
|
618
|
+
}
|
|
550
619
|
|
|
551
|
-
|
|
620
|
+
&:not(:nth-last-of-type(-n + 2))::after {
|
|
621
|
+
inset-inline-end: calc(
|
|
622
|
+
-1 * ${chevronConfig.coarseWidth} + ${chevronConfig.coarseOffsetRight}
|
|
623
|
+
);
|
|
624
|
+
}
|
|
625
|
+
}
|
|
626
|
+
`;
|
|
627
|
+
};
|
|
628
|
+
const stageContainerSegmentedStyles = (theme, readOnly) => {
|
|
629
|
+
const includeHover = !readOnly;
|
|
630
|
+
return css `
|
|
631
|
+
--segmented-edge-thickness: var(--chevron-border-thickness);
|
|
632
|
+
|
|
633
|
+
/* Segmented: stages overlap by --segmented-width so parallelogram edges meet flush */
|
|
634
|
+
margin-inline-start: calc(-1 * var(--segmented-width));
|
|
635
|
+
|
|
636
|
+
&:nth-of-type(2) {
|
|
637
|
+
margin-inline-start: 0;
|
|
638
|
+
}
|
|
639
|
+
|
|
640
|
+
/* Left segmented border strip: diagonal clip-path on each stage's inline-start edge (stages 2..N).
|
|
641
|
+
* The strip goes from (segmented-width, 0%) at top to (0%, 100%) at bottom of the pseudo,
|
|
642
|
+
* matching the parallelogram's inline-start clip edge exactly.
|
|
643
|
+
*/
|
|
644
|
+
&:not(:nth-of-type(-n + 2))::before {
|
|
645
|
+
content: '';
|
|
646
|
+
position: absolute;
|
|
647
|
+
inset-block: 0;
|
|
648
|
+
inset-inline-start: 0;
|
|
649
|
+
width: calc(var(--segmented-width) + var(--segmented-edge-thickness));
|
|
650
|
+
clip-path: polygon(
|
|
651
|
+
var(--segmented-width) 0%,
|
|
652
|
+
calc(var(--segmented-width) + var(--segmented-edge-thickness)) 0%,
|
|
653
|
+
var(--segmented-edge-thickness) 100%,
|
|
654
|
+
0% 100%
|
|
655
|
+
);
|
|
656
|
+
background: ${theme.base.palette['border-line']};
|
|
657
|
+
pointer-events: none;
|
|
658
|
+
z-index: 1;
|
|
659
|
+
}
|
|
660
|
+
|
|
661
|
+
/* Right segmented border strip: diagonal clip-path on each stage's inline-end edge (stages 1..N-1). */
|
|
662
|
+
&:not(:nth-last-of-type(-n + 2))::after {
|
|
663
|
+
content: '';
|
|
664
|
+
position: absolute;
|
|
665
|
+
inset-block: 0;
|
|
666
|
+
inset-inline-end: 0;
|
|
667
|
+
width: calc(var(--segmented-width) + var(--segmented-edge-thickness));
|
|
668
|
+
clip-path: polygon(
|
|
669
|
+
var(--segmented-width) 0%,
|
|
670
|
+
calc(var(--segmented-width) + var(--segmented-edge-thickness)) 0%,
|
|
671
|
+
var(--segmented-edge-thickness) 100%,
|
|
672
|
+
0% 100%
|
|
673
|
+
);
|
|
674
|
+
background: ${theme.base.palette['border-line']};
|
|
675
|
+
pointer-events: none;
|
|
676
|
+
z-index: 2;
|
|
677
|
+
}
|
|
678
|
+
|
|
679
|
+
/* Interactive states: update pseudo background to signal hover/focus/active */
|
|
680
|
+
${includeHover &&
|
|
552
681
|
css `
|
|
553
|
-
|
|
554
|
-
|
|
555
|
-
|
|
556
|
-
${palette['border-line']};
|
|
682
|
+
&:has(button:hover) {
|
|
683
|
+
--segmented-edge-thickness: var(--segmented-border-thickness);
|
|
684
|
+
}
|
|
557
685
|
|
|
558
|
-
|
|
559
|
-
|
|
560
|
-
|
|
561
|
-
|
|
562
|
-
|
|
563
|
-
|
|
686
|
+
&:has(button:hover)::before,
|
|
687
|
+
&:has(button:hover)::after {
|
|
688
|
+
background: ${theme.base.palette['border-line']};
|
|
689
|
+
}
|
|
690
|
+
`}
|
|
691
|
+
|
|
692
|
+
&:has(button:focus-visible),
|
|
693
|
+
&:has(button:active) {
|
|
694
|
+
--segmented-edge-thickness: var(--segmented-border-thickness);
|
|
695
|
+
}
|
|
696
|
+
|
|
697
|
+
&:has(button:focus-visible)::before,
|
|
698
|
+
&:has(button:focus-visible)::after,
|
|
699
|
+
&:has(button:active)::before,
|
|
700
|
+
&:has(button:active)::after {
|
|
701
|
+
background: ${theme.base.palette.interactive};
|
|
702
|
+
}
|
|
564
703
|
|
|
565
|
-
|
|
566
|
-
|
|
567
|
-
|
|
704
|
+
/* First stage (no inline-start cut): flat left edge + inset shadow edge indicator */
|
|
705
|
+
&:nth-of-type(2) > ${StyledStage} {
|
|
706
|
+
${segmentedClipPath(false, true)}
|
|
707
|
+
|
|
708
|
+
${includeHover &&
|
|
709
|
+
css `
|
|
710
|
+
&:hover {
|
|
711
|
+
box-shadow: inset var(--segmented-border-thickness) 0 0
|
|
712
|
+
${theme.base.palette['border-line']};
|
|
568
713
|
|
|
569
714
|
[dir='rtl'] & {
|
|
570
|
-
box-shadow: inset calc(-
|
|
715
|
+
box-shadow: inset calc(-1 * var(--segmented-border-thickness)) 0 0
|
|
716
|
+
${theme.base.palette['border-line']};
|
|
571
717
|
}
|
|
572
718
|
}
|
|
719
|
+
`}
|
|
720
|
+
|
|
721
|
+
&:focus-visible,
|
|
722
|
+
&:active {
|
|
723
|
+
box-shadow: inset var(--segmented-border-thickness) 0 0 ${theme.base.palette.interactive};
|
|
573
724
|
|
|
574
|
-
|
|
575
|
-
--
|
|
576
|
-
|
|
725
|
+
[dir='rtl'] & {
|
|
726
|
+
box-shadow: inset calc(-1 * var(--segmented-border-thickness)) 0 0
|
|
727
|
+
${theme.base.palette.interactive};
|
|
577
728
|
}
|
|
578
729
|
}
|
|
730
|
+
}
|
|
579
731
|
|
|
580
|
-
|
|
581
|
-
|
|
582
|
-
|
|
583
|
-
border-end-end-radius: ${borderRadius};
|
|
584
|
-
padding-inline-end: 0;
|
|
585
|
-
width: 100%;
|
|
586
|
-
${stageClipPath(true, false)}
|
|
732
|
+
/* Last stage (no inline-end cut): flat right edge + inset shadow edge indicator */
|
|
733
|
+
&:nth-last-of-type(2) > ${StyledStage} {
|
|
734
|
+
${segmentedClipPath(true, false)}
|
|
587
735
|
|
|
588
|
-
|
|
736
|
+
${includeHover &&
|
|
589
737
|
css `
|
|
590
|
-
|
|
591
|
-
|
|
592
|
-
|
|
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};
|
|
738
|
+
&:hover {
|
|
739
|
+
box-shadow: inset calc(-1 * var(--segmented-border-thickness)) 0 0
|
|
740
|
+
${theme.base.palette['border-line']};
|
|
605
741
|
|
|
606
742
|
[dir='rtl'] & {
|
|
607
|
-
box-shadow: inset
|
|
743
|
+
box-shadow: inset var(--segmented-border-thickness) 0 0
|
|
744
|
+
${theme.base.palette['border-line']};
|
|
608
745
|
}
|
|
609
746
|
}
|
|
747
|
+
`}
|
|
610
748
|
|
|
611
|
-
|
|
612
|
-
|
|
749
|
+
&:focus-visible,
|
|
750
|
+
&:active {
|
|
751
|
+
box-shadow: inset calc(-1 * var(--segmented-border-thickness)) 0 0
|
|
752
|
+
${theme.base.palette.interactive};
|
|
753
|
+
|
|
754
|
+
[dir='rtl'] & {
|
|
755
|
+
box-shadow: inset var(--segmented-border-thickness) 0 0 ${theme.base.palette.interactive};
|
|
613
756
|
}
|
|
614
757
|
}
|
|
758
|
+
}
|
|
615
759
|
|
|
616
|
-
|
|
617
|
-
|
|
618
|
-
}
|
|
760
|
+
/* RTL: flip clip-paths for first and last stage buttons */
|
|
761
|
+
[dir='rtl'] &:nth-of-type(2) > ${StyledStage} {
|
|
762
|
+
${segmentedClipPath(true, false, true)}
|
|
763
|
+
}
|
|
764
|
+
|
|
765
|
+
[dir='rtl'] &:nth-last-of-type(2) > ${StyledStage} {
|
|
766
|
+
${segmentedClipPath(false, true, true)}
|
|
767
|
+
}
|
|
768
|
+
|
|
769
|
+
/* RTL: mirror the pseudo clip-paths.
|
|
770
|
+
* In LTR the strip goes top-right → bottom-left (polygon A 0%, A+B 0%, B 100%, 0% 100%).
|
|
771
|
+
* In RTL the pseudo is positioned at the opposite physical edge via logical inset properties,
|
|
772
|
+
* so the strip must go top-left → bottom-right to stay aligned with the flipped slant.
|
|
773
|
+
*/
|
|
774
|
+
[dir='rtl'] &:not(:nth-of-type(-n + 2))::before,
|
|
775
|
+
[dir='rtl'] &:not(:nth-last-of-type(-n + 2))::after {
|
|
776
|
+
clip-path: polygon(
|
|
777
|
+
0% 0%,
|
|
778
|
+
var(--segmented-edge-thickness) 0%,
|
|
779
|
+
calc(var(--segmented-width) + var(--segmented-edge-thickness)) 100%,
|
|
780
|
+
var(--segmented-width) 100%
|
|
781
|
+
);
|
|
782
|
+
}
|
|
783
|
+
|
|
784
|
+
@media (pointer: coarse) {
|
|
785
|
+
/* A single CSS custom property update propagates to all margin and clip-path consumers */
|
|
786
|
+
--segmented-width: ${segmentedConfig.coarseWidth};
|
|
787
|
+
}
|
|
788
|
+
`;
|
|
789
|
+
};
|
|
790
|
+
const stageContainerVariants = {
|
|
791
|
+
chevron: stageContainerChevronStyles,
|
|
792
|
+
segmented: stageContainerSegmentedStyles,
|
|
793
|
+
milestone: () => css ``
|
|
794
|
+
};
|
|
795
|
+
/**
|
|
796
|
+
* `<li>` container for a single stage item. Manages negative-margin chevron overlap,
|
|
797
|
+
* pseudo-element positioning, and z-index stacking for interactive states.
|
|
798
|
+
*/
|
|
799
|
+
export const StyledStageContainer = styled.li(({ theme, theme: { components: { card: { 'border-radius': borderRadius } } }, readOnly, variant: shape }) => {
|
|
800
|
+
return css `
|
|
801
|
+
display: flex;
|
|
802
|
+
position: relative;
|
|
619
803
|
|
|
620
|
-
|
|
621
|
-
|
|
804
|
+
/* Resting z-index: for same-z siblings, DOM order determines paint order.
|
|
805
|
+
* All non-last <li>s have z-index:1 so the later (right) <li>'s ::before paints on top
|
|
806
|
+
* at internal boundaries; the last <li> has no z-index so its left neighbor's ::after
|
|
807
|
+
* wins at the final boundary. On hover/focus/active, the interacting <li> gains z:2/3
|
|
808
|
+
* and its own pseudo-element surfaces for that boundary, regardless of which side.
|
|
809
|
+
*/
|
|
810
|
+
&:not(:nth-last-of-type(-n + 2)) {
|
|
811
|
+
z-index: 1;
|
|
622
812
|
}
|
|
623
813
|
|
|
624
|
-
&:
|
|
625
|
-
|
|
626
|
-
|
|
627
|
-
|
|
814
|
+
&:has(button:focus-visible),
|
|
815
|
+
&:has(button:active) {
|
|
816
|
+
z-index: 2;
|
|
817
|
+
}
|
|
628
818
|
|
|
629
|
-
|
|
819
|
+
${!readOnly &&
|
|
630
820
|
css `
|
|
631
|
-
|
|
632
|
-
|
|
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};
|
|
821
|
+
&:has(button:hover) {
|
|
822
|
+
z-index: 3;
|
|
643
823
|
}
|
|
824
|
+
`}
|
|
825
|
+
|
|
826
|
+
/* Corner radii are shared across all shape variants */
|
|
827
|
+
&:nth-of-type(2) > ${StyledStage} {
|
|
828
|
+
border-start-start-radius: ${borderRadius};
|
|
829
|
+
border-end-start-radius: ${borderRadius};
|
|
830
|
+
}
|
|
831
|
+
|
|
832
|
+
&:nth-last-of-type(2) > ${StyledStage} {
|
|
833
|
+
border-start-end-radius: ${borderRadius};
|
|
834
|
+
border-end-end-radius: ${borderRadius};
|
|
644
835
|
}
|
|
836
|
+
|
|
837
|
+
${stageContainerVariants[shape](theme, readOnly)}
|
|
645
838
|
`;
|
|
646
839
|
});
|
|
647
840
|
StyledStageContainer.defaultProps = defaultThemeProp;
|
|
@@ -704,6 +897,195 @@ export const StyledStageGlimpse = styled.div(({ theme }) => {
|
|
|
704
897
|
`;
|
|
705
898
|
});
|
|
706
899
|
StyledStageGlimpse.defaultProps = defaultThemeProp;
|
|
900
|
+
const milestonePulse = keyframes `
|
|
901
|
+
0%, 100% {
|
|
902
|
+
box-shadow: 0 0 0 var(--milestone-pulse-min) var(--milestone-pulse-start);
|
|
903
|
+
}
|
|
904
|
+
60% {
|
|
905
|
+
box-shadow: 0 0 0 var(--milestone-pulse-spread) var(--milestone-pulse-end);
|
|
906
|
+
}
|
|
907
|
+
`;
|
|
908
|
+
export const StyledMilestoneLabel = styled.span(({ theme }) => {
|
|
909
|
+
return css `
|
|
910
|
+
color: ${theme.base.palette['foreground-color']};
|
|
911
|
+
line-height: ${theme.base['line-height']};
|
|
912
|
+
text-align: center;
|
|
913
|
+
align-self: stretch;
|
|
914
|
+
overflow-wrap: break-word;
|
|
915
|
+
padding-inline: calc(0.25 * ${theme.base.spacing});
|
|
916
|
+
`;
|
|
917
|
+
});
|
|
918
|
+
StyledMilestoneLabel.defaultProps = defaultThemeProp;
|
|
919
|
+
/**
|
|
920
|
+
* `<li>` container for a single stage item in the 'milestone' shape variant.
|
|
921
|
+
* Renders column-flex layout (milestone above, label below) and draws the
|
|
922
|
+
* horizontal connector as a single line from this milestone's centre to the next
|
|
923
|
+
* milestone's centre (::after), sized so every connector has an identical length.
|
|
924
|
+
*/
|
|
925
|
+
export const StyledMilestoneStageContainer = styled.li(({ theme, nextCompleted, status }) => {
|
|
926
|
+
const { base: { palette: { interactive, 'border-line': borderLine }, spacing } } = theme;
|
|
927
|
+
const fontSize = calculateFontSize(theme.base['font-size'], theme.base['font-scale']);
|
|
928
|
+
const connectorFilled = nextCompleted;
|
|
929
|
+
return css `
|
|
930
|
+
--connector-height: ${connectorFilled ? '0.25rem' : '0.125rem'};
|
|
931
|
+
--connector-display: block;
|
|
932
|
+
--connector-start: 50%;
|
|
933
|
+
--connector-width: 100%;
|
|
934
|
+
--connector-bg: ${connectorFilled ? interactive : borderLine};
|
|
935
|
+
--connector-forced-bg: ${connectorFilled ? 'Highlight' : 'CanvasText'};
|
|
936
|
+
display: flex;
|
|
937
|
+
flex-direction: column;
|
|
938
|
+
align-items: center;
|
|
939
|
+
flex: 1 0 0;
|
|
940
|
+
font-size: ${fontSize.xs};
|
|
941
|
+
font-weight: ${status === 'current'
|
|
942
|
+
? theme.base['font-weight']['semi-bold']
|
|
943
|
+
: theme.base['font-weight'].normal};
|
|
944
|
+
min-width: 15ch;
|
|
945
|
+
position: relative;
|
|
946
|
+
gap: ${spacing};
|
|
947
|
+
z-index: 1;
|
|
948
|
+
|
|
949
|
+
&:nth-of-type(2):not(:nth-last-of-type(2)) {
|
|
950
|
+
--connector-start: calc(var(--milestone-size) / 2);
|
|
951
|
+
--connector-width: calc(200% - var(--milestone-size));
|
|
952
|
+
align-items: flex-start;
|
|
953
|
+
flex: 0.5 0 calc(var(--milestone-size) / 2);
|
|
954
|
+
min-width: calc(7.5ch + var(--milestone-size) / 2);
|
|
955
|
+
|
|
956
|
+
${StyledMilestoneLabel} {
|
|
957
|
+
text-align: start;
|
|
958
|
+
}
|
|
959
|
+
}
|
|
960
|
+
|
|
961
|
+
&:nth-last-of-type(2):not(:nth-of-type(2)) {
|
|
962
|
+
--connector-display: none;
|
|
963
|
+
align-items: flex-end;
|
|
964
|
+
flex: 0.5 0 calc(var(--milestone-size) / 2);
|
|
965
|
+
min-width: calc(7.5ch + var(--milestone-size) / 2);
|
|
966
|
+
|
|
967
|
+
${StyledMilestoneLabel} {
|
|
968
|
+
text-align: end;
|
|
969
|
+
}
|
|
970
|
+
}
|
|
971
|
+
|
|
972
|
+
&:nth-of-type(2):nth-last-of-type(2) {
|
|
973
|
+
--connector-display: none;
|
|
974
|
+
align-items: center;
|
|
975
|
+
flex: 1 0 0;
|
|
976
|
+
}
|
|
977
|
+
|
|
978
|
+
&::after {
|
|
979
|
+
content: '';
|
|
980
|
+
display: var(--connector-display);
|
|
981
|
+
position: absolute;
|
|
982
|
+
inset-block-start: calc(var(--milestone-size) / 2 - var(--connector-height) / 2);
|
|
983
|
+
inset-inline-start: var(--connector-start);
|
|
984
|
+
width: var(--connector-width);
|
|
985
|
+
height: var(--connector-height);
|
|
986
|
+
background: var(--connector-bg);
|
|
987
|
+
pointer-events: none;
|
|
988
|
+
|
|
989
|
+
@media (forced-colors: active) {
|
|
990
|
+
background: var(--connector-forced-bg);
|
|
991
|
+
}
|
|
992
|
+
}
|
|
993
|
+
`;
|
|
994
|
+
});
|
|
995
|
+
StyledMilestoneStageContainer.defaultProps = defaultThemeProp;
|
|
996
|
+
export const StyledMilestoneButton = styled.button(({ theme, status, readOnly }) => {
|
|
997
|
+
const { base: { 'hit-area': hitArea, animation: { speed: animationSpeed, timing: { ease: animationTiming } }, shadow: { focus: focusShadow } }, components: { button: { 'border-width': borderWidth }, 'case-view': { stages } } } = theme;
|
|
998
|
+
const stageForeground = calculateForegroundColor(stages.status[status].background, stages.status[status]['foreground-color']);
|
|
999
|
+
const fontSize = calculateFontSize(theme.base['font-size'], theme.base['font-scale']);
|
|
1000
|
+
const completedBorderColor = status === 'completed'
|
|
1001
|
+
? tryCatch(() => darken(0.12, stages.status.completed.background), () => 'transparent')
|
|
1002
|
+
: '';
|
|
1003
|
+
return css `
|
|
1004
|
+
position: relative;
|
|
1005
|
+
z-index: 1;
|
|
1006
|
+
display: flex;
|
|
1007
|
+
align-items: center;
|
|
1008
|
+
justify-content: center;
|
|
1009
|
+
flex-shrink: 0;
|
|
1010
|
+
border-radius: 50%;
|
|
1011
|
+
width: var(--milestone-size);
|
|
1012
|
+
height: var(--milestone-size);
|
|
1013
|
+
background: ${stages.status[status].background};
|
|
1014
|
+
color: ${stageForeground};
|
|
1015
|
+
font-size: ${fontSize.s};
|
|
1016
|
+
font-weight: ${status === 'current'
|
|
1017
|
+
? theme.base['font-weight']['semi-bold']
|
|
1018
|
+
: theme.base['font-weight'].normal};
|
|
1019
|
+
outline: none;
|
|
1020
|
+
border: none;
|
|
1021
|
+
cursor: ${readOnly ? 'default' : 'pointer'};
|
|
1022
|
+
transition: box-shadow calc(2 * ${animationSpeed}) ${animationTiming};
|
|
1023
|
+
|
|
1024
|
+
${status === 'completed' &&
|
|
1025
|
+
css `
|
|
1026
|
+
box-shadow: inset 0 0 0 calc(2 * ${borderWidth}) ${completedBorderColor};
|
|
1027
|
+
`}
|
|
1028
|
+
|
|
1029
|
+
&:focus-visible {
|
|
1030
|
+
box-shadow: ${focusShadow};
|
|
1031
|
+
|
|
1032
|
+
@media (forced-colors: active) {
|
|
1033
|
+
outline: 0.125rem solid Highlight;
|
|
1034
|
+
outline-offset: 0.125rem;
|
|
1035
|
+
}
|
|
1036
|
+
}
|
|
1037
|
+
|
|
1038
|
+
${!readOnly &&
|
|
1039
|
+
css `
|
|
1040
|
+
&:hover {
|
|
1041
|
+
filter: brightness(0.85);
|
|
1042
|
+
}
|
|
1043
|
+
|
|
1044
|
+
&:active {
|
|
1045
|
+
filter: brightness(0.85);
|
|
1046
|
+
}
|
|
1047
|
+
`}
|
|
1048
|
+
|
|
1049
|
+
${status === 'current' &&
|
|
1050
|
+
!readOnly &&
|
|
1051
|
+
css `
|
|
1052
|
+
&::before {
|
|
1053
|
+
content: '';
|
|
1054
|
+
position: absolute;
|
|
1055
|
+
inset: 0;
|
|
1056
|
+
border-radius: 50%;
|
|
1057
|
+
pointer-events: none;
|
|
1058
|
+
animation: ${milestonePulse} 2s ease-out infinite;
|
|
1059
|
+
|
|
1060
|
+
@media (prefers-reduced-motion: reduce) {
|
|
1061
|
+
animation: none;
|
|
1062
|
+
}
|
|
1063
|
+
}
|
|
1064
|
+
`}
|
|
1065
|
+
|
|
1066
|
+
/* Expanded hit area */
|
|
1067
|
+
&::after {
|
|
1068
|
+
content: '';
|
|
1069
|
+
position: absolute;
|
|
1070
|
+
width: ${hitArea['mouse-min']};
|
|
1071
|
+
height: ${hitArea['mouse-min']};
|
|
1072
|
+
inset-block-start: calc((${hitArea['mouse-min']} - var(--milestone-size)) / -2);
|
|
1073
|
+
inset-inline-start: calc((${hitArea['mouse-min']} - var(--milestone-size)) / -2);
|
|
1074
|
+
|
|
1075
|
+
@media (pointer: coarse) {
|
|
1076
|
+
width: ${hitArea['finger-min']};
|
|
1077
|
+
height: ${hitArea['finger-min']};
|
|
1078
|
+
inset-block-start: calc((${hitArea['finger-min']} - var(--milestone-size)) / -2);
|
|
1079
|
+
inset-inline-start: calc((${hitArea['finger-min']} - var(--milestone-size)) / -2);
|
|
1080
|
+
}
|
|
1081
|
+
}
|
|
1082
|
+
|
|
1083
|
+
@media (forced-colors: active) {
|
|
1084
|
+
border: 0.125rem solid ButtonText;
|
|
1085
|
+
}
|
|
1086
|
+
`;
|
|
1087
|
+
});
|
|
1088
|
+
StyledMilestoneButton.defaultProps = defaultThemeProp;
|
|
707
1089
|
/**
|
|
708
1090
|
* Visually hidden `<p>` providing an accessible description for the stages list,
|
|
709
1091
|
* announced by screen readers but not displayed on screen.
|