Install and Setup Chakra UI in a React Project
npx create-next-app --ts
# or
yarn create next-app --typescript
yarn add @chakra-ui/react @emotion/react@^11 @emotion/styled@^11 framer-motion@^4
AppProps is a type that is given to us by Next.js and Typescript.
import { AppProps } from 'next/app';
const App = () => {
};
export default App;
const App = ({ Component, pageProps }: AppProps) => {
return <Component {...pageProps} />
};
import { ChakraProvider } from '@chakra-ui/react';
const App = ({ Component, pageProps }: AppProps) => {
return
<ChakraProvider>
<Component {...pageProps} />
</ChakraProvider>
};
Build a Layout with the Container, Flex and VStack Component in Chakra UI
Figma is a vector graphics editor and prototyping tool which is primarily web-based, with additional offline features enabled by desktop applications for macOS and Windows.
Containers are used to constrain a content's width to the current breakpoint while keeping it fluid.
import { Container } from '@chakra-ui/react';
const IndexPage = () => (
<Container>
</Container>
)
Style props are a way to alter the style of a component by simply passing props to it.
The sizes key allows you to customize the global sizing of components you build for your project.
const IndexPage = () => (
<Container maxWidth="container.xl" padding={0}>
</Container>
)
Flex is Box with display: flex
and comes with helpful style shorthand. It renders a div
element.
import { Container, Flex } from '@chakra-ui/react';
const IndexPage = () => (
<Container maxWidth="container.xl" padding={0}>
<Flex h="100vh" py={20}>
</Flex>
</Container>
)
VStack is used to add spacing between elements in vertical direction only, and centers them.
import { Container, Flex, VStack } from '@chakra-ui/react';
const IndexPage = () => (
<Container maxWidth="container.xl" padding={0}>
<Flex h="100vh" py={20}>
<VStack
w="full"
h="full"
p={10}
spacing={10}
alignItems="flex-start"
></VStack>
</Flex>
</Container>
)
const IndexPage = () => (
<Container maxWidth="container.xl" padding={0}>
<Flex h="100vh" py={20}>
<VStack
w="full"
h="full"
p={10}
spacing={10}
alignItems="flex-start"
></VStack>
<VStack
w="full"
h="full"
p={10}
spacing={10}
alignItems="flex-start"
bg="gray.50"
></VStack>
</Flex>
</Container>
)
Build a 2-Column Form with the SimpleGrid, FormControl, and Input Component in Chakra UI
Headings are used for rendering headlines.
import { VStack, Heading } from '@chakra-ui/react';
const Details = () => {
return (
<VStack w="full" h="full" p={10} spacing={10} alignItems="flex-start">
<Heading size="2xl">Your details</Heading>
</VStack>
)
}
Text component is the used to render text and paragraphs within an interface.
import { VStack, Heading, Text } from '@chakra-ui/react';
<Heading size="2xl">Your details</Heading>
<Text>If you already have an account, click here to log in.</Text>
Overriding a parent's styling is quite easy in Chakra UI. To override the parent's spacing
, we can wrap our Heading
and our Text
in another VStack
and set spacing={3}
. In existing react components, trying to override them may force you to restyle your parent components along with their internals.
Create a Dark Mode Switcher in Chakra UI
useColorMode is a React hook that gives you access to the current color mode, and a function to toggle the color mode.
const Cart = () => {
const { toggleColorMode } = useColorMode();
...
<Button onClick={toggleColorMode} variant="link" colorScheme="black">
try changing the theme.
</Button>
}
useColorModeValue is a React hook used to change any value or style based on the color mode. It takes 2 arguments: the value in light mode, and the value in dark mode.
const bgColor = useColorModeValue("gray.50", "whiteAlpha.50")
<VStack
w="full"
h="full"
p={10}
spacing={6}
align="Flex-start"
bg={bgColor}
>
const secondaryTextColor = useColorModeValue("gray.600", "gray.400")
<Text color="gray.600">
// turns into
<Text color={secondaryTextColor}>
<VStack spacing={3} alignItems="flex-start">
<Heading size="2xl">Your details</Heading>
<Text>If you already have an account, click here to log in.</Text>
</VStack>
Grid is a primitive useful for grid layouts. Grid is Box
with display: grid
and it comes with helpful style shorthand. It renders a div
element.
import { VStack, Heading, Text, SimpleGrid, GridItem } from '@chakra-ui/react';
<SimpleGrid columns={2} columnGap={3} rowGap={6} w="full">
</SimpleGrid>
FormControl provides context such as isInvalid
, isDisabled
, and isRequired
to form elements. Since our SimpleGrid
is two columns, we can make one of our inputs only take up one of those columns using colSpan={1}
.
import { ..., FormControl, FormLabel, Input } from '@chakra-ui/react';
<SimpleGrid columns={2} columnGap={3} rowGap={6} w="full">
<GridItem colSpan={1}>
<FormControl>
<FormLabel>First Name</FormLabel>
<Input placeholder="John"/>
</FormControl>
</GridItem>
</SimpleGrid>
<GridItem colSpan={1}>
<FormControl>
<FormLabel>Last Name</FormLabel>
<Input placeholder="Doe"/>
</FormControl>
</GridItem>
<GridItem colSpan={2}>
<FormControl>
<FormLabel>Address</FormLabel>
<Input placeholder="Blvd. Broken Dreams 21"/>
</FormControl>
</GridItem>
<GridItem colSpan={1}>
<FormControl>
<FormLabel>City</FormLabel>
<Input placeholder="San Francisco"/>
</FormControl>
</GridItem>
Select component is a component that allows users pick a value from predefined options. Ideally, it should be used when there are more than 5 options, otherwise you might consider using a radio group instead.
import { ..., Select } from '@chakra-ui/react';
<GridItem colSpan={1}>
<FormControl>
<FormLabel>City</FormLabel>
<Select>
<option value="usa">United States of America</option>
<option value="uae">United Arab Emirates</option>
<option value="nmk">North Macedonia</option>
<option value="de">Germany</option>
</Select>
</FormControl>
</GridItem>
The Checkbox component is used in forms when a user needs to select multiple values from several options.
import { ..., Checkbox, Button } from '@chakra-ui/react';
<GridItem colSpan={2}>
<CheckBox defaultChecked>Ship to billing address.</CheckBox>
</GridItem>
<GridItem colSpan={2}>
<Button size="lb" w="full">
Place Order
</Button>
</GridItem>
Implement Responsive Design in Chakra UI
All style props accept arrays as values for mobile-first responsive styles. This is known as The Array syntax.
This means that in our array, we get 0 from 0 to 479 pixels, 10 from 480 pixels until 767 pixels, and then 20 from 768 pixels and up.
<Flex h="100vh" py={[0, 10, 20]}>
<Details />
<Cart />
</Flex>
By using Responsive Direction, we can pass responsive values to our Flex
component to change the stack direction and/or the spacing between our elements.
<Flex
h="100vh"
py={[0, 10, 20]}
direction={{ base: 'column-reverse', md: 'row' }}
>
<Details />
<Cart />
</Flex>
<Flex
h={{ base: 'auto', md: '100vh' }}
py={[0, 10, 20]}
direction={{ base: 'column-reverse', md: 'row' }}
>
<Details />
<Cart />
</Flex>
The useBreakpointValue is a custom hook which returns the value for the current breakpoint from the provided responsive values object. This hook also responds to the window resizing and returning the appropriate value for the new window size.
import { ..., useBreakpointValue } from '@chakra-ui/react';
const colSpan = useBreakpointValue({ base: 2, md: 1 });
<GridItem colSpan={1}>
// All of them will now be....
<GridItem colSpan={colSpan}>
Define Custom Colors and Fonts in Chakra UI
By default, all Chakra components inherit values from the default theme. In some scenarios, you might need to customize the theme tokens to match your design requirements. This is where extendTheme comes in to play.
import { extendTheme} from '@chakra-ui/rect';
const theme = extendTheme({});
export default theme;
import theme from '../src/theme';
const App = ({ Component, pageProps }: AppProps) => {
return (
<ChakraProvider theme={theme}>
<Component {...pageProps}>
</ChakraProvider>
)
}
const theme = extendTheme({
fonts: {
heading: 'Montserrat',
body: 'Inter',
}
});
import { ..., theme as base } from '@chakra-ui/rect';
const theme = extendTheme({
fonts: {
heading: `Montserrat, ${base.fonts?.heading}`,
body: `Inter, ${base.fonts?.body}`,
}
});
@import url('https://fonts.googleapis.com/css2?family=Inter:wght@400;500;600&family=Montserrat:wght@700&display=swap');
colors: {
brand: {
50: '#f5fee5',
100: '#e1fbb2',
200: '#cdf781',
300: '#b8ee56',
400: '#a2e032',
500: '#8ac919',
600: '#71ab09',
700: '#578602',
800: '#3c5e00',
900: '#203300',
},
},
<Button colorScheme="brand" size="lg" w="full">
Place Order
</Button>
Use Theme Extensions in Chakra UI
withDefaultColorScheme does exactly what is in the name, sets a default color scheme to all of your components. It takes an object where you can set your colorScheme
to a color, and you can set it to specifically focus on certain components such as Button
or Badge
.
Most components in Chakra UI have default styling. Variants are one way we can override those default settings and set certain components to have a different visual styles. withDefaultVariant is how we handle our variants.
withDefaultColorScheme({
colorScheme: 'brand',
components: ['Checkbox'],
})
withDefaultVariant({
variant: 'filled',
components: ['Input', 'Select'],
})
Override the Built-in Component's Styles in Chakra UI
Continuing on how we override the default styling of our components, without using any theme extensions, we are going to use the basic API for this.
export default {
// Styles for the base style
baseStyle: {},
// Styles for the size variations
sizes: {},
// Styles for the visual style variations
variants: {},
// The default `size` or `variant` values
defaultProps: {},
}
components: {
Input: {
sizes: {
md: {
field: {
borderRadius: 'none',
}
}
}
},
},
variants: {
filled: {
field: {
_focus: {
borderColor: 'brand.500',
},
},
},
},
Checkbox: {
baseStyle: {
control: {
borderRadius: 'none',
_focus: {
ring: 2,
ringColor: 'brand.500',
}
}
}
}
Create Custom Variants in Chakra UI
Just like we edited the styling of our components in the last two lessons, we are going to do the same to our variants to create our own custom variants. Just make sure to use the variant
prop on your components in your details.tsx file and set it to what you named your variant, in our case primary
.
Button: {
variants: {
primary: {
rounded: 'none',
},
},
},
Button: {
variants: {
primary: (props) => ({
rounded: 'none',
...brandRing,
backgroundColor: mode('brand.500', 'brand.200')(props),
}),
},
},
Button: {
variants: {
primary: (props) => ({
rounded: 'none',
...brandRing,
backgroundColor: mode('brand.500', 'brand.200')(props),
_hover: {
backgroundColor: mode('brand.600', 'brand.300')(props),
},
_active: {
backgroundColor: mode('brand.700', 'brand.400')(props),
},
}),
},
},
Button: {
variants: {
primary: (props) => ({
rounded: 'none',
...brandRing,
color: mode('white', 'gray.800')(props),
backgroundColor: mode('brand.500', 'brand.200')(props),
_hover: {
backgroundColor: mode('brand.600', 'brand.300')(props),
},
_active: {
backgroundColor: mode('brand.700', 'brand.400')(props),
},
}),
},
},
Top comments (0)