Skip to content

Commit

Permalink
fix: stepper styling
Browse files Browse the repository at this point in the history
  • Loading branch information
ankitskvmdam committed Oct 14, 2021
1 parent 263e556 commit cc013b4
Show file tree
Hide file tree
Showing 2 changed files with 171 additions and 49 deletions.
84 changes: 73 additions & 11 deletions src/stepper/stepper.stories.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,13 @@ import { Box } from '../box'
import { Button } from '../button'

import { Stepper, StepsType, StepStatus } from './stepper'
import { StepStatusEnum } from '.'
import { StepStatusEnum } from './stepper'

import UploadIcon from '../icons/System/upload-line'
import MapIcon from '../icons/Map/guide-fill'
import SupplementaryIcon from '../icons/Business/donut-chart-fill'
import ConfigureIcon from '../icons/Design/tools-fill'
import SaveIcon from '../icons/Device/save-3-fill'

export default {
title: 'Stepper',
Expand All @@ -13,24 +19,32 @@ export default {

const steps: StepsType[] = [
{
title: 'Step 1',
description: ' This is step 1',
title: 'Upload files',
description:
'Files we can accepts include: gff, fasta, .tsv, .csv, .etc.',
},
{
title: 'Step 2',
description: 'This is step 2.',
title: 'Map Columns',
},
{
title: 'Step 3',
description: 'This is step 3.',
title: 'Supplementary Data',
description: (
<Box>
Based on your uploaded data, we have couple of question for you.
Also in this section you can enable and disable default
settings.
</Box>
),
},
{
title: 'Step 4',
description: 'This is step 4.',
title: 'Configure Settings',
description:
'Brilliant!, Nearly done. In this section we would like to ask some question on how you want to publish your new mine.',
},
{
title: 'Step 5',
description: 'This is step 5.',
title: 'Finalise And Save',
description:
'Almost Done. This section is to review your work. If you are okay, then you can upload and save.',
},
]

Expand Down Expand Up @@ -128,3 +142,51 @@ RandomStepStatus.args = {
steps,
color: 'secondary',
}

const steps2: StepsType[] = [
{
title: 'Upload files',
description:
'Files we can accepts include: gff, fasta, .tsv, .csv, .etc.',
AvatarIcon: <UploadIcon />,
CompleteIcon: <UploadIcon />,
},
{
title: 'Map Columns',
description:
'Map you header rows, map entries. Give us information about sequence features.',
AvatarIcon: <MapIcon />,
CompleteIcon: <MapIcon />,
},
{
title: 'Supplementary Data',
description: (
<Box>
Based on your uploaded data, we have couple of question for you.
Also in this section you can enable and disable default
settings.
</Box>
),
AvatarIcon: <SupplementaryIcon />,
CompleteIcon: <SupplementaryIcon />,
},
{
AvatarIcon: <ConfigureIcon />,
CompleteIcon: <ConfigureIcon />,
title: 'Configure Settings',
description:
'Brilliant!, Nearly done. In this section we would like to ask some question on how you want to publish your new mine.',
},
{
AvatarIcon: <SaveIcon />,
CompleteIcon: <SaveIcon />,
title: 'Finalise And Save',
description:
'Almost Done. This section is to review your work. If you are okay, then you can upload and save.',
},
]

export const WithCustomIcons = Template.bind({})
WithCustomIcons.args = {
steps: steps2,
}
136 changes: 98 additions & 38 deletions src/stepper/stepper.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,12 @@ export type StepsType = {
*/
id?: string
}
export type StepStatusEnum = 'complete' | 'error' | 'warning' | 'none'
export type StepStatusEnum =
| 'complete'
| 'error'
| 'warning'
| 'none'
| 'current'
export type StepStatus = { [k: number]: StepStatusEnum }

export interface StepperProps
Expand Down Expand Up @@ -87,6 +92,10 @@ export interface StepperProps
* Applied to title
*/
title?: string
/**
* Applied to avatar and title container
*/
avatarAndTitleContainer?: string
/**
* Applied to description
*/
Expand Down Expand Up @@ -116,6 +125,10 @@ export interface StepperProps
* Applied to title
*/
title?: ThemeCSSStyles
/**
* Applied to avatar and title container
*/
avatarAndTitleContainer?: string
/**
* Applied to description
*/
Expand All @@ -132,7 +145,8 @@ const getThemeColorBasedOnStatus = (
status: StepStatusEnum,
palette: ThemePalette
): string => {
if (status === 'complete') return palette.primary[type]
if (status === 'complete' || status === 'current')
return palette.primary[type]
if (status === 'warning') return palette.warning[type]
if (status === 'error') return palette.error[type]

Expand All @@ -143,25 +157,16 @@ type AvatarProps = {
children?: ReactElement
alignment?: StepperProps['alignment']
status: StepStatusEnum
isActive: boolean
}

const Avatar = createStyledComponent<typeof Box, AvatarProps>(
Box,
(theme, props) => {
const { csx = {}, alignment, status, isActive } = props
const { csx = {}, alignment, status } = props
const { palette } = theme

const background = getThemeColorBasedOnStatus(
'main',
isActive ? 'complete' : status,
palette
)
const color = getThemeColorBasedOnStatus(
'text',
isActive ? 'complete' : status,
palette
)
const background = getThemeColorBasedOnStatus('main', status, palette)
const color = getThemeColorBasedOnStatus('text', status, palette)
return {
alignItems: 'center',
background,
Expand All @@ -174,6 +179,7 @@ const Avatar = createStyledComponent<typeof Box, AvatarProps>(
justifyContent: 'center',
margin: alignment === 'vt' ? '0 1.5rem 0 0' : '0 0 1rem 0',
padding: '0.5rem',
transition: '0.230s',
width: '2rem',
...getThemeCSSObject(csx.root, theme),
}
Expand All @@ -184,14 +190,38 @@ const getAvatarIcon = (
status: StepStatusEnum,
props: Partial<StepsType>
): ReactElement => {
if (!status || status === 'none') return props.AvatarIcon
if (!status || status === 'none' || status === 'current')
return props.AvatarIcon
if (status === 'complete') return props.CompleteIcon
if (status === 'warning') return props.WarningIcon
if (status === 'error') return props.ErrorIcon

return props.AvatarIcon
}

type AvatarAndTitleContainerProps = {
alignment: StepperProps['alignment']
}

const AvatarAndTitleContainer = createStyledComponent<
typeof Box,
AvatarAndTitleContainerProps
>(
Box,
(theme, props) => {
const { alignment, csx = {} } = props

return {
alignItems: 'center',
padding: '0.5rem',
display: 'flex',
flexDirection: alignment === 'vt' ? 'row' : 'column',
...getThemeCSSObject(csx.root, theme),
}
},
{ isExtendStyleFromThemeVars: false }
)

type StepContainerProps = {
children?: ReactElement
alignment?: StepperProps['alignment']
Expand All @@ -200,11 +230,13 @@ type StepContainerProps = {
const StepContainer = createStyledComponent<typeof Box, StepContainerProps>(
Box,
(theme, props) => {
const { csx = {}, alignment = 'vt' } = props
const { csx = {} } = props

return {
display: 'inline-flex',
flex: 1,
flexDirection: 'column',
maxWidth: '25rem',
...getThemeCSSObject(csx.root, theme),
}
}
Expand All @@ -226,12 +258,14 @@ const DescriptionContainer = createStyledComponent<
} = theme
const { alignment, csx = {}, isLast } = props
return {
marginLeft: alignment === 'vt' ? '1.5rem' : '0',
paddingLeft: alignment === 'vt' ? '2.5rem' : '0',
color: neutral[80],
borderLeft:
alignment === 'vt' && !isLast
? `0.0625rem solid ${neutral.main}`
: '0',
marginLeft: alignment === 'vt' ? '1.5rem' : '0',
paddingLeft: alignment === 'vt' ? '2.5rem' : '0',
textAlign: alignment === 'hr' ? 'center' : undefined,
...getThemeCSSObject(csx.root, theme),
}
},
Expand Down Expand Up @@ -266,13 +300,14 @@ const DividerRoot = createStyledComponent<typeof Divider, DividerRootProps>(
return {
borderColor: getThemeColorBasedOnStatus(
'main',
status,
status === 'current' ? 'none' : status,
theme.palette
),
display: isLast ? 'none' : undefined,
flex: 1,
marginLeft: alignment === 'vt' ? '1.5rem' : '0',
marginTop: alignment === 'vt' ? '0' : '1.5rem',
transition: '0.230s',
...getDimension(),
...getThemeCSSObject(csx.root, theme),
}
Expand Down Expand Up @@ -317,6 +352,38 @@ export const Stepper = (props: StepperProps): JSX.Element => {
...rest
} = props

const getTitle = (
title: ReactElement,
status: StepStatusEnum
): ReactElement => {
if (typeof title === 'string') {
return (
<Typography
variant="title"
className={cx(classes.title)}
csx={{
root: (theme) => ({
color:
status === 'none' || !status
? theme.palette.neutral[70]
: theme.palette.neutral[90],
...getThemeCSSObject(csx.title, theme),
}),
}}
>
{title}
</Typography>
)
}
return title
}

const getStatus = (idx: number, activeStep: number): StepStatusEnum => {
if (stepsStatus[idx + 1]) return stepsStatus[idx + 1]
if (activeStep === idx + 1) return 'current'
return 'none'
}

return (
<StepperContainer
className={cx(className, classes.root)}
Expand All @@ -335,28 +402,21 @@ export const Stepper = (props: StepperProps): JSX.Element => {
id = typeof title === 'string' ? title : idx,
} = step

const _status = getStatus(idx, activeStep)
return (
<>
<StepContainer alignment={alignment} key={id}>
<Box
csx={{
root: {
alignItems: 'center',
padding: '0.5rem',
display: 'flex',
flexDirection:
alignment === 'vt'
? 'row'
: 'column',
},
}}
>
<StepContainer
classes={{ root: classes.stepContainer }}
csx={{ root: csx.stepContainer }}
alignment={alignment}
key={id}
>
<AvatarAndTitleContainer alignment={alignment}>
<Avatar
alignment={alignment}
csx={{ root: csx.avatar }}
className={cx(classes.avatar)}
status={stepsStatus[idx + 1] ?? 'none'}
isActive={idx + 1 == activeStep}
status={_status}
>
{getAvatarIcon(stepsStatus[idx + 1], {
CompleteIcon: _CompleteIcon,
Expand All @@ -365,8 +425,8 @@ export const Stepper = (props: StepperProps): JSX.Element => {
AvatarIcon,
})}
</Avatar>
{title}
</Box>
{getTitle(title, _status)}
</AvatarAndTitleContainer>
<DescriptionContainer
alignment={alignment}
isOpen={activeStep === idx + 1}
Expand All @@ -381,7 +441,7 @@ export const Stepper = (props: StepperProps): JSX.Element => {
isLast={idx + 1 === steps.length}
csx={{ root: csx.divider }}
classes={{ root: classes.divider }}
status={stepsStatus[idx + 1] ?? 'none'}
status={_status}
alignment={alignment}
/>
</>
Expand Down

0 comments on commit cc013b4

Please sign in to comment.