Chakra UI: The Ultimate Cheat Sheet

Introduction to Chakra UI

Chakra UI is a simple, modular, and accessible component library that gives you the building blocks to create React applications with speed and consistency. It provides a set of professionally designed, composable, and reusable components built with accessibility in mind. Chakra UI matters because it combines the best practices of style systems like Tailwind with the convenience of component libraries like Material UI, all while maintaining a small bundle size and excellent developer experience.

Core Concepts and Principles

Style System Fundamentals

  • Theme-Based: All components use values from a centralized theme
  • Responsive Styles: Built-in responsive design system
  • Component Composition: Components can be combined and nested
  • Style Props: Inline styling with shorthand props
  • Color Mode: Built-in light and dark mode support
  • Accessibility: ARIA compliant with keyboard navigation

Style Props

Style props allow you to pass styles directly to components as props:

CategoryPropsExample
Marginm, mt, mr, mb, ml, mx, my<Box m="4" mt="2">
Paddingp, pt, pr, pb, pl, px, py<Box p="4" px="6">
Colorcolor, bg, bgColor, opacity<Text color="blue.500">
TypographyfontSize, fontWeight, letterSpacing<Text fontSize="xl">
Layoutwidth, height, display, minW, maxW<Box w="100%" maxW="500px">
Flexboxflex, flexDirection, justify, align<Flex justify="center">
GridgridGap, gridColumn, gridRow<Grid gridGap="4">
Borderborder, borderWidth, borderRadius<Box borderRadius="md">

Responsive Design System

Chakra UI uses array syntax for responsive styles:

// This sets different margins for different breakpoints
<Box m={[2, 4, 6, 8]}>
  Responsive margin
</Box>

// This is equivalent to:
// base: margin: 8px
// sm: margin: 16px
// md: margin: 24px
// lg: margin: 32px

You can also use object syntax:

<Box
  width={{
    base: "100%",   // 0-479px
    sm: "80%",      // 480-767px
    md: "60%",      // 768-991px
    lg: "40%",      // 992-1279px
    xl: "30%"       // 1280px+
  }}
>
  Responsive width
</Box>

Setup and Installation

Basic Setup with Create React App

# Create a new React app
npx create-react-app my-chakra-app
cd my-chakra-app

# Install Chakra UI and its peer dependencies
npm i @chakra-ui/react @emotion/react @emotion/styled framer-motion

Setup with Next.js

# Create a new Next.js app
npx create-next-app my-chakra-next-app
cd my-chakra-next-app

# Install Chakra UI and its peer dependencies
npm i @chakra-ui/react @emotion/react @emotion/styled framer-motion

Provider Setup

// App.js or _app.js (for Next.js)
import { ChakraProvider } from '@chakra-ui/react'

function MyApp({ Component, pageProps }) {
  return (
    <ChakraProvider>
      <Component {...pageProps} />
    </ChakraProvider>
  )
}

export default MyApp

Custom Theme Setup

// theme.js
import { extendTheme } from '@chakra-ui/react'

const theme = extendTheme({
  colors: {
    brand: {
      100: "#f7fafc",
      500: "#3182ce",
      900: "#1a365d",
    },
  },
  fonts: {
    heading: 'Montserrat, sans-serif',
    body: 'Inter, system-ui, sans-serif',
  },
  fontWeights: {
    normal: 400,
    medium: 500,
    bold: 700,
  },
  breakpoints: {
    sm: '480px',
    md: '768px',
    lg: '992px',
    xl: '1280px',
    '2xl': '1536px',
  },
  components: {
    Button: {
      // Custom variants
      variants: {
        solid: {
          bg: 'brand.500',
          color: 'white',
          _hover: {
            bg: 'brand.600',
          },
        },
      },
    },
  },
})

export default theme
// Import and use the theme
import theme from './theme'

function MyApp({ Component, pageProps }) {
  return (
    <ChakraProvider theme={theme}>
      <Component {...pageProps} />
    </ChakraProvider>
  )
}

Layout Components

Box

The fundamental building block:

<Box
  bg="gray.50"
  p={4}
  color="gray.700"
  borderRadius="md"
  boxShadow="md"
>
  This is a Box
</Box>

Flex

Flex container with built-in flexbox properties:

<Flex
  direction={{ base: "column", md: "row" }}
  align="center"
  justify="space-between"
  wrap="wrap"
  p={4}
  bg="gray.100"
>
  <Box p={2}>Item 1</Box>
  <Box p={2}>Item 2</Box>
  <Box p={2}>Item 3</Box>
</Flex>

Grid

CSS Grid container:

<Grid
  templateColumns={{ 
    base: "repeat(1, 1fr)",
    md: "repeat(2, 1fr)",
    lg: "repeat(3, 1fr)" 
  }}
  gap={6}
  p={4}
>
  <Box bg="tomato" p={4}>Item 1</Box>
  <Box bg="blue.300" p={4}>Item 2</Box>
  <Box bg="green.300" p={4}>Item 3</Box>
  <Box bg="yellow.300" p={4}>Item 4</Box>
</Grid>

SimpleGrid

Simplified responsive grid system:

<SimpleGrid
  columns={{ base: 1, md: 2, lg: 3 }}
  spacing={10}
>
  <Box bg="tomato" p={4}>Item 1</Box>
  <Box bg="blue.300" p={4}>Item 2</Box>
  <Box bg="green.300" p={4}>Item 3</Box>
</SimpleGrid>

Container

Centers content with a max-width:

<Container maxW="container.md" p={4}>
  Centered content with a max-width
</Container>

Stack

Stack children in horizontal or vertical direction:

// Vertical stack
<VStack
  spacing={4}
  align="stretch"
>
  <Box bg="red.200" p={4}>Item 1</Box>
  <Box bg="green.200" p={4}>Item 2</Box>
  <Box bg="blue.200" p={4}>Item 3</Box>
</VStack>

// Horizontal stack
<HStack spacing={4}>
  <Box bg="red.200" p={4}>Item 1</Box>
  <Box bg="green.200" p={4}>Item 2</Box>
  <Box bg="blue.200" p={4}>Item 3</Box>
</HStack>

Center

Center child elements:

<Center h="200px" color="white" bg="blue.500">
  This is centered
</Center>

Typography Components

Text

For paragraphs and spans:

<Text 
  fontSize={{ base: "md", md: "lg" }}
  fontWeight="medium"
  color="gray.700"
  lineHeight="tall"
>
  This is a text component
</Text>

Heading

For headings:

<Heading
  as="h1"
  size="xl"
  color="blue.500"
  textAlign="center"
  mb={4}
>
  Main Heading
</Heading>

<Heading as="h2" size="lg" mb={2}>Subheading</Heading>
<Heading as="h3" size="md" mb={2}>Section Heading</Heading>

LinkText

For hyperlinks:

<Link
  color="teal.500"
  href="https://chakra-ui.com"
  isExternal
  _hover={{ textDecoration: "none", color: "teal.700" }}
>
  Chakra UI Website
</Link>

Form Components

Button

Basic button component:

<Button
  colorScheme="blue"
  size="md"
  variant="solid"
  leftIcon={<EmailIcon />}
  isLoading={false}
  loadingText="Submitting"
  onClick={() => console.log('Button clicked')}
  _hover={{ bg: "blue.600" }}
>
  Submit
</Button>

Button variants and sizes:

// Variants
<Button variant="solid">Solid</Button>
<Button variant="outline">Outline</Button>
<Button variant="ghost">Ghost</Button>
<Button variant="link">Link</Button>

// Sizes
<Button size="xs">XS</Button>
<Button size="sm">SM</Button>
<Button size="md">MD</Button>
<Button size="lg">LG</Button>

Input

Text input field:

<Input
  placeholder="Enter email"
  type="email"
  size="md"
  variant="outline"
  focusBorderColor="blue.500"
  errorBorderColor="red.500"
  isRequired
  isInvalid={errors.email}
/>

With form control and label:

<FormControl isRequired isInvalid={errors.email}>
  <FormLabel htmlFor="email">Email</FormLabel>
  <Input
    id="email"
    type="email"
    value={email}
    onChange={(e) => setEmail(e.target.value)}
  />
  <FormHelperText>
    We'll never share your email.
  </FormHelperText>
  <FormErrorMessage>
    {errors.email}
  </FormErrorMessage>
</FormControl>

Select

Dropdown selection:

<Select
  placeholder="Select option"
  variant="filled"
  onChange={(e) => setValue(e.target.value)}
>
  <option value="option1">Option 1</option>
  <option value="option2">Option 2</option>
  <option value="option3">Option 3</option>
</Select>

Checkbox

Checkbox component:

<Checkbox
  isChecked={checked}
  onChange={(e) => setChecked(e.target.checked)}
  colorScheme="green"
  size="lg"
>
  I agree to terms
</Checkbox>

// Checkbox group
<CheckboxGroup 
  colorScheme="blue" 
  defaultValue={["one", "three"]}
  onChange={setCheckedItems}
>
  <Stack spacing={2} direction="column">
    <Checkbox value="one">One</Checkbox>
    <Checkbox value="two">Two</Checkbox>
    <Checkbox value="three">Three</Checkbox>
  </Stack>
</CheckboxGroup>

Radio

Radio buttons:

<RadioGroup onChange={setValue} value={value} defaultValue="1">
  <Stack direction="column">
    <Radio value="1" colorScheme="red">Option 1</Radio>
    <Radio value="2" colorScheme="green">Option 2</Radio>
    <Radio value="3" colorScheme="blue">Option 3</Radio>
  </Stack>
</RadioGroup>

Switch

Toggle switch:

<Switch
  isChecked={isChecked}
  onChange={(e) => setIsChecked(e.target.checked)}
  colorScheme="teal"
  size="lg"
/>

<FormControl display="flex" alignItems="center">
  <FormLabel htmlFor="dark-mode" mb="0">
    Enable Dark Mode
  </FormLabel>
  <Switch id="dark-mode" colorScheme="purple" />
</FormControl>

Textarea

Multiline text input:

<Textarea
  placeholder="Enter your message"
  value={message}
  onChange={(e) => setMessage(e.target.value)}
  size="md"
  resize="vertical"
  rows={4}
/>

NumberInput

For numeric input:

<NumberInput
  defaultValue={15}
  min={10}
  max={30}
  step={1}
  precision={0}
  onChange={(valueString) => setValue(parseInt(valueString))}
>
  <NumberInputField />
  <NumberInputStepper>
    <NumberIncrementStepper />
    <NumberDecrementStepper />
  </NumberInputStepper>
</NumberInput>

Slider

Range slider:

<Slider
  defaultValue={60}
  min={0}
  max={100}
  step={1}
  onChange={(v) => setValue(v)}
  colorScheme="teal"
>
  <SliderTrack>
    <SliderFilledTrack />
  </SliderTrack>
  <SliderThumb />
</Slider>

PinInput

For verification codes:

<PinInput otp size="lg" onChange={(value) => setPinValue(value)}>
  <PinInputField />
  <PinInputField />
  <PinInputField />
  <PinInputField />
</PinInput>

Feedback Components

Alert

For important messages:

<Alert
  status="success"
  variant="subtle"
  flexDirection="row"
  alignItems="center"
  justifyContent="center"
  textAlign="center"
  height="200px"
>
  <AlertIcon boxSize="40px" mr={0} />
  <AlertTitle mt={4} mb={1} fontSize="lg">
    Application submitted!
  </AlertTitle>
  <AlertDescription maxWidth="sm">
    Thanks for submitting your application. Our team will get back to you soon.
  </AlertDescription>
</Alert>

// Status variants: "info", "warning", "success", "error", "loading"

Toast

Temporary notification:

function ToastExample() {
  const toast = useToast()
  return (
    <Button
      onClick={() =>
        toast({
          title: "Account created.",
          description: "We've created your account for you.",
          status: "success",
          duration: 9000,
          isClosable: true,
          position: "top-right",
        })
      }
    >
      Show Toast
    </Button>
  )
}

