diff --git a/src/stepper/stepper.stories.tsx b/src/stepper/stepper.stories.tsx index f0d4c539..bc91cc5e 100644 --- a/src/stepper/stepper.stories.tsx +++ b/src/stepper/stepper.stories.tsx @@ -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', @@ -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: ( + + Based on your uploaded data, we have couple of question for you. + Also in this section you can enable and disable default + settings. + + ), }, { - 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.', }, ] @@ -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: , + CompleteIcon: , + }, + { + title: 'Map Columns', + description: + 'Map you header rows, map entries. Give us information about sequence features.', + AvatarIcon: , + CompleteIcon: , + }, + { + title: 'Supplementary Data', + description: ( + + Based on your uploaded data, we have couple of question for you. + Also in this section you can enable and disable default + settings. + + ), + AvatarIcon: , + CompleteIcon: , + }, + { + AvatarIcon: , + CompleteIcon: , + 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: , + CompleteIcon: , + 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, +} diff --git a/src/stepper/stepper.tsx b/src/stepper/stepper.tsx index 96b6a52c..df3e84f8 100644 --- a/src/stepper/stepper.tsx +++ b/src/stepper/stepper.tsx @@ -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 @@ -87,6 +92,10 @@ export interface StepperProps * Applied to title */ title?: string + /** + * Applied to avatar and title container + */ + avatarAndTitleContainer?: string /** * Applied to description */ @@ -116,6 +125,10 @@ export interface StepperProps * Applied to title */ title?: ThemeCSSStyles + /** + * Applied to avatar and title container + */ + avatarAndTitleContainer?: string /** * Applied to description */ @@ -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] @@ -143,25 +157,16 @@ type AvatarProps = { children?: ReactElement alignment?: StepperProps['alignment'] status: StepStatusEnum - isActive: boolean } const Avatar = createStyledComponent( 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, @@ -174,6 +179,7 @@ const Avatar = createStyledComponent( 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), } @@ -184,7 +190,8 @@ const getAvatarIcon = ( status: StepStatusEnum, props: Partial ): 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 @@ -192,6 +199,29 @@ const getAvatarIcon = ( 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'] @@ -200,11 +230,13 @@ type StepContainerProps = { const StepContainer = createStyledComponent( 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), } } @@ -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), } }, @@ -266,13 +300,14 @@ const DividerRoot = createStyledComponent( 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), } @@ -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 ( + ({ + color: + status === 'none' || !status + ? theme.palette.neutral[70] + : theme.palette.neutral[90], + ...getThemeCSSObject(csx.title, theme), + }), + }} + > + {title} + + ) + } + 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 ( { id = typeof title === 'string' ? title : idx, } = step + const _status = getStatus(idx, activeStep) return ( <> - - + + {getAvatarIcon(stepsStatus[idx + 1], { CompleteIcon: _CompleteIcon, @@ -365,8 +425,8 @@ export const Stepper = (props: StepperProps): JSX.Element => { AvatarIcon, })} - {title} - + {getTitle(title, _status)} + { isLast={idx + 1 === steps.length} csx={{ root: csx.divider }} classes={{ root: classes.divider }} - status={stepsStatus[idx + 1] ?? 'none'} + status={_status} alignment={alignment} />