@pega/cosmos-react-work 10.0.0-build.4.7 → 10.0.0-build.4.9
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 +2 -0
- package/lib/components/CaseView/CaseView.styles.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.styles.d.ts +2 -0
- package/lib/components/GenAICoach/GenAICoach.styles.d.ts.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.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 +597 -162
- 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/Tasks/TaskList.js +1 -1
- package/lib/components/Tasks/TaskList.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 = {
|
|
@@ -195,13 +209,17 @@ export const StyledStagesWrapper = styled.div(({ theme }) => {
|
|
|
195
209
|
});
|
|
196
210
|
StyledStagesWrapper.defaultProps = defaultThemeProp;
|
|
197
211
|
/**
|
|
198
|
-
* Scrollable `<ol>` containing all stage chevron items. Sets the `--chevron-spacing
|
|
199
|
-
* 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.
|
|
200
215
|
*/
|
|
201
|
-
export const StyledStages = styled.ol(({ theme }) => {
|
|
216
|
+
export const StyledStages = styled.ol(({ theme, variant }) => {
|
|
217
|
+
const isMilestone = variant === 'milestone';
|
|
202
218
|
return css `
|
|
203
219
|
--chevron-spacing: ${theme.base.spacing};
|
|
204
220
|
--chevron-border-thickness: ${theme.components.button['border-width']};
|
|
221
|
+
--segmented-border-thickness: calc(2 * ${theme.components.button['border-width']});
|
|
222
|
+
--segmented-width: ${segmentedConfig.width};
|
|
205
223
|
border-radius: ${theme.components.card['border-radius']};
|
|
206
224
|
display: flex;
|
|
207
225
|
padding: 0;
|
|
@@ -212,6 +230,17 @@ export const StyledStages = styled.ol(({ theme }) => {
|
|
|
212
230
|
scrollbar-width: thin;
|
|
213
231
|
scrollbar-color: transparent transparent;
|
|
214
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
|
+
|
|
215
244
|
&:hover,
|
|
216
245
|
&:focus-within {
|
|
217
246
|
scrollbar-color: var(
|
|
@@ -299,11 +328,58 @@ export const StyledInnerStage = styled.span(({ theme, ellipsis }) => {
|
|
|
299
328
|
`;
|
|
300
329
|
});
|
|
301
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
|
+
};
|
|
302
378
|
/**
|
|
303
379
|
* Clickable `<button>` for a single stage. Renders the chevron clip-path shape and
|
|
304
380
|
* applies status-based background and foreground colours.
|
|
305
381
|
*/
|
|
306
|
-
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 }) => {
|
|
307
383
|
const stageForeground = calculateForegroundColor(stages.status[status].background, stages.status[status]['foreground-color']);
|
|
308
384
|
return css `
|
|
309
385
|
background: ${stages.status[status].background};
|
|
@@ -318,26 +394,10 @@ export const StyledStage = styled.button(({ theme: { base: { palette, 'hit-area'
|
|
|
318
394
|
* Adding 0.0625rem (1px at default font size) to min-height compensates so the button fills its <li> container,
|
|
319
395
|
* keeping the clipped chevron background flush with the top and bottom borders. */
|
|
320
396
|
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
397
|
margin-inline-start: 0;
|
|
324
398
|
margin-inline-end: 0;
|
|
325
|
-
width: calc(100% + ${chevronConfig.width});
|
|
326
|
-
--stage-chevron-width: ${chevronConfig.width};
|
|
327
399
|
|
|
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
|
-
}
|
|
400
|
+
${stageButtonVariants[shape](theme)}
|
|
341
401
|
|
|
342
402
|
${!readOnly &&
|
|
343
403
|
css `
|
|
@@ -376,9 +436,6 @@ export const StyledStage = styled.button(({ theme: { base: { palette, 'hit-area'
|
|
|
376
436
|
|
|
377
437
|
@media (pointer: coarse) {
|
|
378
438
|
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
439
|
}
|
|
383
440
|
`;
|
|
384
441
|
});
|
|
@@ -400,195 +457,384 @@ export const StyledStageText = styled(Text)(({ theme, isCurrent }) => css `
|
|
|
400
457
|
font-weight: ${isCurrent ? theme.base['font-weight'].bold : theme.base['font-weight'].normal};
|
|
401
458
|
`);
|
|
402
459
|
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 }) => {
|
|
460
|
+
const stageContainerChevronStyles = (theme, readOnly) => {
|
|
461
|
+
const includeHover = !readOnly;
|
|
408
462
|
return css `
|
|
409
|
-
|
|
410
|
-
|
|
411
|
-
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});
|
|
412
465
|
|
|
413
|
-
|
|
414
|
-
|
|
415
|
-
|
|
466
|
+
&:nth-of-type(2) {
|
|
467
|
+
margin-inline-start: 0;
|
|
468
|
+
}
|
|
416
469
|
|
|
417
|
-
|
|
418
|
-
|
|
419
|
-
|
|
420
|
-
|
|
421
|
-
*
|
|
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.
|
|
422
480
|
*/
|
|
423
|
-
|
|
424
|
-
|
|
481
|
+
z-index: 1;
|
|
482
|
+
}
|
|
483
|
+
|
|
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']};
|
|
425
507
|
}
|
|
508
|
+
`}
|
|
426
509
|
|
|
427
|
-
|
|
428
|
-
|
|
429
|
-
|
|
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 &&
|
|
528
|
+
css `
|
|
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
|
+
}
|
|
538
|
+
}
|
|
539
|
+
`}
|
|
540
|
+
|
|
541
|
+
&:focus-visible,
|
|
542
|
+
&:active {
|
|
543
|
+
box-shadow: inset calc(2 * var(--chevron-border-thickness)) 0 0
|
|
544
|
+
${theme.base.palette.interactive};
|
|
545
|
+
|
|
546
|
+
[dir='rtl'] & {
|
|
547
|
+
box-shadow: inset calc(-2 * var(--chevron-border-thickness)) 0 0
|
|
548
|
+
${theme.base.palette.interactive};
|
|
549
|
+
}
|
|
430
550
|
}
|
|
431
551
|
|
|
432
|
-
|
|
552
|
+
@media (pointer: coarse) {
|
|
553
|
+
--stage-chevron-width: ${chevronConfig.coarseWidth};
|
|
554
|
+
width: calc(100% + (2 * var(--stage-chevron-width)));
|
|
555
|
+
}
|
|
556
|
+
}
|
|
557
|
+
|
|
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)}
|
|
564
|
+
|
|
565
|
+
${includeHover &&
|
|
433
566
|
css `
|
|
434
|
-
|
|
435
|
-
|
|
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
|
+
}
|
|
436
576
|
}
|
|
437
577
|
`}
|
|
438
578
|
|
|
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
|
+
}
|
|
588
|
+
}
|
|
589
|
+
|
|
439
590
|
@media (pointer: coarse) {
|
|
440
|
-
|
|
591
|
+
--stage-chevron-width: ${chevronConfig.coarseWidth};
|
|
592
|
+
}
|
|
593
|
+
}
|
|
594
|
+
|
|
595
|
+
/* RTL: flip clip-paths for first and last stages */
|
|
596
|
+
[dir='rtl'] &:nth-of-type(2) > ${StyledStage} {
|
|
597
|
+
${stageClipPath(true, false, true)}
|
|
598
|
+
}
|
|
599
|
+
|
|
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};
|
|
441
612
|
}
|
|
442
613
|
|
|
443
614
|
&:not(:nth-of-type(-n + 2))::before {
|
|
444
|
-
|
|
445
|
-
|
|
446
|
-
|
|
447
|
-
* button, making it only partially visible through the clip-path notch window. This
|
|
448
|
-
* causes thicker interactive-state borders (3×) to look thinner on the left boundary
|
|
449
|
-
* than on the right (::after, which paints last and is always fully visible).
|
|
450
|
-
* The ::before tip's rightmost extent is at --stage-chevron-width from the <li> start,
|
|
451
|
-
* which is before the stage text (padding-inline-start: 2 × spacing), so no content overlap.
|
|
452
|
-
*/
|
|
453
|
-
z-index: 1;
|
|
615
|
+
inset-inline-start: calc(
|
|
616
|
+
-1 * ${chevronConfig.coarseWidth} - ${chevronConfig.coarseOffsetLeft}
|
|
617
|
+
);
|
|
454
618
|
}
|
|
455
619
|
|
|
456
620
|
&:not(:nth-last-of-type(-n + 2))::after {
|
|
457
|
-
|
|
621
|
+
inset-inline-end: calc(
|
|
622
|
+
-1 * ${chevronConfig.coarseWidth} + ${chevronConfig.coarseOffsetRight}
|
|
623
|
+
);
|
|
458
624
|
}
|
|
625
|
+
}
|
|
626
|
+
`;
|
|
627
|
+
};
|
|
628
|
+
const stageContainerSegmentedStyles = (theme, readOnly) => {
|
|
629
|
+
const includeHover = !readOnly;
|
|
630
|
+
return css `
|
|
631
|
+
--segmented-edge-thickness: var(--chevron-border-thickness);
|
|
459
632
|
|
|
460
|
-
|
|
461
|
-
|
|
462
|
-
*/
|
|
633
|
+
/* Segmented: stages overlap by --segmented-width so parallelogram edges meet flush */
|
|
634
|
+
margin-inline-start: calc(-1 * var(--segmented-width));
|
|
463
635
|
|
|
464
|
-
|
|
465
|
-
|
|
466
|
-
|
|
467
|
-
}
|
|
636
|
+
&:nth-of-type(2) {
|
|
637
|
+
margin-inline-start: 0;
|
|
638
|
+
}
|
|
468
639
|
|
|
469
|
-
|
|
470
|
-
|
|
471
|
-
|
|
472
|
-
|
|
473
|
-
|
|
474
|
-
|
|
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 &&
|
|
475
681
|
css `
|
|
476
|
-
|
|
477
|
-
|
|
478
|
-
border-color: ${palette['border-line']};
|
|
479
|
-
}
|
|
480
|
-
`}
|
|
481
|
-
&:has(button:focus-visible)::before,
|
|
482
|
-
&:has(button:focus-visible)::after {
|
|
483
|
-
border-color: ${palette.interactive};
|
|
682
|
+
&:has(button:hover) {
|
|
683
|
+
--segmented-edge-thickness: var(--segmented-border-thickness);
|
|
484
684
|
}
|
|
485
685
|
|
|
486
|
-
&:has(button:
|
|
487
|
-
&:has(button:
|
|
488
|
-
|
|
686
|
+
&:has(button:hover)::before,
|
|
687
|
+
&:has(button:hover)::after {
|
|
688
|
+
background: ${theme.base.palette['border-line']};
|
|
489
689
|
}
|
|
690
|
+
`}
|
|
490
691
|
|
|
491
|
-
|
|
492
|
-
|
|
493
|
-
|
|
494
|
-
|
|
495
|
-
|
|
496
|
-
|
|
497
|
-
|
|
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
|
+
}
|
|
703
|
+
|
|
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']};
|
|
498
713
|
|
|
499
|
-
|
|
500
|
-
|
|
501
|
-
|
|
502
|
-
|
|
714
|
+
[dir='rtl'] & {
|
|
715
|
+
box-shadow: inset calc(-1 * var(--segmented-border-thickness)) 0 0
|
|
716
|
+
${theme.base.palette['border-line']};
|
|
717
|
+
}
|
|
503
718
|
}
|
|
719
|
+
`}
|
|
720
|
+
|
|
721
|
+
&:focus-visible,
|
|
722
|
+
&:active {
|
|
723
|
+
box-shadow: inset var(--segmented-border-thickness) 0 0 ${theme.base.palette.interactive};
|
|
504
724
|
|
|
505
|
-
|
|
506
|
-
|
|
507
|
-
|
|
508
|
-
);
|
|
725
|
+
[dir='rtl'] & {
|
|
726
|
+
box-shadow: inset calc(-1 * var(--segmented-border-thickness)) 0 0
|
|
727
|
+
${theme.base.palette.interactive};
|
|
509
728
|
}
|
|
510
729
|
}
|
|
730
|
+
}
|
|
511
731
|
|
|
512
|
-
|
|
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)}
|
|
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)}
|
|
519
735
|
|
|
520
|
-
|
|
736
|
+
${includeHover &&
|
|
521
737
|
css `
|
|
522
|
-
|
|
523
|
-
|
|
524
|
-
|
|
525
|
-
${palette['border-line']};
|
|
526
|
-
|
|
527
|
-
[dir='rtl'] & {
|
|
528
|
-
box-shadow: inset calc(-2 * var(--chevron-border-thickness)) 0 0
|
|
529
|
-
${palette['border-line']};
|
|
530
|
-
}
|
|
531
|
-
}
|
|
532
|
-
`}
|
|
533
|
-
|
|
534
|
-
&:focus-visible,
|
|
535
|
-
&:active {
|
|
536
|
-
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']};
|
|
537
741
|
|
|
538
742
|
[dir='rtl'] & {
|
|
539
|
-
box-shadow: inset
|
|
743
|
+
box-shadow: inset var(--segmented-border-thickness) 0 0
|
|
744
|
+
${theme.base.palette['border-line']};
|
|
540
745
|
}
|
|
541
746
|
}
|
|
747
|
+
`}
|
|
748
|
+
|
|
749
|
+
&:focus-visible,
|
|
750
|
+
&:active {
|
|
751
|
+
box-shadow: inset calc(-1 * var(--segmented-border-thickness)) 0 0
|
|
752
|
+
${theme.base.palette.interactive};
|
|
542
753
|
|
|
543
|
-
|
|
544
|
-
--
|
|
545
|
-
width: calc(100% + (2 * var(--stage-chevron-width)));
|
|
754
|
+
[dir='rtl'] & {
|
|
755
|
+
box-shadow: inset var(--segmented-border-thickness) 0 0 ${theme.base.palette.interactive};
|
|
546
756
|
}
|
|
547
757
|
}
|
|
758
|
+
}
|
|
548
759
|
|
|
549
|
-
|
|
550
|
-
|
|
551
|
-
|
|
552
|
-
|
|
553
|
-
padding-inline-end: 0;
|
|
554
|
-
width: 100%;
|
|
555
|
-
${stageClipPath(true, false)}
|
|
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
|
+
}
|
|
556
764
|
|
|
557
|
-
|
|
558
|
-
|
|
559
|
-
|
|
560
|
-
&:hover {
|
|
561
|
-
box-shadow: inset calc(-2 * var(--chevron-border-thickness)) 0 0
|
|
562
|
-
${palette['border-line']};
|
|
765
|
+
[dir='rtl'] &:nth-last-of-type(2) > ${StyledStage} {
|
|
766
|
+
${segmentedClipPath(false, true, true)}
|
|
767
|
+
}
|
|
563
768
|
|
|
564
|
-
|
|
565
|
-
|
|
566
|
-
|
|
567
|
-
|
|
568
|
-
|
|
569
|
-
|
|
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
|
+
}
|
|
570
783
|
|
|
571
|
-
|
|
572
|
-
|
|
573
|
-
|
|
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;
|
|
574
803
|
|
|
575
|
-
|
|
576
|
-
|
|
577
|
-
|
|
578
|
-
|
|
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;
|
|
812
|
+
}
|
|
579
813
|
|
|
580
|
-
|
|
581
|
-
|
|
582
|
-
|
|
814
|
+
&:has(button:focus-visible),
|
|
815
|
+
&:has(button:active) {
|
|
816
|
+
z-index: 2;
|
|
583
817
|
}
|
|
584
818
|
|
|
585
|
-
|
|
586
|
-
|
|
819
|
+
${!readOnly &&
|
|
820
|
+
css `
|
|
821
|
+
&:has(button:hover) {
|
|
822
|
+
z-index: 3;
|
|
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};
|
|
587
830
|
}
|
|
588
831
|
|
|
589
|
-
|
|
590
|
-
${
|
|
832
|
+
&:nth-last-of-type(2) > ${StyledStage} {
|
|
833
|
+
border-start-end-radius: ${borderRadius};
|
|
834
|
+
border-end-end-radius: ${borderRadius};
|
|
591
835
|
}
|
|
836
|
+
|
|
837
|
+
${stageContainerVariants[shape](theme, readOnly)}
|
|
592
838
|
`;
|
|
593
839
|
});
|
|
594
840
|
StyledStageContainer.defaultProps = defaultThemeProp;
|
|
@@ -651,6 +897,195 @@ export const StyledStageGlimpse = styled.div(({ theme }) => {
|
|
|
651
897
|
`;
|
|
652
898
|
});
|
|
653
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;
|
|
654
1089
|
/**
|
|
655
1090
|
* Visually hidden `<p>` providing an accessible description for the stages list,
|
|
656
1091
|
* announced by screen readers but not displayed on screen.
|