Progress

Progress indicators:

// Linear progress
<Progress value={80} colorScheme="green" size="lg" />

// Circular progress
<CircularProgress value={40} color="green.400" thickness="4px">
  <CircularProgressLabel>40%</CircularProgressLabel>
</CircularProgress>

// Indeterminate progress
<Progress size="xs" isIndeterminate />

Skeleton

Loading placeholder:

<Skeleton height="20px" />
<Skeleton height="40px" mt={2} />
<Skeleton height="60px" mt={2} />

// With isLoaded prop
<Skeleton isLoaded={isLoaded}>
  <Text>This content will appear when loaded</Text>
</Skeleton>

// With fadeDuration
<SkeletonText mt="4" noOfLines={4} spacing="4" skeletonHeight="2" fadeDuration={1} />

Spinner

Loading spinner:

<Spinner
  thickness="4px"
  speed="0.65s"
  emptyColor="gray.200"
  color="blue.500"
  size="xl"
/>

Data Display Components

Badge

For status indicators or counts:

<Badge colorScheme="green">Success</Badge>
<Badge colorScheme="red">Error</Badge>
<Badge colorScheme="purple" variant="outline">Outline</Badge>
<Badge colorScheme="teal" variant="solid">Solid</Badge>

// With an icon
<Badge colorScheme="green">
  <Icon as={CheckIcon} mr={1} />
  Verified
</Badge>

Tag

Similar to badges but for filtering:

<Tag size="lg" colorScheme="red" borderRadius="full">
  <TagLabel>Sample Tag</TagLabel>
  <TagCloseButton onClick={() => console.log('Tag removed')} />
</Tag>

List

List component with various styles:

<List spacing={3}>
  <ListItem>
    <ListIcon as={CheckCircleIcon} color="green.500" />
    Item 1
  </ListItem>
  <ListItem>
    <ListIcon as={CheckCircleIcon} color="green.500" />
    Item 2
  </ListItem>
  <ListItem>
    <ListIcon as={WarningIcon} color="red.500" />
    Item 3
  </ListItem>
</List>

Table

Data tables:

<TableContainer>
  <Table variant="simple" colorScheme="teal">
    <TableCaption>Imperial to metric conversion factors</TableCaption>
    <Thead>
      <Tr>
        <Th>Item</Th>
        <Th isNumeric>Multiply by</Th>
        <Th>To convert</Th>
      </Tr>
    </Thead>
    <Tbody>
      <Tr>
        <Td>inches</Td>
        <Td isNumeric>25.4</Td>
        <Td>millimeters</Td>
      </Tr>
      <Tr>
        <Td>feet</Td>
        <Td isNumeric>30.48</Td>
        <Td>centimeters</Td>
      </Tr>
    </Tbody>
    <Tfoot>
      <Tr>
        <Th>Item</Th>
        <Th isNumeric>Multiply by</Th>
        <Th>To convert</Th>
      </Tr>
    </Tfoot>
  </Table>
</TableContainer>

Stat

For displaying statistics:

<Stat>
  <StatLabel>Collected Fees</StatLabel>
  <StatNumber>£0.00</StatNumber>
  <StatHelpText>Feb 12 - Feb 28</StatHelpText>
</Stat>

// With indicators
<StatGroup>
  <Stat>
    <StatLabel>Sent</StatLabel>
    <StatNumber>345,670</StatNumber>
    <StatHelpText>
      <StatArrow type="increase" />
      23.36%
    </StatHelpText>
  </Stat>

  <Stat>
    <StatLabel>Clicked</StatLabel>
    <StatNumber>45</StatNumber>
    <StatHelpText>
      <StatArrow type="decrease" />
      9.05%
    </StatHelpText>
  </Stat>
</StatGroup>

Code

For displaying code:

<Code>console.log("Hello, world!");</Code>

