-
Notifications
You must be signed in to change notification settings - Fork 117
Expand file tree
/
Copy pathindex.tsx
More file actions
127 lines (118 loc) · 3.94 KB
/
index.tsx
File metadata and controls
127 lines (118 loc) · 3.94 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
"use client";
import { Text } from "@stellar/design-system";
import "./styles.scss";
export type TransactionStepName =
| "build"
| "import"
| "simulate"
| "validate"
| "sign"
| "submit";
const STEP_LABELS: Record<TransactionStepName, string> = {
build: "Build transaction",
import: "Import XDR",
simulate: "Simulate transaction",
validate: "Validate transaction",
sign: "Sign transaction",
submit: "Submit transaction",
};
const STEP_DESCRIPTIONS: Partial<Record<TransactionStepName, string>> = {
validate:
"This transaction contains authorization entries that need to be validated before submitting.",
};
/**
* Returns the display label for a transaction step.
*
* @param step - The step name
* @returns Human-readable label string
*
* @example
* getStepLabel("build") // "Build transaction"
*/
export const getStepLabel = (step: TransactionStepName): string =>
STEP_LABELS[step];
/**
* Presentational stepper component for the single-page transaction flow.
* Displays a vertical list of numbered steps with active/completed/disabled
* states. Steps that have been completed are clickable; future steps are not.
*
* @param steps - Ordered array of step names to display
* @param activeStep - The currently active step
* @param highestCompletedStep - The furthest step the user has reached (null if none)
* @param onStepClick - Callback when a completed step is clicked
*/
export const TransactionStepper = ({
steps,
activeStep,
highestCompletedStep,
onStepClick,
}: {
steps: TransactionStepName[];
activeStep: TransactionStepName;
highestCompletedStep: TransactionStepName | null;
onStepClick: (step: TransactionStepName) => void;
}) => {
const highestCompletedIndex = highestCompletedStep
? steps.indexOf(highestCompletedStep)
: -1;
return (
<div className="TransactionStepper">
{steps.map((step, index) => {
const isActive = step === activeStep;
const isCompleted = index <= highestCompletedIndex;
const isClickable = isCompleted && !isActive;
const isLast = index === steps.length - 1;
return (
<div
role="button"
key={step}
className="TransactionStepper__step"
data-is-active={isActive || undefined}
data-is-completed={isCompleted || undefined}
data-is-clickable={isClickable || undefined}
data-has-description={!!STEP_DESCRIPTIONS[step] || undefined}
onClick={isClickable ? () => onStepClick(step) : undefined}
>
<div className="TransactionStepper__indicator">
<div className="TransactionStepper__badgeWrapper">
<div className="TransactionStepper__badge">{index + 1}</div>
{isCompleted && (
<div className="TransactionStepper__checkmark">
<svg
width="6"
height="5"
viewBox="0 0 6 5"
fill="none"
xmlns="http://www.w3.org/2000/svg"
>
<path
d="M1 2.5L2.5 4L5 1"
stroke="white"
strokeWidth="1.2"
strokeLinecap="round"
strokeLinejoin="round"
/>
</svg>
</div>
)}
</div>
{!isLast && <div className="TransactionStepper__connector" />}
</div>
<div className="TransactionStepper__label">
{STEP_LABELS[step]}
{STEP_DESCRIPTIONS[step] && (
<Text
size="xs"
as="div"
addlClassName="TransactionStepper__description"
>
{STEP_DESCRIPTIONS[step]}
</Text>
)}
</div>
</div>
);
})}
</div>
);
};