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:
pnpm i -E @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 Next.js, you need to set this up in
pages/_app.tsx
- For Create React App, you need to set this up in
index.tsx
For including <CSSReset />
just add resetCSS
prop to <ChakraProvider>
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.
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. To further improve readability, it is advised to move every Box
or Flex
component to a separate component, with a descriptive name.
const ListWrapper = chakra(Box, {
baseStyle: {
shadow: "lg",
rounded: "lg",
bg: "white",
},
});
For more about style props read docs
sx
prop
The 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>
__css
prop
The __css
prop is similar to sx
but it is designed ONLY for internal use (hence the private prefix __
).
The main difference is that __css
prop will be merged before sx
prop (github).
We should ONLY use it for building primitive core
components.
import { chakra, HTMLChakraProps, ThemingProps, useStyleConfig } from '@chakra-ui/react';
import { __DEV__ } from "@chakra-ui/utils";
export interface CardOptions {};
export interface CardProps
extends HTMLChakraProps<"div">,
CardOptions,
ThemingProps<"Card"> {};
export const Card = forwardRef<CardProps, "div">(({ variant, ...rest }, ref) => {
const styles = useStyleConfig("Card", { variant });
return <chakra.div ref={ref} __css={styles} {...rest} />;
});
if (__DEV__) {
Card.displayName = "Card"
}
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",
},
});
Update (14.05.2021.)
Previously we had this example:
const FbButton = chakra(Button, {
baseStyle: {
bg: "primary.500",
},
});
We decided this is not the way to go and instead we should make special colorScheme
in the theme.
Theme:
// ./src/styles/theme/foundations/colors.ts
const colors = {
facebook: {
50: "#E8F4F9",
100: "#D9DEE9",
200: "#B7C2DA",
300: "#6482C0",
400: "#4267B2",
500: "#385898",
600: "#314E89",
700: "#29487D",
800: "#223B67",
900: "#1E355B",
},
}
// ./src/styles/theme/components/button.ts
function variantSolid(props: Dict) {
const { colorScheme } = props;
if (colorScheme === 'facebook') {
return {
bg: 'facebook.500',
}
}
return {
bg: `${colorScheme}.200`,
}
}
const variants = {
solid: variantSolid
};
export default {
variants,
};
Usage:
const ExampleForm = () => {
return (
<form>
// ...some inputs
<Button colorScheme="facebook" />
</form>
)
}
NOTE:
messenger
,telegram
color schemes OTB. You can find the example here
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
as
polymorphic prop
The 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 the example above the a
element will be rendered as a Button
component.
The as
prop can also be another React component:
<Button as={Link} someLinkProp={value}>
Chakra UI docs
</Button>
Button
will be rendered asLink
componentLink
props will become available onButton
Link
andButton
styles will be combined
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:
mode(lightMode, darkMode)(props)
function is the same ascolorMode === "dark" ? darkMode : lightMode
.orient
definevertical
andhorizontal
style for component:<Divider orientation="horizontal | vertical" />
transparentize
helper to make a color transparenttransparentize('blue.100', 0.3)
darken
darken a specified colordarken('blue.100', 0.5)
(there is alsolighten
,blacken
,whiten
)
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...
│ ├── font-sizes.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",
},
};
How to generate colors
We recommend adding a palette that ranges from 50
to 900
. Tools like Themera, Smart Swatch, Coolors or Palx are available to generate these palettes.
Sometimes you can get different or incomplete color palette from designer.
For example, designer provided us with only one primary
color value #68aaf8
.
In this case you can use this tool color-scheme-builder to generate the color palette while retaining the exact color value.
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:
base
: From0em
upwardsmd
: From48em
upwardslg
: From62em
upwardsxl
: From80em
upwards
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:
baseStyles
sizes
variants
defaultProps
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:
lg
md
sm
xs
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/react-select.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:
- clearIndicator
- container
- control
- dropdownIndicator
- group
- groupHeading
- indicatorsContainer
- indicatorSeparator
- input
- loadingIndicator
- loadingMessage
- menu
- menuList
- menuPortal
- multiValue
- multiValueLabel
- multiValueRemove
- noOptionsMessage
- option
- placeholder
- singleValue
- valueContainer
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.