Chakra
Last modified on Tue 23 Feb 2021

Chakra UI is a simple, modular and accessible component library that gives you the building blocks you need to build your React applications.

Getting started

Installation:

npm i @chakra-ui/react @emotion/react @emotion/styled framer-motion

For more about setup read docs

Setup provider:

For Chakra UI to work correctly, you need to set up the ChakraProvider at the root of your application. Under the hood Chakra UI is using emotion ThemeProvider

Example:

import { ChakraProvider } from "@chakra-ui/react";

function App({ Component, pageProps }: AppProps): ReactElement {
  return (
    <ChakraProvider theme={theme}>
      <Component {...pageProps} />
    </ChakraProvider>
  );
}

export default App;

Note:

For including <CSSReset /> just add resetCSS prop to <ChakraProvider>

All provider props

Style props

Style props are a way to alter the style of a component by simply passing props to it. It helps to save time by providing helpful shorthand ways to style components. Alternative to that is using chakra factory.

Style props should be used for one-off styles (up to max 3 props):

<Button display="block" mt="md">
  Click me!
</Button>

Components that have more than 3 styles should be moved to separate component. Every Box or Flex components should be moved to separate component, regarding of number of styles, with a descriptive name.

const ListWrapper = chakra(Box, {
  baseStyle: {
    shadow: "lg",
    rounded: "lg",
    bg: "white",
  },
});

For more about style props read docs

sx prop works similar to style prop. It takes an object with styles.

Example:

<Button
  sx={{
    display: "block",
    mt: "md",
    color: "primary.100",
    mx: 12,
  }}
>
  Click me!
</Button>

There is also __css prop that is similar to sx. The only difference is that __css prop will be merged before sx prop (github).

Chakra Factory

Chakra factory serves as an object of chakra JSX elements, and also a function that can be used to enable custom component receive chakra's style props.

import { chakra } from "@chakra-ui/react";

// preferred way!
chakra("button", {
  baseStyle: {
    shadow: "lg",
    rounded: "lg",
    bg: "white",
  },
});

// using sx prop
<chakra.button
  sx={{
    shadow: "lg",
    rounded: "lg",
    bg: "white",
  }}
>
  Click me
</chakra.button>;

This reduces the need to create custom component wrappers and name them. Syntax is available for common html elements. See the reference for the full list of elements supported. Beside list of elements, we can pass a function as see custom components

Chakra factory will be defined with base style and can be overridden by sx prop because baseStyle is merged before sx. Components created using chakra factory can be overridden by also using chakra factory (merge order)

Example:

const Button = chakra("button", {
  baseStyle: {
    bg: "white",
  },
});
const FbButton = chakra(Button, {
  baseStyle: {
    bg: "primary.500",
  },
});

Custom component example

For example react-datepicker can be wrapped in chakra factory function so we can pass sx or style props to <DatePicker />

Example:

import DatePicker from "react-datepicker";
import { chakra } from "@chakra-ui/react";

const StyledaDatepicker = chakra(DatePicker);

export const Datepicker = (props) => (
  <StyledaDatepicker w="100%" bg="blue.100" {...props} />
);

Chakra factory function will pass className to DatePicker input component with all styles. In this case input will be rendered with custom bg and width styles.

For more about chakra factory read docs

The as polymorphic prop

The as prop is a feature that all Chakra UI components have and it allows you to pass an HTML tag or component to be rendered.

as prop (polymorphic prop) is a feature of emotion borrowed from styled-components

It allows us to use all of the Button props and all of the a props without having to wrap the Button in an a component.

Example:

<Button as="a" href="https://chakra-ui.com/docs/getting-started">
  Chakra UI docs
</Button>

In example above a element will be rendered with styled of Button component. Except HTML elements as prop can be another React component:

<Button as={Link} someLinkProp={value}>
  Chakra UI docs
</Button>

For more info about as prop read docs

Setup custom theme

If you need to customize the default theme to match your design requirements, you can use extendTheme from @chakra-ui/react.

Example:

import { extendTheme } from "@chakra-ui/react";

const overrides = {
  colors: {
    primary: {
      100: "#ff0000",
      80: "#ff1a1a",
    },
  },
};

const theme = extendTheme(overrides);

export default theme;

For more info about setup read docs

Theming rules

The theme object is where you define your application's color palette, type scale, font stacks, breakpoints, border radius values, and more. Theme overrides are placed in src/styles/themes folder.

Theming with Chakra UI is based on the Styled System Theme Specification

Example:

const overrides = {
  colors: {
    primary: {
      100: "#ff0000",
      80: "#ff1a1a",
    },
  },
};

Except objects, theme override can take a function:

const overrides = {
  colors: (props) => {
    const { colorMode } = props;

    return {
      primary: {
        100: colorMode === "dark" ? "#ff0000" : "#ffffff",
        80: "#ff1a1a",
      },
    };
  },
};

Then in props we have access button props, theme object and colorMode.

chakra-ui/theme-tools

Chakra has a whole pallet of useful helpers:

For more about theme-tools check out github

Theme folder structure:

src
└── styles
    └── theme
        ├── index.ts # main theme endpoint
        ├── styles.ts # global styles
        ├── foundations # colors, typography, sizes...
        │   ├── fontSizes.ts
        │   └── colors.ts
        └── components # components styles
            └── button.ts

Colors

Color naming should a single value or an object with keys in range from 50 to 900.

Example:

export const colors = {
  white: "#ffffff",
  primary: {
    50: "#f6faff",
    100: "#d7e9fd",
    200: "#c0dcfc",
    300: "#a7cefb",
    400: "#8abdfa",
    500: "#68aaf8",
    600: "#3d92f6",
    700: "#0070f3",
    800: "#0064d8",
    900: "#0055b9",
  },
};

Pseudo props

Pseudo props in ChakraUI can be passed as props to component. Full list of props can be found in docs

Example:

<Button
  bg="blue.100"
  _hover={{
    background: "white",
  }}
>
  Submit
</Button>

Also pseudo elements can be used in theme or in chakra factory:

const Card = chakra("div", {
  baseStyle: {
    bg: "blue.100",
    _hover: {
      bg: "white",
    },
  },
});

// or
const Card = chakra("div", {
  baseStyle: {
    bg: "blue.100",
    ":hover": {
      bg: "white",
    },
  },
});

Global styles

Global styles are theme-aware styles you can apply to any html element globally.

They are defined in src/styles/theme/styles.ts file.

Example:

const overrides = {
  styles: {
    global: {
      body: {
        fontFamily: "body",
        bg: "white",
        color: "primary.200",
      },
      "*": {
        boxSizing: "border-box",
      },
    },
  },
};

Responsive

Chakra UI supports responsive styles out of the box. Instead of manually adding @media queries and adding nested styles throughout your code, Chakra UI allows you to provide object and array values to add mobile-first responsive styles.

Under the hood @media(min-width) media query is used to ensure mobile-first

Chakra UI default breakpoints:

export const breakpoints = {
  sm: "30em",
  md: "48em",
  lg: "62em",
  xl: "80em",
};

Here's how to interpret this syntax:

For responsive styles, array or object syntax can be used.

// array syntax
<Text fontSize={["24px", "40px", "56px"]}>
  Lorem Ipsum is simply dummy text
</Text>
// object syntax
<Text fontSize={{ base: "24px", md: "40px", lg: "56px" }}>
  Lorem Ipsum is simply dummy text
</Text>

In case we need to skip a certain breakpoint, null is passed at that position in the array to avoid generating unnecessary CSS.

Example:

<Text fontSize={["24px", null, "56px"]}>Lorem Ipsum is simply dummy text</Text>

Array and Object syntax work for every style prop in the theme specification, which means you can change most properties at a given breakpoint. Preferred way is to use array.

To create custom breakpoints read docs.

NOTE: there is an issue with having strict: false in tsconfig when using createBreakpoints. Error that breaks the build: Type '(() => string) & (() => string)' is not assignable to type 'string'. Current workaround is to add strictNullChecks: true to tsconfig. (github issue)

For more about responsive styles read styled-system responsive styles docs

Custom components style

Chakra UI has a specific API for styling components. Most components have default or base styles baseStyle, styles for different sizes sizes, and styles for different visual variants variants.

Components styles are defined in theme/components/<component-name>.ts Each component style will export these objects:

baseStyle are styles that all button types share.

const baseStyle: StyleObjectOrFn = {
  lineHeight: "1.2",
  borderRadius: "md",
  _focus: {
    boxShadow: "outline",
  },
  _disabled: {
    opacity: 0.4,
    cursor: "not-allowed",
    boxShadow: "none",
  },
  _hover: {
    cursor: "pointer",
  },
};

variants represents visual style.

const variants: { [variant: string]: StyleObjectOrFn } = {
  solid: {
    bg: 'primary.100',,
    color: 'white',
    _hover: {
      bg: 'primary.400',
    },
    _disabled: {
      bg: 'neutral.200',
    }
  },
  outline: (props: Dict): SystemStyleObject => ({
    bg: 'transparent',,
    border: '1px solid',
    borderColor: 'primary.100',
    _hover: {
      bg: 'primary.100',
    }
  }),
};

sizes determine all the component sizes like width, height, font-size etc

const sizes: { [size: string]: StyleObjectOrFn } = {
  sm: {
    h: 8,
    minW: 8,
    fontSize: "sm",
    px: 3,
  },
  xs: (props: Dict): SystemStyleObject => ({
    h: 6,
    minW: 6,
    fontSize: "xs",
    px: 2,
  }),
};

Naming used for sizes:

defaultProps are default values for size and variant

const defaultProps = {
  variant: "solid",
  size: "md",
};

For more info about custom component styles read docs

Color mode

When you use the ChakraProvider at the root of your app, you can automatically use color mode in your apps. By default, most of Chakra UI component are dark mode compatible. To handle color mode manually in your application, use the useColorMode or useColorModeValue hooks.

Tip: Chakra stores the color mode in localStorage and uses CSS variables to ensure the color mode is persistent.

useColorMode

useColorMode is a React hook that gives you access to the current color mode, and a function to toggle the color mode.

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

useColorModeValue

useColorModeValue is React hook that takes 2 arguments, first is value for light mode and second is value for dark mode, and returnees the the value based on the active color mode

const value = useColorModeValue(lightModeValue, darkModeValue);

Style 3rd party components

In this example we will style react-select with Chakra UI

First we need to create custom style object in theme

// style/theme/components/reactSelect.ts
const ReactSelect = {
  baseStyle: () => ({
    container: {
      bg: "black",
      p: 8,
    },
    menu: {
      color: "blue.100",
      bg: "blue.500",
      padding: 8,
    },
  }),
};

Keys in baseStyle can be one of:

Reade more about react-select style objects in docs.

After we have ReactSelect theme object, we need to add that to theme.components

// style/theme/index.ts
const overrides = {
  colors,
  // ...
  components: {
    Button,
    ReactSelect,
    // ...
  },
};

Now we can create Select component in components folder:

const selectStyle = {
  container: (base, { theme }) => {
    return {
      ...base,
      ...theme.container,
    };
  },
  menu: (base, { theme }) => ({
    ...base,
    ...theme.menu,
  }),
};

const Select = (props) => {
  const styles = useStyleConfig("ReactSelect", props);

  return (
    <ReactSelect
      theme={css(styles)(useTheme())}
      styles={selectStyle}
      {...props}
    />
  );
};

Each key added to the theme needs to be added to selectStyle.

Additionally, custom components can be added to react-select like SelectContainer

Example:

const SelectContainer: FC<ContainerProps<BoxProps>> = ({
  children,
  ...rest
}) => {
  return (
    <components.SelectContainer {...rest}>
      <chakra.div sx={rest.selectProps.sx}>{children}</chakra.div>
    </components.SelectContainer>
  );
};

This will allow us to use sx prop on select component.

<Select sx={{ mt: 12 }} options={[]} />

React hook form example

This example shows how to build a simple form with Chakra UI form components and the React Hook Form form library.