Skip to content

Instantly share code, notes, and snippets.

@tomaswitek
Created April 25, 2018 07:42
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save tomaswitek/af3d76c4f2d41db4323eb4f3a3f3bf8d to your computer and use it in GitHub Desktop.
Save tomaswitek/af3d76c4f2d41db4323eb4f3a3f3bf8d to your computer and use it in GitHub Desktop.
Stepper
import React from 'react';
import { colors } from '../../theme';
export interface CircleProps {
index: number;
active: boolean;
size?: number;
finished?: boolean;
}
/**
* Translates a given latin number to its roman equivalent.
*
* @param num latin number to translate.
*/
const toRoman = (num: number) => {
switch (num) {
case 1:
return 'I';
case 2:
return 'II';
case 3:
return 'III';
case 4:
return 'IV';
case 5:
return 'V';
default:
num.toString();
}
};
const Circle: React.SFC<CircleProps> = ({
finished,
active,
index,
size = 40,
}) => {
const bgColor = finished ? colors.green : colors.greyDark;
return (
<p className="circle">
{toRoman(index)}
<style jsx>{`
.circle {
background-color: ${bgColor};
border-radius: 100px;
width: ${size}px;
height: ${size}px;
color: white;
text-align: center;
font-size: 20px;
line-height: ${size}px;
box-shadow: 0px 0px 0px 5px
${active ? colors.grey : colors.transparent};
}
`}</style>
</p>
);
};
export default Circle;
import React from 'react';
import { colors, media } from '../../theme';
import { Link } from '../../routes';
import Circle from './Circle';
export interface StepOptions {
path: string;
finished?: boolean;
text?: string;
}
export interface StepProps {
index: number;
options: StepOptions;
active: boolean;
finished?: boolean;
size?: number;
}
export interface BaseStepProps extends StepProps {
color: string;
}
const Step: React.SFC<StepProps> = props => {
const LinkWrapper = ({ children }) =>
!!props.finished ? (
<Link route={props.options.path}>
<a style={{ display: 'flex' }}>{children}</a>
</Link>
) : (
<div style={{ display: 'flex', color: '#848484' }}>{children}</div>
);
return (
<li className="step">
<LinkWrapper>
<Circle {...props} />
<span>{props.options.text}</span>
</LinkWrapper>
<style jsx>{`
.step {
display: inline-block;
margin: 0 2%;
@media (${media.mobile}) {
margin: 0 5%;
}
&:hover {
:global(.circle) {
box-shadow: 0px 0px 0px 5px
${props.finished || props.active
? colors.grey
: colors.transparent};
}
}
}
span {
line-height: ${props.size || 40}px;
margin-left: 10px;
@media (${media.mobile}) {
display: none;
}
}
`}</style>
</li>
);
};
export default Step;
import React from 'react';
import Step, { StepOptions } from './Step';
export interface StepperProps {
steps: StepOptions[];
currentPath: string;
}
const Stepper: React.SFC<StepperProps> = ({ steps, currentPath }) => {
const currentIndex = steps.findIndex(s => s.path === currentPath);
return (
<ul className="stepper-container">
{steps.map((step, index) => {
return (
<Step
key={step.path}
options={step}
index={index + 1}
active={index === currentIndex}
finished={step.finished}
/>
);
})}
<style jsx>{`
.stepper-container {
list-style: none;
text-align: center;
padding: 0;
p {
margin: 0;
}
}
`}</style>
</ul>
);
};
export default Stepper;
@tomaswitek
Copy link
Author

This is how it looks like when I navigate via client side navigation (no SSR):
screen shot 2018-04-25 at 09 43 04

This is how it looks like when I refresh the page:
screen shot 2018-04-25 at 09 43 15

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment