Build a modern user interface with ChakraUI

Build a modern user interface with ChakraUI

·

8 min read

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),
      },
    }),
  },
},