| b69ab31 | | | 1 | /** |
| b69ab31 | | | 2 | * Copyright (c) Meta Platforms, Inc. and affiliates. |
| b69ab31 | | | 3 | * |
| b69ab31 | | | 4 | * This source code is licensed under the MIT license found in the |
| b69ab31 | | | 5 | * LICENSE file in the root directory of this source tree. |
| b69ab31 | | | 6 | */ |
| b69ab31 | | | 7 | |
| b69ab31 | | | 8 | import type {MultiStepperContext} from 'isl-components/multi_stepper/MultiStepperContext'; |
| b69ab31 | | | 9 | |
| b69ab31 | | | 10 | import * as stylex from '@stylexjs/stylex'; |
| b69ab31 | | | 11 | import {Icon} from 'isl-components/Icon'; |
| b69ab31 | | | 12 | |
| b69ab31 | | | 13 | const styles = stylex.create({ |
| b69ab31 | | | 14 | stepItem: { |
| b69ab31 | | | 15 | display: 'flex', |
| b69ab31 | | | 16 | alignItems: 'center', |
| b69ab31 | | | 17 | gap: '12px', |
| b69ab31 | | | 18 | padding: '12px', |
| b69ab31 | | | 19 | borderRadius: '4px', |
| b69ab31 | | | 20 | marginBottom: '8px', |
| b69ab31 | | | 21 | }, |
| b69ab31 | | | 22 | stepItemActive: { |
| b69ab31 | | | 23 | backgroundColor: 'var(--highlight-background)', |
| b69ab31 | | | 24 | }, |
| b69ab31 | | | 25 | stepItemCompleted: { |
| b69ab31 | | | 26 | cursor: 'pointer', |
| b69ab31 | | | 27 | }, |
| b69ab31 | | | 28 | stepNumber: { |
| b69ab31 | | | 29 | display: 'flex', |
| b69ab31 | | | 30 | alignItems: 'center', |
| b69ab31 | | | 31 | justifyContent: 'center', |
| b69ab31 | | | 32 | width: '20px', |
| b69ab31 | | | 33 | height: '20px', |
| b69ab31 | | | 34 | borderRadius: '50%', |
| b69ab31 | | | 35 | border: '2px solid var(--foreground)', |
| b69ab31 | | | 36 | fontSize: '12px', |
| b69ab31 | | | 37 | fontWeight: 'bold', |
| b69ab31 | | | 38 | }, |
| b69ab31 | | | 39 | stepNumberActive: { |
| b69ab31 | | | 40 | backgroundColor: 'var(--button-primary-background)', |
| b69ab31 | | | 41 | borderColor: 'var(--button-primary-background)', |
| b69ab31 | | | 42 | color: 'var(--button-primary-foreground)', |
| b69ab31 | | | 43 | }, |
| b69ab31 | | | 44 | stepNumberCompleted: { |
| b69ab31 | | | 45 | backgroundColor: 'var(--success-background)', |
| b69ab31 | | | 46 | borderColor: 'var(--success-background)', |
| b69ab31 | | | 47 | }, |
| b69ab31 | | | 48 | stepLabel: { |
| b69ab31 | | | 49 | fontSize: '14px', |
| b69ab31 | | | 50 | }, |
| b69ab31 | | | 51 | stepLabelActive: { |
| b69ab31 | | | 52 | fontWeight: 'bold', |
| b69ab31 | | | 53 | }, |
| b69ab31 | | | 54 | }); |
| b69ab31 | | | 55 | |
| b69ab31 | | | 56 | type Props<TKey> = { |
| b69ab31 | | | 57 | stepper: MultiStepperContext<TKey>; |
| b69ab31 | | | 58 | }; |
| b69ab31 | | | 59 | |
| b69ab31 | | | 60 | /** |
| b69ab31 | | | 61 | * A vertical progress bar for a multi-step stepper. |
| b69ab31 | | | 62 | */ |
| b69ab31 | | | 63 | export function VerticalStepperProgress<TKey>({stepper}: Props<TKey>) { |
| b69ab31 | | | 64 | const icon = <Icon icon="check" />; |
| b69ab31 | | | 65 | |
| b69ab31 | | | 66 | const steps = stepper.getAllSteps(); |
| b69ab31 | | | 67 | const currentIndex = stepper.getStepIndex(); |
| b69ab31 | | | 68 | |
| b69ab31 | | | 69 | return ( |
| b69ab31 | | | 70 | <div> |
| b69ab31 | | | 71 | {steps.map((step, index) => { |
| b69ab31 | | | 72 | const isActive = index === currentIndex; |
| b69ab31 | | | 73 | const isCompleted = index < currentIndex; |
| b69ab31 | | | 74 | |
| b69ab31 | | | 75 | return ( |
| b69ab31 | | | 76 | <div |
| b69ab31 | | | 77 | key={String(step.key)} |
| b69ab31 | | | 78 | onClick={() => (isCompleted ? stepper.goToStepByKey(step.key) : undefined)} |
| b69ab31 | | | 79 | {...stylex.props( |
| b69ab31 | | | 80 | styles.stepItem, |
| b69ab31 | | | 81 | isActive && styles.stepItemActive, |
| b69ab31 | | | 82 | isCompleted && styles.stepItemCompleted, |
| b69ab31 | | | 83 | )}> |
| b69ab31 | | | 84 | <div |
| b69ab31 | | | 85 | {...stylex.props( |
| b69ab31 | | | 86 | styles.stepNumber, |
| b69ab31 | | | 87 | isActive && styles.stepNumberActive, |
| b69ab31 | | | 88 | isCompleted && styles.stepNumberCompleted, |
| b69ab31 | | | 89 | )}> |
| b69ab31 | | | 90 | {isCompleted ? icon : index + 1} |
| b69ab31 | | | 91 | </div> |
| b69ab31 | | | 92 | <div {...stylex.props(styles.stepLabel, isActive && styles.stepLabelActive)}> |
| b69ab31 | | | 93 | {step.label} |
| b69ab31 | | | 94 | </div> |
| b69ab31 | | | 95 | </div> |
| b69ab31 | | | 96 | ); |
| b69ab31 | | | 97 | })} |
| b69ab31 | | | 98 | </div> |
| b69ab31 | | | 99 | ); |
| b69ab31 | | | 100 | } |