// With color schemes
<Code colorScheme="red">Error code: 404</Code>
<Code colorScheme="green">Success code: 200</Code>

Kbd

For keyboard shortcuts:

<span>
  <Kbd>shift</Kbd> + <Kbd>H</Kbd>
</span>

Disclosure Components

Accordion

Collapsible panels:

<Accordion allowMultiple>
  <AccordionItem>
    <h2>
      <AccordionButton>
        <Box flex="1" textAlign="left">
          Section 1 title
        </Box>
        <AccordionIcon />
      </AccordionButton>
    </h2>
    <AccordionPanel pb={4}>
      Section 1 content
    </AccordionPanel>
  </AccordionItem>

  <AccordionItem>
    <h2>
      <AccordionButton>
        <Box flex="1" textAlign="left">
          Section 2 title
        </Box>
        <AccordionIcon />
      </AccordionButton>
    </h2>
    <AccordionPanel pb={4}>
      Section 2 content
    </AccordionPanel>
  </AccordionItem>
</Accordion>

Tabs

Tabbed interface:

<Tabs variant="enclosed" colorScheme="teal">
  <TabList>
    <Tab>Profile</Tab>
    <Tab>Settings</Tab>
    <Tab>Messages</Tab>
  </TabList>
  <TabPanels>
    <TabPanel>
      <p>Profile content!</p>
    </TabPanel>
    <TabPanel>
      <p>Settings content!</p>
    </TabPanel>
    <TabPanel>
      <p>Messages content!</p>
    </TabPanel>
  </TabPanels>
</Tabs>

// Variants: "line", "enclosed", "enclosed-colored", "soft-rounded", "solid-rounded", "unstyled"

Modal

Dialogs and modals:

function BasicModal() {
  const { isOpen, onOpen, onClose } = useDisclosure()
  return (
    <>
      <Button onClick={onOpen}>Open Modal</Button>

      <Modal isOpen={isOpen} onClose={onClose}>
        <ModalOverlay />
        <ModalContent>
          <ModalHeader>Modal Title</ModalHeader>
          <ModalCloseButton />
          <ModalBody>
            Content of the modal goes here.
          </ModalBody>
          <ModalFooter>
            <Button colorScheme="blue" mr={3} onClick={onClose}>
              Close
            </Button>
            <Button variant="ghost">Secondary Action</Button>
          </ModalFooter>
        </ModalContent>
      </Modal>
    </>
  )
}

Drawer

Sliding panels:

function DrawerExample() {
  const { isOpen, onOpen, onClose } = useDisclosure()
  const [placement, setPlacement] = React.useState("right")

  return (
    <>
      <Button colorScheme="blue" onClick={onOpen}>
        Open Drawer
      </Button>
      <Drawer placement={placement} onClose={onClose} isOpen={isOpen}>
        <DrawerOverlay />
        <DrawerContent>
          <DrawerHeader borderBottomWidth="1px">Basic Drawer</DrawerHeader>
          <DrawerBody>
            <p>Some contents...</p>
          </DrawerBody>
          <DrawerFooter>
            <Button variant="outline" mr={3} onClick={onClose}>
              Cancel
            </Button>
            <Button colorScheme="blue">Save</Button>
          </DrawerFooter>
        </DrawerContent>
      </Drawer>
    </>
  )
}

Popover

Small floating content panels:

<Popover>
  <PopoverTrigger>
    <Button>Trigger</Button>
  </PopoverTrigger>
  <PopoverContent>
    <PopoverArrow />
    <PopoverCloseButton />
    <PopoverHeader>Confirmation!</PopoverHeader>
    <PopoverBody>Are you sure you want to continue?</PopoverBody>
    <PopoverFooter d="flex" justifyContent="flex-end">
      <ButtonGroup size="sm">
        <Button variant="outline">Cancel</Button>
        <Button colorScheme="red">Apply</Button>
      </ButtonGroup>
    </PopoverFooter>
  </PopoverContent>
</Popover>

Tooltip

Information on hover:

<Tooltip label="Hey, I'm here!" aria-label="A tooltip">
  Hover me
