Skip to content

Commit

Permalink
feat(component): add Stepper component
Browse files Browse the repository at this point in the history
  • Loading branch information
Ricardo Figueroa committed Feb 25, 2021
1 parent f32f888 commit ee08d97
Show file tree
Hide file tree
Showing 13 changed files with 700 additions and 0 deletions.
52 changes: 52 additions & 0 deletions packages/big-design/src/components/Stepper/Step/Step.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
import { CheckIcon } from '@bigcommerce/big-design-icons';
import React, { memo } from 'react';

import { StyledDash, StyledLight, StyledSrOnlyText, StyledStep, StyledText } from './styled';

interface StepProps {
index: number;
selectedIndex: number;
stepperLength: number;
text: string;
}

export const Step: React.FC<StepProps> = memo(({ index, selectedIndex, stepperLength, text }) => {
const isComplete = selectedIndex > index;
const isSelected = selectedIndex === index;
const isActive = isSelected || isComplete;

return (
<StyledStep
display={{ mobile: isSelected ? 'grid' : 'none', tablet: 'grid' }}
marginRight={{ tablet: 'xSmall' }}
marginBottom="xLarge"
>
<StyledLight
alignItems="center"
backgroundColor={isActive ? 'primary' : 'secondary50'}
flexDirection="row"
justifyContent="center"
paddingHorizontal={{ mobile: 'xSmall', tablet: 'none' }}
paddingVertical={{ mobile: 'xxSmall', tablet: 'none' }}
>
{isComplete ? (
<CheckIcon color="white" size="large" />
) : (
// span is needed to preserve white space inside a flex container
<span>
<StyledSrOnlyText>Step</StyledSrOnlyText>
{` ${index + 1} `}
<StyledSrOnlyText>of {stepperLength}</StyledSrOnlyText>
</span>
)}
</StyledLight>
<StyledDash
display={{ mobile: 'none', tablet: index === stepperLength - 1 ? 'none' : 'block' }}
backgroundColor={isComplete ? 'primary' : 'secondary30'}
/>
<StyledText color={isActive ? 'secondary70' : 'secondary50'}>{text}</StyledText>
</StyledStep>
);
});

Step.displayName = 'Step';
1 change: 1 addition & 0 deletions packages/big-design/src/components/Stepper/Step/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
export { Step } from './Step';
60 changes: 60 additions & 0 deletions packages/big-design/src/components/Stepper/Step/styled.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
import { theme as defaultTheme } from '@bigcommerce/big-design-theme';
import { hideVisually } from 'polished';
import styled from 'styled-components';

import { Box } from '../../Box';
import { Flex } from '../../Flex';
import { Grid } from '../../Grid';
import { StyleableText } from '../../Typography/private';

export const StyledStep = styled(Grid)`
flex-basis: 100%;
gap: ${({ theme }) => theme.spacing.xSmall};
grid-template-areas:
'light dash'
'text text';
grid-template-columns: auto 1fr;
${({ theme }) => theme.breakpoints.tablet} {
grid-template-columns: ${({ theme }) => theme.spacing.xLarge} 1fr;
grid-template-rows: ${({ theme }) => theme.spacing.xLarge} 1fr;
max-width: ${({ theme }) => theme.helpers.remCalc(228)};
min-width: ${({ theme }) => theme.helpers.remCalc(96)};
}
`;

export const StyledSrOnlyText = styled.span`
${({ theme }) => theme.breakpoints.tablet} {
${hideVisually()}
}
`;

export const StyledLight = styled(Flex)`
border-radius: ${({ theme }) => theme.spacing.medium};
color: ${({ theme }) => theme.colors.white};
grid-area: light;
user-select: none;
${({ theme }) => theme.breakpoints.tablet} {
border-radius: ${({ theme }) => theme.borderRadius.circle};
font-size: ${({ theme }) => theme.typography.fontSize.medium};
line-height: ${({ theme }) => theme.lineHeight.medium};
}
`;

export const StyledDash = styled(Box)`
align-self: center;
height: ${({ theme }) => theme.helpers.remCalc(2)};
grid-area: dash;
width: 100%;
`;

export const StyledText = styled(StyleableText)`
grid-area: text;
`;

StyledStep.defaultProps = { theme: defaultTheme };
StyledSrOnlyText.defaultProps = { theme: defaultTheme };
StyledLight.defaultProps = { theme: defaultTheme };
StyledDash.defaultProps = { theme: defaultTheme };
StyledText.defaultProps = { theme: defaultTheme };
35 changes: 35 additions & 0 deletions packages/big-design/src/components/Stepper/Stepper.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
import React, { HTMLAttributes, memo } from 'react';

import { Flex } from '../Flex';

import { Step } from './Step';

export interface StepperProps extends HTMLAttributes<HTMLDivElement> {
steps: Array<string>;
currentStep: number;
}

export const Stepper: React.FC<StepperProps> = memo(({ className, style, steps, currentStep, ...props }) => (
<Flex
{...props}
aria-valuenow={currentStep + 1}
aria-valuemin={0}
aria-valuemax={steps.length}
aria-valuetext={`Step ${currentStep + 1}: ${steps[currentStep]}`}
flexDirection="row"
flexWrap="nowrap"
marginBottom="xLarge"
role="progressbar"
>
{steps.map((text, index) => (
<Step index={index} selectedIndex={currentStep} stepperLength={steps.length} text={text} key={index} />
))}
</Flex>
));

Stepper.defaultProps = {
steps: [],
currentStep: 0,
};

Stepper.displayName = 'Stepper';
Loading

0 comments on commit ee08d97

Please sign in to comment.