Introduction
Let us continue building our chakra components using styled-components
& styled-system
. Chakra UI has some pretty neat container components namely Square, Center, Circle and Container
.
I would like you to first check the [chakra docs] for each of the components here.
We will compose (extend) our
Flex
component to create these components.All the code for this tutorial can be found here under the atom-layout-containers branch.
Prerequisite
Please check the previous post where we have completed the Stack Component. Also please check the Chakra Component code here. In this tutorial we will -
- Create a Square component.
- Create a Circle component.
- Create a Center component.
- Create a Container component.
- Create their respective stories.
Setup
- First let us create a branch, from the main branch run -
git checkout -b atom-layout-containers
Under the
components/atoms/layout
folder create a new folder called containers. Under containers folder create 2 filesindex.tsx
andcontainers.stories.tsx
.So our folder structure stands like - src/components/atoms/layout/containers.
Square Component
This component will center its child given size (width and height). We can also pass centerContent = false prop if we don't want to center content.
import * as React from "react";
import { Flex, FlexProps } from "../flex";
type SqureOmitted = "width" | "height" | "w" | "h";
export interface SquareProps extends Omit<FlexProps, SqureOmitted> {
centerContent?: boolean;
}
export const Square = React.forwardRef<HTMLDivElement, SquareProps>(
(props, ref) => {
const { size, centerContent = true, children, ...delegated } = props;
const squareProps = centerContent && {
align: "center",
justify: "center",
};
return (
<Flex
ref={ref}
size={size}
{...squareProps}
grow={0}
shrink={0}
{...delegated}
>
{children}
</Flex>
);
}
);
For simplicity we omitted height and width props instead simply pass the size prop.
Circle Component
We extend the Square Component with a round border radius so that it appears like a Circle, this will come handy if you want to display some icons under a circle.
export const Circle = React.forwardRef<HTMLDivElement, SquareProps>(
(props, ref) => {
const { size, children, ...delegated } = props;
return (
<Square ref={ref} size={size} {...delegated} borderRadius="9999px">
{children}
</Square>
);
}
);
Center Component
This component will center its child given width and height.
interface CenterProps
extends Omit<FlexProps, "display" | "align" | "justify"> {}
export const Center = React.forwardRef<HTMLDivElement, CenterProps>(
(props, ref) => {
const { children, ...delegated } = props;
return (
<Flex ref={ref} align="center" justify="center" {...delegated}>
{children}
</Flex>
);
}
);
Because as the name suggest this is a Center
component, we omit the alignItems and justifyContent props and by default pass these with center values.
Container Component
This component is used to constrain a content's width to the current breakpoint, while keeping it fluid. It sets margin-left
and margin-right
to auto
, to keep its content centered.
It also sets a default max-width of 60ch
(60 characters), but you can customize this by passing custom maxWidth value. We can also pass centerContent = true prop if we want to center content inside the container
.
export interface ContainerProps extends FlexProps {
centerContent?: boolean;
}
export const Container = React.forwardRef<HTMLDivElement, ContainerProps>(
(props, ref) => {
const { children, centerContent, ...delegated } = props;
const centerContentProps = centerContent && {
align: "center",
};
return (
<Flex
ref={ref}
width="100%"
mx="auto"
maxW="60ch"
px="10px"
direction="column"
{...centerContentProps}
{...delegated}
>
{children}
</Flex>
);
}
);
Story
- With the above our
Container
components are completed, let us create a story. - Under the
src/components/atoms/layout/containers/containers.stories.tsx
file we add the below story code. - We will create 3 stories - center, square, container.
import * as React from "react";
import { HStack, VStack } from "../stack";
import { Container, Square, Circle, Center } from ".";
export default {
title: "Atoms/Layout/Containers",
};
export const center = {
render: () => (
<Center bg="tomato" h="100px" color="white">
This is the Center
</Center>
),
};
export const square = {
render: () => (
<HStack spacing="4xl">
<Square size="40px" bg="tomato" color="white">
1
</Square>
<Square
as="span"
size="40px"
bg="tomato"
color="white"
centerContent={false}
>
2
</Square>
<Circle size="40px" bg="tomato" color="white">
3
</Circle>
</HStack>
),
};
export const container = {
render: () => (
<VStack spacing="4xl">
<Container color="white" p="md" bg="red500" maxW="900px">
Not Centered Content
</Container>
<Container p="md" bg="yellow200" maxW="900px" centerContent>
Centered Content
</Container>
</VStack>
),
};
Build the Library
- Under the
/layout/index.ts
file and paste the following -
export * from "./box";
export * from "./flex";
export * from "./stack";
export * from "./containers";
Now
npm run build
.Under the folder
example/src/App.tsx
we can test ourBox
component. Copy paste the following code and runnpm run start
from theexample
directory.
import * as React from "react";
import { HStack, Square, Circle } from "chakra-ui-clone";
export function App() {
return (
<HStack spacing="4xl">
<Square size="40px" bg="tomato" color="white">
1
</Square>
<Square
as="span"
size="40px"
bg="tomato"
color="white"
centerContent={false}
>
2
</Square>
<Circle size="40px" bg="tomato" color="white">
3
</Circle>
</HStack>
);
}
Summary
There you go guys in this tutorial we created Container
components just like chakra ui and stories for them. You can find the code for this tutorial under the atom-layout-containers branch here. In the next tutorial we will create Wrap and WrapItem components. Until next time PEACE.
Top comments (0)