Introduction
Let us continue building our chakra components using styled-components
& styled-system
. In this tutorial we will be cloning the Chakra UI Spinner
component.
- I would like you to first check the chakra docs for spinner.
- We will compose (extend) our
Box
component to create theSpinner
component and add some more styles and a size variant. - All the code for this tutorial can be found here under the atom-feedback-spinner branch.
Prerequisite
Please check the previous post where we have completed the Heading Component. Also please check the Chakra Spinner Component code here. Check the theme and styles for the Spinner Component here.
In this tutorial we will -
- Create a Spinner component.
Setup
- First let us create a branch, from the main branch run -
git checkout -b atom-feedback-spinner
Under the
components/atoms
folder create a new folder called feedback. Under feedback folder create 2 filesindex.ts
andspinner.tsx
.So our folder structure stands like - src/components/atoms/feedback.
Spinner Component
If you did read and try out chakra's Spinner component you know what we need here. We need to handle the size of the Spinner, the color, its speed and also an emptyColor property.
Let me paste the code -
import * as React from "react";
import styled, { css, keyframes } from "styled-components";
import { variant as variantFun, ResponsiveValue } from "styled-system";
import { Box, BoxProps } from "../layout";
import { VisuallyHiddenText } from "../typography";
const spin = keyframes`
0% {
transform: rotate(0deg);
}
100% {
transform: rotate(360deg);
}
`;
type SpinnerSize = "xs" | "sm" | "md" | "lg" | "xl";
interface SpinnerOptions {
emptyColor?: string;
thickness?: string;
speed?: string;
label?: string;
variant?: ResponsiveValue<SpinnerSize>;
}
export interface SpinnerProps
extends Omit<BoxProps, keyof SpinnerOptions>,
SpinnerOptions {}
const animation = (speed = "0.45s") => css`
${spin} ${speed} linear infinite;
`;
const BaseSpinner = styled(Box)<SpinnerProps>`
animation: ${({ speed }) => animation(speed)};
width: 1em;
height: 1em;
${variantFun({
prop: "variant",
variants: {
xs: {
width: "1.5rem",
height: "1.5rem",
},
sm: {
width: "2rem",
height: "2rem",
},
md: {
width: "2.5rem",
height: "2.5rem",
},
lg: {
width: "3rem",
height: "3rem",
},
xl: {
width: "3.5rem",
height: "3.5rem",
},
},
})}
`;
export const Spinner = React.forwardRef<HTMLDivElement, SpinnerProps>(
(props, ref) => {
const {
label = "Loading....",
thickness = "2px",
emptyColor = "transparent",
color,
...delegated
} = props;
const spinnerStyles = {
display: "inline-block",
borderColor: "currentColor",
borderStyle: "solid",
borderRadius: "99999px",
borderWidth: thickness,
borderBottomColor: emptyColor,
borderLeftColor: emptyColor,
color,
};
return (
<BaseSpinner ref={ref} {...spinnerStyles} {...delegated}>
{label && <VisuallyHiddenText>{label}</VisuallyHiddenText>}
</BaseSpinner>
);
}
);
First thing to notice, we are using the animation function from styled-components. We are passing in the speed parameter, which we can now control via props.
Second thing to notice, we introduced a prop called variant by which we control the size of the Spinner component. The prop is named variant so that it does not conflict with the styled-system
size prop
.Third the use of
VisuallyHiddenText
which we created in the Text component tutorial. It will be used by screen readers, pass some meaningful accessible text using the label prop.Fourth thing, we are passing the color prop and using the CSS "currentColor" property, this will make the borderColor = color.
Build the Library
- Under the
/feedback/index.ts
file and paste the following -
export * from "./spinner";
- Under the
/atom/index.ts
file and paste the following -
export * from "./layout";
export * from "./typography";
export * from "./feedback";
Now
npm run build
.Under the folder
example/src/App.tsx
we can test ourSpinner
component. Copy paste the following code and runnpm run start
from theexample
directory.
import * as React from "react";
import { Stack, Spinner } from "chakra-ui-clone";
export function App() {
return (
<Stack spacing="lg">
<Spinner variant="xs" />
<Spinner variant="sm" />
<Spinner variant="md" />
<Spinner variant="lg" />
<Spinner variant="xl" />
<Spinner variant="sm" color="red500" />
<Spinner
thickness="4px"
speed="0.65s"
emptyColor="gray200"
color="blue500"
variant="xl"
/>
</Stack>
);
}
Summary
There you go guys in this tutorial we created Spinner component just like chakra ui. You can find the code for this tutorial under the atom-feedback-spinner branch here. In the next tutorial we will create Icon component. Until next time PEACE.
Top comments (0)