Skip to content
Merged
Show file tree
Hide file tree
Changes from 6 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Binary file modified .loki/reference/chrome_laptop_Components_Stepper_Default.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file modified .loki/reference/chrome_laptop_Components_Stepper_With_State.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
17 changes: 11 additions & 6 deletions src/components/Stepper/Step.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -18,17 +18,22 @@ it('should render correctly when status is active', () => {
expect(container).toMatchSnapshot()
})

it('should render correctly when status is inactive', () => {
const { container } = render(<Step status='inactive'>Inactive step</Step>)
expect(container).toMatchSnapshot()
})

it('should accept "style" prop', () => {
const { container } = render(<Step style={{ color: 'red' }}>Step red</Step>)
expect(container).toMatchSnapshot()
})

it('should allow override of components', () => {
const RootOverride = props => <span id='root' {...props} />
const ConnectorOverride = props => <span id='connector' {...props} />
const IconOverride = props => <span id='icon' {...props} />
const IconContainerOverride = props => <span id='icon-container' {...props} />
const LabelOverride = props => <span id='label' {...props} />
const RootOverride = (props) => <span id='root' {...props} />
const ConnectorOverride = (props) => <span id='connector' {...props} />
const IconOverride = (props) => <span id='icon' {...props} />
const IconContainerOverride = (props) => <span id='icon-container' {...props} />
const LabelOverride = (props) => <span id='label' {...props} />

const { container } = render(
<Step
Expand All @@ -47,7 +52,7 @@ it('should allow override of components', () => {
})

it('should not render Connector when "hasConnector" props is false', () => {
const Connector = props => <span id='connector' />
const Connector = (props) => <span id='connector' />

const { rerender, container } = render(
<Step overrides={{ Connector }} hasConnector={false}>
Expand Down
107 changes: 59 additions & 48 deletions src/components/Stepper/Step.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,12 @@ import { ExternalStyles, focusBoxShadow, Theme, useStyles } from '../../styles'
import { Omit } from '../../util'
import { getComponents } from '../../util/overrides'
import CheckIcon from '../Icon/generated/CheckDefault'
import { StepInactiveIcon } from './StepInactiveIcon'

export type StepStatus = 'active' | 'completed' | 'incompleted' | 'inactive'

export interface StepProps extends Omit<React.HTMLAttributes<HTMLSpanElement>, 'style'> {
status?: 'active' | 'completed' | 'incompleted'
status?: StepStatus
hasConnector?: boolean
style?: ExternalStyles
overrides?: {
Expand All @@ -30,6 +33,7 @@ export function Step(props: StepProps) {
<IconContainer className={classes.iconContainer}>
{Icon && <Icon className={classes.icon} />}
{!Icon && status === 'completed' && <CheckIcon className={classes.icon} />}
{!Icon && status === 'inactive' && <StepInactiveIcon />}
</IconContainer>

<Label className={classes.stepLabel}>{children}</Label>
Expand All @@ -50,50 +54,57 @@ export const defaultComponents: StepProps['overrides'] = {
Label: 'span',
}

const createStyles = (theme: Theme, { status }: StepProps) => ({
step: {
position: 'relative',
flex: '1',
display: 'flex',
flexDirection: 'column',
alignItems: 'center',
textAlign: 'center',
padding: '0 0.5rem',
} as CSSProperties,
connector: {
position: 'absolute',
top: '0.5rem',
left: 'calc(-50% + 0.5rem)',
right: 'calc(50% + 0.5rem)',
borderTopWidth: '2px',
borderTopStyle: 'solid',
borderTopColor: status === 'incompleted' ? theme.pallete.gray.c80 : theme.pallete.primary.main,
transition: 'all .4s ease',
} as CSSProperties,
iconContainer: {
zIndex: 1,
display: 'flex',
alignItems: 'center',
justifyContent: 'center',
width: '1rem',
height: '1rem',
borderRadius: '50%',
background: status === 'incompleted' ? theme.pallete.gray.c80 : theme.pallete.primary.main,
textAlign: 'center',
marginBottom: '0.75rem',
transition: 'all .4s ease',
boxShadow:
(status === 'active' && focusBoxShadow(theme, 'primary')) ||
(status === 'completed' && `0 0 0 4px ${theme.pallete.primary.main}`),
} as CSSProperties,
icon: {
fill: theme.pallete.primary.c100,
width: '1rem',
height: '1rem',
} as CSSProperties,
stepLabel: {
fontWeight: 'bold',
color: status === 'active' && theme.pallete.primary.main,
transition: 'all .4s ease',
} as CSSProperties,
})
const createStyles = (theme: Theme, { status }: StepProps) => {
const activeLabelColor = status === 'active' && theme.pallete.primary.main
const inactiveLabelColor = status === 'inactive' && theme.pallete.text.disabled

return {
step: {
position: 'relative',
flex: '1',
display: 'flex',
flexDirection: 'column',
alignItems: 'center',
textAlign: 'center',
padding: '0 0.5rem',
} as CSSProperties,
connector: {
position: 'absolute',
top: '0.5rem',
left: 'calc(-50% + 0.5rem)',
right: 'calc(50% + 0.5rem)',
borderTopWidth: '2px',
borderTopStyle: status === 'inactive' ? 'dashed' : 'solid',
borderTopColor:
status === 'incompleted' || status === 'inactive' ? theme.pallete.gray.c80 : theme.pallete.primary.main,
transition: 'all .4s ease',
} as CSSProperties,
iconContainer: {
zIndex: 1,
display: 'flex',
alignItems: 'center',
justifyContent: 'center',
width: '1rem',
height: '1rem',
borderRadius: '50%',
background:
status === 'incompleted' || status === 'inactive' ? theme.pallete.gray.c60 : theme.pallete.primary.main,
textAlign: 'center',
marginBottom: '0.75rem',
transition: 'all .4s ease',
boxShadow:
(status === 'active' && focusBoxShadow(theme, 'primary')) ||
(status === 'completed' && `0 0 0 4px ${theme.pallete.primary.main}`),
} as CSSProperties,
icon: {
fill: theme.pallete.primary.c100,
width: '1rem',
height: '1rem',
} as CSSProperties,
stepLabel: {
fontWeight: 'bold',
color: activeLabelColor || inactiveLabelColor || theme.pallete.text.main,
transition: 'all .4s ease',
} as CSSProperties,
}
}
27 changes: 27 additions & 0 deletions src/components/Stepper/StepInactiveIcon.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
import React, { CSSProperties } from 'react'
import { Theme, useStyles } from '../../styles'

export function StepInactiveIcon() {
const { classes, css } = useStyles(createStyles)

return (
<div className={css(classes.container)}>
<div className={css(classes.icon)} />
</div>
)
}

const createStyles = (theme: Theme) => ({
container: {
width: '1rem',
height: '1rem',
display: 'flex',
alignItems: 'center',
justifyContent: 'center',
} as CSSProperties,
icon: {
width: '6px',
height: '2px',
background: theme.pallete.surface.main,
} as CSSProperties,
})
2 changes: 1 addition & 1 deletion src/components/Stepper/Stepper.stories.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ export const Default = () => (
</Step>
<Step status='active'>Second and active step</Step>
<Step>Some incompleted step</Step>
<Step>Last and incompleted step</Step>
<Step status='inactive'>Last and inactive step</Step>
</Stepper>
)

Expand Down
124 changes: 121 additions & 3 deletions src/components/Stepper/__snapshots__/Step.test.tsx.snap
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ exports[`should accept "style" prop 1`] = `
width: 1rem;
height: 1rem;
border-radius: 50%;
background: #D3D4DD;
background: #8F8FA2;
text-align: center;
margin-bottom: 0.75rem;
-webkit-transition: all .4s ease;
Expand All @@ -39,6 +39,7 @@ exports[`should accept "style" prop 1`] = `

.emotion-2 {
font-weight: bold;
color: #24252E;
-webkit-transition: all .4s ease;
transition: all .4s ease;
}
Expand Down Expand Up @@ -133,7 +134,7 @@ exports[`should allow override of components 1`] = `
width: 1rem;
height: 1rem;
border-radius: 50%;
background: #D3D4DD;
background: #8F8FA2;
text-align: center;
margin-bottom: 0.75rem;
-webkit-transition: all .4s ease;
Expand All @@ -148,6 +149,7 @@ exports[`should allow override of components 1`] = `

.emotion-3 {
font-weight: bold;
color: #24252E;
-webkit-transition: all .4s ease;
transition: all .4s ease;
}
Expand Down Expand Up @@ -293,6 +295,7 @@ exports[`should render correctly when status is completed 1`] = `

.emotion-3 {
font-weight: bold;
color: #24252E;
-webkit-transition: all .4s ease;
transition: all .4s ease;
}
Expand Down Expand Up @@ -366,6 +369,120 @@ exports[`should render correctly when status is completed 1`] = `
</div>
`;

exports[`should render correctly when status is inactive 1`] = `
.emotion-5 {
position: relative;
-webkit-flex: 1;
-ms-flex: 1;
flex: 1;
display: -webkit-box;
display: -webkit-flex;
display: -ms-flexbox;
display: flex;
-webkit-flex-direction: column;
-ms-flex-direction: column;
flex-direction: column;
-webkit-align-items: center;
-webkit-box-align: center;
-ms-flex-align: center;
align-items: center;
text-align: center;
padding: 0 0.5rem;
}

.emotion-3 {
z-index: 1;
display: -webkit-box;
display: -webkit-flex;
display: -ms-flexbox;
display: flex;
-webkit-align-items: center;
-webkit-box-align: center;
-ms-flex-align: center;
align-items: center;
-webkit-box-pack: center;
-webkit-justify-content: center;
-ms-flex-pack: center;
justify-content: center;
width: 1rem;
height: 1rem;
border-radius: 50%;
background: #8F8FA2;
text-align: center;
margin-bottom: 0.75rem;
-webkit-transition: all .4s ease;
transition: all .4s ease;
}

.emotion-0 {
position: absolute;
top: 0.5rem;
left: calc(-50% + 0.5rem);
right: calc(50% + 0.5rem);
border-top-width: 2px;
border-top-style: dashed;
border-top-color: #D3D4DD;
-webkit-transition: all .4s ease;
transition: all .4s ease;
}

.emotion-4 {
font-weight: bold;
color: #AAAAB9;
-webkit-transition: all .4s ease;
transition: all .4s ease;
}

.emotion-2 {
width: 1rem;
height: 1rem;
display: -webkit-box;
display: -webkit-flex;
display: -ms-flexbox;
display: flex;
-webkit-align-items: center;
-webkit-box-align: center;
-ms-flex-align: center;
align-items: center;
-webkit-box-pack: center;
-webkit-justify-content: center;
-ms-flex-pack: center;
justify-content: center;
}

.emotion-1 {
width: 6px;
height: 2px;
background: #FFFFFF;
}

<div>
<span
class="emotion-5"
>
<span
class="emotion-0"
/>
<span
class="emotion-3"
>
<div
class="emotion-2"
>
<div
class="emotion-1"
/>
</div>
</span>
<span
class="emotion-4"
>
Inactive step
</span>
</span>
</div>
`;

exports[`should render correctly when status is incompleted 1`] = `
.emotion-3 {
position: relative;
Expand Down Expand Up @@ -416,7 +533,7 @@ exports[`should render correctly when status is incompleted 1`] = `
width: 1rem;
height: 1rem;
border-radius: 50%;
background: #D3D4DD;
background: #8F8FA2;
text-align: center;
margin-bottom: 0.75rem;
-webkit-transition: all .4s ease;
Expand All @@ -425,6 +542,7 @@ exports[`should render correctly when status is incompleted 1`] = `

.emotion-2 {
font-weight: bold;
color: #24252E;
-webkit-transition: all .4s ease;
transition: all .4s ease;
}
Expand Down
2 changes: 1 addition & 1 deletion src/components/Stepper/index.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,3 @@
export { Stepper, StepperProps } from './Stepper'
export { Step, StepProps } from './Step'
export { Step, StepProps, StepStatus } from './Step'
export { getStepProps, useStepperState } from './useStepperState'
Loading