Skip to content

Commit dad6df1

Browse files
authored
fix: update steppedlistcard (#5780)
* fix: update steppedlistcard * fix: feedback
1 parent 566c51d commit dad6df1

File tree

13 files changed

+426
-55
lines changed

13 files changed

+426
-55
lines changed

.changeset/late-tips-heal.md

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
---
2+
"@ultraviolet/plus": patch
3+
---
4+
5+
`SteppedListCard`:
6+
- possibility to have an icon instead of a step number
7+
- `nextStep` will not change the step state (completed or not) if it does not receive a prop
8+
- smaller bullets
9+
- Update stories

packages/plus/src/components/SteppedListCard/Step.tsx

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22

33
import { CheckIcon } from '@ultraviolet/icons'
44
import { StepList, Text } from '@ultraviolet/ui'
5+
import type { ReactNode } from 'react'
56
import { useContext } from 'react'
67
import { Data } from './helper'
78
import { steppedListCardStep, steppedListCardStepTitle } from './styles.css'
@@ -11,6 +12,10 @@ type StepProps = {
1112
* The number of the step, max 5 steps.
1213
*/
1314
stepNumber: number
15+
/**
16+
* An icon to replace the step number in the bullet
17+
*/
18+
stepIcon?: ReactNode
1419
/**
1520
* Title of the step
1621
*/
@@ -26,6 +31,7 @@ export const SteppedList = ({
2631
stepNumber,
2732
stepTitle,
2833
completed,
34+
stepIcon,
2935
'data-testid': dataTestId,
3036
}: StepProps) => {
3137
const containerData = useContext(Data)
@@ -39,6 +45,7 @@ export const SteppedList = ({
3945
onClick={() => containerData.setCurrentStep(stepNumber)}
4046
prominence={active ? 'strong' : 'default'}
4147
sentiment="primary"
48+
size="small"
4249
>
4350
<Text
4451
as="h3"
@@ -50,12 +57,13 @@ export const SteppedList = ({
5057
</StepList.Item>
5158
) : (
5259
<StepList.Item
53-
bulletContent={String(stepNumber)}
60+
bulletContent={stepIcon ?? String(stepNumber)}
5461
className={steppedListCardStep}
5562
data-testid={dataTestId}
5663
onClick={() => containerData.setCurrentStep(stepNumber)}
5764
prominence={active ? 'strong' : undefined}
5865
sentiment={active ? 'primary' : undefined}
66+
size="small"
5967
>
6068
<Text
6169
as="h3"

packages/plus/src/components/SteppedListCard/SteppedListCard.tsx

Lines changed: 30 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,11 @@ import { Children, useMemo, useState } from 'react'
66
import { Data } from './helper'
77
import { SteppedList } from './Step'
88
import { SteppedListContent } from './SteppedListContent'
9-
import { steppedListCard, steppedListCardWrapper } from './styles.css'
9+
import {
10+
hideButton,
11+
steppedListCard,
12+
steppedListCardWrapper,
13+
} from './styles.css'
1014

1115
type SteppedListContainerProps = {
1216
/**
@@ -16,7 +20,7 @@ type SteppedListContainerProps = {
1620
/**
1721
* List of steps
1822
*/
19-
steps: string[]
23+
steps: (string | { title: string; icon: ReactNode })[]
2024
/**
2125
* Define here the content of each step
2226
*/
@@ -111,8 +115,12 @@ const SteppedListCard = ({
111115

112116
return (
113117
<Data.Provider value={values}>
114-
<Stack gap={3}>
115-
<Row templateColumns="9fr 1fr">
118+
<Stack gap={2} width="100%">
119+
<Stack
120+
alignItems="center"
121+
direction="row"
122+
justifyContent="space-between"
123+
>
116124
{typeof header === 'string' ? (
117125
<Text as="h3" variant="heading">
118126
{header}
@@ -122,6 +130,7 @@ const SteppedListCard = ({
122130
)}
123131
{showToggleOption ? (
124132
<Button
133+
className={hideButton}
125134
onClick={onClickHideButton}
126135
sentiment="neutral"
127136
size="small"
@@ -131,7 +140,7 @@ const SteppedListCard = ({
131140
{hidden ? showText : hideText}
132141
</Button>
133142
) : null}
134-
</Row>
143+
</Stack>
135144
{hidden ? null : (
136145
<Card className={steppedListCard}>
137146
<Row templateColumns="1fr 3fr">
@@ -141,14 +150,22 @@ const SteppedListCard = ({
141150
gap={4}
142151
>
143152
<StepList>
144-
{steps.map((step, index) => (
145-
<SteppedList
146-
completed={done[index]}
147-
key={step}
148-
stepNumber={index + 1}
149-
stepTitle={step}
150-
/>
151-
))}
153+
{steps.map((step, index) => {
154+
const stepTitle =
155+
typeof step === 'string' ? step : step.title
156+
const stepIcon =
157+
typeof step === 'string' ? undefined : step.icon
158+
159+
return (
160+
<SteppedList
161+
completed={done[index]}
162+
key={stepTitle}
163+
stepIcon={stepIcon}
164+
stepNumber={index + 1}
165+
stepTitle={stepTitle}
166+
/>
167+
)
168+
})}
152169
</StepList>
153170
</Stack>
154171
{children}

packages/plus/src/components/SteppedListCard/SteppedListContent.tsx

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ import {
1212

1313
type SteppedListContentProps = {
1414
subHeader?: ReactNode
15-
children: ((nextStep: (completed: boolean) => void) => ReactNode) | ReactNode
15+
children: ((nextStep: (completed?: boolean) => void) => ReactNode) | ReactNode
1616
image?: ReactNode
1717
stepNumber: number
1818
completed?: boolean
@@ -58,7 +58,7 @@ export const SteppedListContent = ({
5858
)}
5959
</div>
6060
{typeof children === 'function'
61-
? children((completedArg: boolean) =>
61+
? children((completedArg?: boolean) =>
6262
nextStep({
6363
completed: completedArg,
6464
done,
Lines changed: 113 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,113 @@
1+
import type { StoryFn } from '@storybook/react-vite'
2+
import { CheckIcon, EastIcon } from '@ultraviolet/icons'
3+
import { WireIllustration } from '@ultraviolet/illustrations'
4+
import { Button, Snippet, Stack, Text } from '@ultraviolet/ui'
5+
import type { ComponentProps } from 'react'
6+
import { SteppedListCard } from '../SteppedListCard'
7+
8+
export const IconStep: StoryFn<
9+
ComponentProps<typeof SteppedListCard>
10+
> = props => (
11+
<SteppedListCard {...props}>
12+
<SteppedListCard.Step
13+
image={<WireIllustration height={200} name="blockStorage" width={200} />}
14+
stepNumber={1}
15+
subHeader={
16+
<Text as="h3" sentiment="primary" variant="headingSmallStrong">
17+
Welcome aboard!
18+
</Text>
19+
}
20+
>
21+
{nextStep => (
22+
<Stack direction="column" gap={2}>
23+
<Snippet {...props}>
24+
pnpm add @ultraviolet/ui; pnpm install; pnpm start; pnpm build; pnpm
25+
test:unit; pnpm test:visual; pnpm build:storybook;
26+
</Snippet>
27+
<Text as="div" variant="body">
28+
We are thrilled to count you as a Scaleway user! We are looking
29+
forward to providing you with the very best experience. To order
30+
resources to get started with your project, we need you to complete
31+
a few more steps.
32+
</Text>
33+
<Stack direction="row" gap={2}>
34+
<Button sentiment="primary">Action 1</Button>
35+
<Button
36+
onClick={() => {
37+
nextStep(true)
38+
}}
39+
sentiment="primary"
40+
variant="outlined"
41+
>
42+
<CheckIcon /> Mark as done
43+
</Button>
44+
<Button
45+
onClick={() => {
46+
nextStep(false)
47+
}}
48+
sentiment="neutral"
49+
variant="ghost"
50+
>
51+
Skip
52+
</Button>
53+
</Stack>
54+
</Stack>
55+
)}
56+
</SteppedListCard.Step>
57+
<SteppedListCard.Step
58+
image={<WireIllustration height={200} name="blockStorage" width={200} />}
59+
stepNumber={2}
60+
subHeader="Second step"
61+
>
62+
{nextStep => (
63+
<Stack direction="column" gap={2}>
64+
Second step description
65+
<Stack direction="row" gap={2}>
66+
<Button onClick={() => nextStep()} variant="outlined">
67+
Next step
68+
</Button>
69+
<Button onClick={() => nextStep(true)}>
70+
Next step and validate
71+
</Button>
72+
</Stack>
73+
</Stack>
74+
)}
75+
</SteppedListCard.Step>
76+
<SteppedListCard.Step
77+
image={<WireIllustration height={200} name="blockStorage" width={200} />}
78+
stepNumber={3}
79+
subHeader="Last step"
80+
>
81+
{nextStep => (
82+
<Stack gap={2}>
83+
Second step description
84+
<Stack direction="row" gap={2}>
85+
<Button onClick={() => nextStep(true)}>Validate and close</Button>
86+
</Stack>
87+
</Stack>
88+
)}
89+
</SteppedListCard.Step>
90+
</SteppedListCard>
91+
)
92+
93+
IconStep.args = {
94+
header: 'Header',
95+
hideText: 'Hide',
96+
hideTooltipText: 'To hide the content, click on the "hide" button',
97+
showText: 'Show',
98+
showTooltipText: 'To show, click on this button',
99+
steps: [
100+
{ icon: <EastIcon />, title: 'Start' },
101+
{ icon: <EastIcon />, title: 'First step' },
102+
{ icon: <EastIcon />, title: 'Second step' },
103+
],
104+
}
105+
106+
IconStep.parameters = {
107+
docs: {
108+
description: {
109+
story:
110+
'You can replace the step number with a custom icon in the bullet by passing an object of the form { title: string, icon: ReactNode } to the steps array.',
111+
},
112+
},
113+
}
Lines changed: 65 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,65 @@
1+
import type { StoryFn } from '@storybook/react-vite'
2+
import { Button, Stack } from '@ultraviolet/ui'
3+
import type { ComponentProps } from 'react'
4+
import { SteppedListCard } from '../SteppedListCard'
5+
6+
export const NextStep: StoryFn<
7+
ComponentProps<typeof SteppedListCard>
8+
> = props => (
9+
<SteppedListCard {...props}>
10+
<SteppedListCard.Step stepNumber={1}>
11+
{nextStep => (
12+
<Stack direction="column" gap={2}>
13+
<Stack direction="row" gap={2}>
14+
<Button
15+
onClick={() => {
16+
nextStep()
17+
}}
18+
sentiment="primary"
19+
>
20+
nextStep()
21+
</Button>
22+
<Button
23+
onClick={() => {
24+
nextStep(true)
25+
}}
26+
>
27+
nextStep(true)
28+
</Button>
29+
<Button
30+
onClick={() => {
31+
nextStep(false)
32+
}}
33+
>
34+
nextStep(false)
35+
</Button>
36+
</Stack>
37+
</Stack>
38+
)}
39+
</SteppedListCard.Step>
40+
<SteppedListCard.Step stepNumber={2}>
41+
<Stack direction="column" gap={2}>
42+
Click the name of step 1 to navigate back to it and test the different
43+
buttons.
44+
</Stack>
45+
</SteppedListCard.Step>
46+
</SteppedListCard>
47+
)
48+
49+
NextStep.args = {
50+
header: 'Header',
51+
hideText: 'Hide',
52+
hideTooltipText: 'To hide the content, click on the "hide" button',
53+
showText: 'Show',
54+
showTooltipText: 'To show, click on this button',
55+
steps: ['Start', 'First step'],
56+
}
57+
58+
NextStep.parameters = {
59+
docs: {
60+
description: {
61+
story:
62+
"Using the function 'nextStep', you can go to the next step. There are 3 ways to go to the next step: <ul> <li> nextStep(true): will mark current step as done and move to next step </li> <li> nextStep(false): will mark current step as not done adn move to next step </li> <li> nextStep(): go to next step without changing current step status</li></ul>",
63+
},
64+
},
65+
}

packages/plus/src/components/SteppedListCard/__stories__/OnClickHide.stories.tsx

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -71,7 +71,9 @@ export const OnClickHide: StoryFn<
7171

7272
OnClickHide.args = {
7373
header: 'Header',
74+
hideText: 'custom hide text',
7475
hideTooltipText: 'It will trigger "onClickHide"',
76+
showText: 'custom show text',
7577
steps: ['Start', 'First step'],
7678
}
7779

0 commit comments

Comments
 (0)