</Tooltip>

// With placement
<Tooltip hasArrow label="Search places" placement="top">
  <IconButton
    aria-label="Search database"
    icon={<SearchIcon />}
  />
</Tooltip>

Navigation Components

Menu

Dropdown menus:

<Menu>
  <MenuButton as={Button} rightIcon={<ChevronDownIcon />}>
    Actions
  </MenuButton>
  <MenuList>
    <MenuItem>Download</MenuItem>
    <MenuItem>Create a Copy</MenuItem>
    <MenuItem>Mark as Draft</MenuItem>
    <MenuDivider />
    <MenuItem color="red.400">Delete</MenuItem>
  </MenuList>
</Menu>

// With icons
<Menu>
  <MenuButton as={Button}>
    Menu with icons
  </MenuButton>
  <MenuList>
    <MenuItem icon={<AddIcon />}>New File</MenuItem>
    <MenuItem icon={<ExternalLinkIcon />}>Open</MenuItem>
    <MenuItem icon={<RepeatIcon />}>Save</MenuItem>
    <MenuItem icon={<EditIcon />}>Edit</MenuItem>
  </MenuList>
</Menu>

Breadcrumb

Navigation breadcrumbs:

<Breadcrumb separator="/">
  <BreadcrumbItem>
    <BreadcrumbLink href="#">Home</BreadcrumbLink>
  </BreadcrumbItem>

  <BreadcrumbItem>
    <BreadcrumbLink href="#">Docs</BreadcrumbLink>
  </BreadcrumbItem>

  <BreadcrumbItem isCurrentPage>
    <BreadcrumbLink href="#">Components</BreadcrumbLink>
  </BreadcrumbItem>
</Breadcrumb>

// With custom separator
<Breadcrumb separator=">">
  <BreadcrumbItem>
    <BreadcrumbLink href="#">Home</BreadcrumbLink>
  </BreadcrumbItem>
  <BreadcrumbItem isCurrentPage>
    <BreadcrumbLink href="#">About</BreadcrumbLink>
  </BreadcrumbItem>
</Breadcrumb>

Link

For navigation links:

<Link href="https://chakra-ui.com" isExternal>
  Chakra UI <ExternalLinkIcon mx="2px" />
</Link>

Media Components

Image

Display images:

<Image
  src="https://bit.ly/dan-abramov"
  alt="Dan Abramov"
  width="200px"
  height="200px"
  borderRadius="full"
  objectFit="cover"
  fallback={<Spinner />}
/>

Avatar

User avatars:

<Avatar name="Dan Abrahmov" src="https://bit.ly/dan-abramov" />

// Avatar with badge
<AvatarGroup>
  <Avatar name="Ryan Florence" src="https://bit.ly/ryan-florence" />
  <Avatar name="Segun Adebayo" src="https://bit.ly/sage-adebayo" />
  <Avatar name="Kent Dodds" src="https://bit.ly/kent-c-dodds" />
  <Avatar name="Prosper Otemuyiwa" src="https://bit.ly/prosper-baba" />
  <Avatar name="Christian Nwamba" src="https://bit.ly/code-beast" />
</AvatarGroup>

Icon

SVG icons:

// Using built-in icons
<Icon as={FaUser} boxSize={6} color="red.500" />

// Custom icon
<Icon
  width="24px"
  height="24px"
  viewBox="0 0 24 24"
  color="blue.500"
>
  <path
    fill="currentColor"
    d="M12 2C6.48 2 2 6.48 2 12s4.48 10 10 10 10-4.48 10-10S17.52 2 12 2zm0 18c-4.41 0-8-3.59-8-8s3.59-8 8-8 8 3.59 8 8-3.59 8-8 8z"
  />
</Icon>

Overlay Components

AlertDialog

Confirmation dialogs:

