Skip to content

Commit 3f52e12

Browse files
Add multi-step components (#2151)
<!-- Ensure the title clearly reflects what was changed. Provide a clear and concise description of the changes made. The PR should only contain the changes related to the issue, and no other unrelated changes. --> Fixes OPS-3931 ## Additional Notes Verified benchmarks still works as expected
1 parent 9b9d573 commit 3f52e12

17 files changed

Lines changed: 499 additions & 405 deletions

packages/react-ui/src/app/features/benchmark/components/benchmark-wizard-footer.tsx

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -2,11 +2,11 @@ import {
22
BenchmarkRunPhase,
33
Button,
44
INTERNAL_ERROR_TOAST,
5+
MultiStepFormNext,
6+
MultiStepFormPrevious,
57
Tooltip,
68
TooltipContent,
79
TooltipTrigger,
8-
WizardNext,
9-
WizardPrevious,
1010
toast,
1111
} from '@openops/components/ui';
1212
import { BenchmarkCreationResult } from '@openops/shared';
@@ -115,8 +115,8 @@ export const BenchmarkWizardFooter = ({
115115
if (wizardPhase === 'provider-step') {
116116
return (
117117
<>
118-
<WizardPrevious onPrevious={handlePrevious} />
119-
<WizardNext
118+
<MultiStepFormPrevious onPrevious={handlePrevious} />
119+
<MultiStepFormNext
120120
onNext={handleNextFromProviderStep}
121121
disabled={isNextDisabled}
122122
/>
@@ -129,7 +129,7 @@ export const BenchmarkWizardFooter = ({
129129
<div className="flex-1" />
130130
<Tooltip>
131131
<TooltipTrigger asChild className="disabled:pointer-events-auto">
132-
<WizardNext
132+
<MultiStepFormNext
133133
onNext={handleNextFromInitial}
134134
disabled={isNextDisabled}
135135
/>

packages/react-ui/src/app/features/benchmark/components/benchmark-wizard.tsx

Lines changed: 23 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,13 @@
11
import {
22
BenchmarkCreatingPlaceholder,
33
BenchmarkReadyStep,
4-
Wizard,
5-
WizardClose,
6-
WizardContent,
7-
WizardFooter,
8-
WizardHeader,
9-
WizardStep,
10-
WizardTitle,
4+
MultiStepForm,
5+
MultiStepFormClose,
6+
MultiStepFormContent,
7+
MultiStepFormFooter,
8+
MultiStepFormHeader,
9+
MultiStepFormStep,
10+
MultiStepFormTitle,
1111
} from '@openops/components/ui';
1212
import { BenchmarkCreationResult } from '@openops/shared';
1313
import { t } from 'i18next';
@@ -127,30 +127,30 @@ export const BenchmarkWizard = ({
127127
onClose={handleCloseConnectionDialog}
128128
/>
129129
)}
130-
<Wizard
130+
<MultiStepForm
131131
className="border-l-0 border-t-0 pb-9"
132132
value={wizardPhase}
133133
onValueChange={noop}
134134
>
135-
<WizardHeader className="min-h-[60px] bg-white border-gray-200">
136-
<WizardTitle>{t('Run a Benchmark')}</WizardTitle>
137-
<WizardClose onClose={onClose} />
138-
</WizardHeader>
135+
<MultiStepFormHeader className="min-h-[60px] bg-white border-gray-200">
136+
<MultiStepFormTitle>{t('Run a Benchmark')}</MultiStepFormTitle>
137+
<MultiStepFormClose onClose={onClose} />
138+
</MultiStepFormHeader>
139139

140-
<WizardContent className="flex flex-col overflow-hidden">
140+
<MultiStepFormContent className="flex flex-col overflow-hidden">
141141
{isCreatingBenchmark ? (
142142
<BenchmarkCreatingPlaceholder />
143143
) : (
144144
<>
145-
<WizardStep value="initial" key="initial">
145+
<MultiStepFormStep value="initial" key="initial">
146146
<InitialBenchmarkStep
147147
selectedProvider={selectedProvider}
148148
onProviderChange={setSelectedProvider}
149149
onConnect={setConnectingProvider}
150150
connectedProviders={connectedProviders}
151151
/>
152-
</WizardStep>
153-
<WizardStep
152+
</MultiStepFormStep>
153+
<MultiStepFormStep
154154
value="provider-step"
155155
key="provider-step"
156156
className="flex flex-col flex-1 min-h-0"
@@ -163,8 +163,8 @@ export const BenchmarkWizard = ({
163163
onValueChange={setCurrentSelections}
164164
/>
165165
)}
166-
</WizardStep>
167-
<WizardStep
166+
</MultiStepFormStep>
167+
<MultiStepFormStep
168168
value="benchmark-ready"
169169
key="benchmark-ready"
170170
className="flex flex-col flex-1 min-h-0"
@@ -178,12 +178,12 @@ export const BenchmarkWizard = ({
178178
failedWorkflows={failedWorkflows}
179179
/>
180180
)}
181-
</WizardStep>
181+
</MultiStepFormStep>
182182
</>
183183
)}
184-
</WizardContent>
184+
</MultiStepFormContent>
185185

186-
<WizardFooter>
186+
<MultiStepFormFooter>
187187
<BenchmarkWizardFooter
188188
wizardPhase={wizardPhase}
189189
runPhase={runPhase}
@@ -198,8 +198,8 @@ export const BenchmarkWizard = ({
198198
onViewRun={handleViewRun}
199199
onRunAgain={handleRunBenchmark}
200200
/>
201-
</WizardFooter>
202-
</Wizard>
201+
</MultiStepFormFooter>
202+
</MultiStepForm>
203203
</div>
204204
);
205205
};

packages/ui-components/src/components/benchmark/benchmark-ready-step.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ import { BenchmarkRunPhase } from '@/lib/types';
22
import { BenchmarkCreationResult } from '@openops/shared';
33
import { t } from 'i18next';
44
import { Link } from 'react-router-dom';
5-
import { StepDescription } from '../../ui/wizard/wizard-step';
5+
import { StepDescription } from '../../ui/multi-step-form/multi-step-form-step-parts';
66
import { BenchmarkAnalyticsPhase } from './benchmark-analytics-phase';
77
import { BenchmarkFailedPhase } from './benchmark-failed-phase';
88
import { BenchmarkRunningPhase } from './benchmark-running-phase';

packages/ui-components/src/index.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,7 @@ export * from './ui/form';
3333
export * from './ui/image-with-fallback';
3434
export * from './ui/input';
3535
export * from './ui/label';
36+
export * from './ui/multi-step-form';
3637
export * from './ui/numeric-input';
3738
export * from './ui/permission-message-context';
3839
export * from './ui/permission-needed-tooltip';
@@ -65,7 +66,6 @@ export * from './ui/use-toast';
6566
export * from './ui/user-avatar-menu';
6667
export * from './ui/vertical-divider';
6768
export * from './ui/warning-with-icon';
68-
export * from './ui/wizard';
6969

7070
/* export dashboard widgets */
7171
export * from './ui/big-number-chart';

packages/ui-components/src/stories/wizard/wizard.stories.tsx renamed to packages/ui-components/src/stories/multi-step-form/multi-step-form.stories.tsx

Lines changed: 43 additions & 44 deletions
Original file line numberDiff line numberDiff line change
@@ -4,21 +4,21 @@ import { useState } from 'react';
44
import {
55
Avatar,
66
AvatarFallback,
7+
MultiStepForm,
8+
MultiStepFormClose,
9+
MultiStepFormContent,
10+
MultiStepFormFooter,
11+
MultiStepFormHeader,
12+
MultiStepFormNext,
13+
MultiStepFormPrevious,
14+
MultiStepFormStep,
15+
MultiStepFormTitle,
716
SelectAllCheckbox,
817
SelectForm,
918
SelectOption,
1019
StepBody,
1120
StepDescription,
1221
StepTitle,
13-
Wizard,
14-
WizardClose,
15-
WizardContent,
16-
WizardFooter,
17-
WizardHeader,
18-
WizardNext,
19-
WizardPrevious,
20-
WizardStep,
21-
WizardTitle,
2222
type SelectAllChangeAction,
2323
} from '../../index';
2424

@@ -62,21 +62,17 @@ const SERVICES = [
6262
{ id: 'redshift', name: 'Redshift', code: 'Re' },
6363
];
6464

65-
type WizardStep = 'step1' | 'step2' | 'step3' | 'step4' | 'step5';
65+
type Step = 'step1' | 'step2' | 'step3' | 'step4' | 'step5';
6666

67-
const WizardExample = () => {
68-
const [currentStep, setCurrentStep] = useState<WizardStep>('step1');
67+
const MultiStepFormExample = () => {
68+
const [currentStep, setCurrentStep] = useState<Step>('step1');
6969
const [cloudProvider, setCloudProvider] = useState('');
7070
const [awsConnection, setAwsConnection] = useState('');
7171
const [selectedAccounts, setSelectedAccounts] = useState<string[]>([]);
7272
const [selectedRegions, setSelectedRegions] = useState<string[]>([]);
7373
const [selectedServices, setSelectedServices] = useState<string[]>([]);
7474

75-
const steps: WizardStep[] = ['step1', 'step2', 'step3', 'step4', 'step5'];
76-
77-
const handleStepChange = (value: string) => {
78-
setCurrentStep(value as WizardStep);
79-
};
75+
const steps: Step[] = ['step1', 'step2', 'step3', 'step4', 'step5'];
8076

8177
const isCurrentStepValid = (): boolean => {
8278
switch (currentStep) {
@@ -113,14 +109,17 @@ const WizardExample = () => {
113109

114110
return (
115111
<div className="w-[500px] h-[600px] bg-[#FBFBFE] dark:bg-background">
116-
<Wizard value={currentStep} onValueChange={handleStepChange}>
117-
<WizardHeader>
118-
<WizardTitle>Run a Benchmark</WizardTitle>
119-
<WizardClose onClose={() => alert('Wizard closed')} />
120-
</WizardHeader>
112+
<MultiStepForm
113+
value={currentStep}
114+
onValueChange={(v) => setCurrentStep(v as Step)}
115+
>
116+
<MultiStepFormHeader>
117+
<MultiStepFormTitle>Run a Benchmark</MultiStepFormTitle>
118+
<MultiStepFormClose onClose={() => alert('Form closed')} />
119+
</MultiStepFormHeader>
121120

122-
<WizardContent>
123-
<WizardStep value="step1">
121+
<MultiStepFormContent>
122+
<MultiStepFormStep value="step1">
124123
<StepTitle>Let&apos;s create your Benchmark Report!</StepTitle>
125124
<StepDescription className="!mt-0">
126125
<button
@@ -205,9 +204,9 @@ const WizardExample = () => {
205204
</SelectOption>
206205
</SelectForm>
207206
</StepBody>
208-
</WizardStep>
207+
</MultiStepFormStep>
209208

210-
<WizardStep value="step2">
209+
<MultiStepFormStep value="step2">
211210
<StepTitle>Choose the AWS connection you want to use</StepTitle>
212211
<StepDescription className="!mt-0">
213212
OpenOps can pull data from AWS using the connection you select
@@ -258,9 +257,9 @@ const WizardExample = () => {
258257
))}
259258
</SelectForm>
260259
</StepBody>
261-
</WizardStep>
260+
</MultiStepFormStep>
262261

263-
<WizardStep value="step3">
262+
<MultiStepFormStep value="step3">
264263
<StepDescription>
265264
This connection supports multiple accounts, which of them would
266265
like to include in the report?
@@ -306,9 +305,9 @@ const WizardExample = () => {
306305
</SelectForm>
307306
</div>
308307
</StepBody>
309-
</WizardStep>
308+
</MultiStepFormStep>
310309

311-
<WizardStep value="step4">
310+
<MultiStepFormStep value="step4">
312311
<StepDescription>
313312
Choose which AWS regions to include in your benchmark report
314313
</StepDescription>
@@ -351,9 +350,9 @@ const WizardExample = () => {
351350
</SelectForm>
352351
</div>
353352
</StepBody>
354-
</WizardStep>
353+
</MultiStepFormStep>
355354

356-
<WizardStep value="step5">
355+
<MultiStepFormStep value="step5">
357356
<StepDescription>
358357
Choose which AWS services to include in your benchmark report
359358
</StepDescription>
@@ -383,7 +382,7 @@ const WizardExample = () => {
383382
value={service.id}
384383
icon={
385384
<Avatar className="h-8 w-8">
386-
<AvatarFallback className="bg-orange-500 bg-[#FFEDD4] text-[#F54900] text-xs">
385+
<AvatarFallback className="bg-[#FFEDD4] text-[#F54900] text-xs">
387386
{service.code}
388387
</AvatarFallback>
389388
</Avatar>
@@ -396,34 +395,34 @@ const WizardExample = () => {
396395
</SelectForm>
397396
</div>
398397
</StepBody>
399-
</WizardStep>
400-
</WizardContent>
398+
</MultiStepFormStep>
399+
</MultiStepFormContent>
401400

402-
<WizardFooter>
401+
<MultiStepFormFooter>
403402
{steps.includes(currentStep) && steps.indexOf(currentStep) !== 0 ? (
404-
<WizardPrevious />
403+
<MultiStepFormPrevious />
405404
) : (
406405
<div className="w-[112px]" />
407406
)}
408-
<WizardNext disabled={!isCurrentStepValid()} />
409-
</WizardFooter>
410-
</Wizard>
407+
<MultiStepFormNext disabled={!isCurrentStepValid()} />
408+
</MultiStepFormFooter>
409+
</MultiStepForm>
411410
</div>
412411
);
413412
};
414413

415414
const meta = {
416-
title: 'ui/Wizard',
417-
component: Wizard,
415+
title: 'ui/MultiStepForm',
416+
component: MultiStepForm,
418417
tags: ['autodocs'],
419418
parameters: {
420419
layout: 'centered',
421420
},
422-
} satisfies Meta<typeof Wizard>;
421+
} satisfies Meta<typeof MultiStepForm>;
423422

424423
export default meta;
425424

426425
type Story = StoryObj<typeof meta>;
427426
export const BenchmarkWizard: Story = {
428-
render: () => <WizardExample />,
427+
render: () => <MultiStepFormExample />,
429428
};
Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
export { MultiStepForm, useMultiStepForm } from './multi-step-form';
2+
export type { MultiStepFormProps } from './multi-step-form';
3+
export { MultiStepFormContent } from './multi-step-form-content';
4+
export {
5+
MultiStepFormFooter,
6+
MultiStepFormNext,
7+
MultiStepFormPrevious,
8+
} from './multi-step-form-footer';
9+
export {
10+
MultiStepFormClose,
11+
MultiStepFormHeader,
12+
MultiStepFormTitle,
13+
} from './multi-step-form-header';
14+
export { MultiStepFormStep } from './multi-step-form-step';
15+
export type { MultiStepFormStepProps } from './multi-step-form-step';
16+
export {
17+
StepBody,
18+
StepDescription,
19+
StepTitle,
20+
} from './multi-step-form-step-parts';
Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
import * as React from 'react';
2+
3+
import { cn } from '../../lib/cn';
4+
5+
type MultiStepFormContentProps = React.HTMLAttributes<HTMLDivElement>;
6+
7+
const MultiStepFormContent = React.forwardRef<
8+
HTMLDivElement,
9+
MultiStepFormContentProps
10+
>(({ className, children, ...props }, ref) => {
11+
return (
12+
<div
13+
ref={ref}
14+
className={cn('flex-1 px-6 py-2 space-y-6 overflow-auto', className)}
15+
{...props}
16+
>
17+
{children}
18+
</div>
19+
);
20+
});
21+
MultiStepFormContent.displayName = 'MultiStepFormContent';
22+
23+
export { MultiStepFormContent };

0 commit comments

Comments
 (0)