function AlertDialogExample() {
  const [isOpen, setIsOpen] = React.useState(false)
  const onClose = () => setIsOpen(false)
  const cancelRef = React.useRef()
  
  return (
    <>
      <Button colorScheme="red" onClick={() => setIsOpen(true)}>
        Delete Customer
      </Button>

      <AlertDialog
        isOpen={isOpen}
        leastDestructiveRef={cancelRef}
        onClose={onClose}
      >
        <AlertDialogOverlay>
          <AlertDialogContent>
            <AlertDialogHeader fontSize="lg" fontWeight="bold">
              Delete Customer
            </AlertDialogHeader>

            <AlertDialogBody>
              Are you sure? You can't undo this action afterwards.
            </AlertDialogBody>

            <AlertDialogFooter>
              <Button ref={cancelRef} onClick={onClose}>
                Cancel
              </Button>
              <Button colorScheme="red" onClick={onClose} ml={3}>
                Delete
              </Button>
            </AlertDialogFooter>
          </AlertDialogContent>
        </AlertDialogOverlay>
      </AlertDialog>
    </>
  )
}

Common Hooks

useDisclosure

Manage disclosure state (open/close):

function Component() {
  const { isOpen, onOpen, onClose, onToggle } = useDisclosure()

  return (
    <>
      <Button onClick={onOpen}>Open Drawer</Button>
      <Drawer isOpen={isOpen} onClose={onClose}>
        <DrawerOverlay />
        <DrawerContent>
          <DrawerHeader>Drawer Example</DrawerHeader>
          <DrawerBody>Some content</DrawerBody>
        </DrawerContent>
      </Drawer>
    </>
  )
}

useColorMode

Toggle between light and dark modes:

function ColorModeToggle() {
  const { colorMode, toggleColorMode } = useColorMode()
  
  return (
    <Button onClick={toggleColorMode}>
      Toggle {colorMode === "light" ? "Dark" : "Light"} Mode
    </Button>
  )
}

useBreakpointValue

Responsive value based on breakpoint:

function ResponsiveComponent() {
  const variant = useBreakpointValue({ 
    base: "solid", 
    md: "outline",
    lg: "ghost" 
  })
  
  return <Button variant={variant}>Click me</Button>
}

useToast

Create toast notifications:

function ToastExample() {
  const toast = useToast()
  
  return (
    <Button
      onClick={() =>
        toast({
          title: "Account created.",
          description: "We've created your account for you.",
          status: "success",
          duration: 5000,
          isClosable: true,
          position: "top-right"
        })
      }
    >
      Show Toast
    </Button>
  )
}

Best Practices

Performance Optimization

  • Use shouldWrapChildren prop to avoid unnecessary DOM nesting
  • Memoize components with React.memo when appropriate
  • Use isLazy prop on complex components like Modal and Drawer when they’re conditionally rendered

Accessibility Best Practices

  • Always provide aria-label for IconButton components
  • Use semantic HTML elements (Heading, Button, etc.)
  • Keep correct heading hierarchy (h1, h2, h3)
  • Ensure sufficient color contrast
  • Provide text alternatives for non-text content
  • Make keyboard navigation smooth

Dark Mode Support

// In your theme.js
const theme = extendTheme({
  config: {
    initialColorMode: "light",
    useSystemColorMode: true,
  },
  styles: {
    global: (props) => ({
      body: {
        bg: props.colorMode === "dark" ? "gray.800" : "white",
        color: props.colorMode === "dark" ? "white" : "gray.800",
      },
    }),
  },
})

// Component with conditional styling
function ConditionalComponent() {
  const { colorMode } = useColorMode()
  
  return (
    <Box bg={colorMode === "dark" ? "gray.700" : "gray.100"} p={4}>
      This box changes with color mode
    </Box>
  )
}

Resources for Further Learning

Official Documentation

Community Resources

Learning Paths

  1. Beginner: Start with layout components (Box, Flex, Grid)
  2. Intermediate: Build forms and complex layouts
  3. Advanced: Create custom components and themes

This comprehensive cheat sheet covers the essential components, hooks, and patterns for building applications with Chakra UI. Whether you’re just starting or looking to optimize your workflow, these examples will help you build accessible, responsive interfaces with speed and consistency.

Scroll to Top