Theme
Used to force a part of the tree to light or dark mode, and to override appearance tokens like radius and scale.
import { Button, Stack } from '@chakra-ui/react'
import { Theme } from '#components/ui/theme'
export const ThemeBasic = () => {
return (
<Stack align="flex-start">
<Button variant="surface" colorPalette="teal">
Auto Button
</Button>
<Theme p="4" appearance="dark" colorPalette="teal">
<Button variant="surface">Dark Button</Button>
</Theme>
<Theme p="4" appearance="light" colorPalette="teal">
<Button variant="surface">Light Button</Button>
</Theme>
</Stack>
)
}
Anatomy
import { Theme } from '#components/ui/theme'<Theme appearance="dark">
<div />
</Theme>Usage
Theme renders a div that scopes appearance to its subtree. It sets the
chakra-theme class together with the appearance class, and applies the native
color-scheme style so browser UI (scrollbars, form controls) follows along.
The key things to note:
appearanceforceslightordarkfor everything inside. Leave it off to inherit the current color mode.hasBackground(defaulttrue) paints thebgandfgtokens. Set it tofalsewhen the theme wraps an element that already has a background, like a popover or dialog.colorPalettesets the default palette for all components in the subtree.- The radius and scale props write CSS variables that the Saas UI semantic tokens read, so they cascade to every component below.
Examples
Nested
Themes can be nested to apply different appearances to different parts of the tree. This is useful for applying a global appearance and then overriding some parts of it.
Good to know: this uses native CSS selectors, so there is no extra React context involved.
import { Box, Button } from '@chakra-ui/react'
import { Theme } from '#components/ui/theme'
export const ThemeNested = () => {
return (
<Box p="8" borderWidth="1px">
Hello Normal <Button>Click me</Button>
<Theme appearance="dark" colorPalette="red">
<Box p="8" borderWidth="1px">
Hello Dark <Button>Click me</Button>
<Theme appearance="light" colorPalette="pink">
<Box p="8" borderWidth="1px">
Hello Light <Button>Click me</Button>
</Box>
</Theme>
</Box>
</Theme>
</Box>
)
}
Portalled
Portalled content, such as a popover or dialog, is rendered outside the tree and
therefore does not inherit a parent Theme. Wrap the portalled content itself
and set hasBackground={false} so it keeps the panel styles.
Naruto is a Japanese manga series written and illustrated by Masashi Kishimoto.
import { Text, Button, Input } from '@chakra-ui/react'
import { Theme } from '#components/ui/theme'
import { Popover } from '#components/ui/popover'
export const ThemeWithPortalled = () => {
return (
<Popover.Root>
<Popover.Trigger asChild>
<Button size="sm" variant="outline">
Click me
</Button>
</Popover.Trigger>
<Popover.Content asChild>
<Theme hasBackground={false} appearance="dark" colorPalette="teal">
<Popover.Arrow />
<Popover.Body spaceY="4">
<Popover.Title fontWeight="medium">Naruto Form</Popover.Title>
<Text>
Naruto is a Japanese manga series written and illustrated by
Masashi Kishimoto.
</Text>
<Input placeholder="Search" />
<Button>Click me</Button>
</Popover.Body>
</Theme>
</Popover.Content>
</Popover.Root>
)
}
Radius
Use controlRadius, panelRadius and indicatorRadius to change the border
radius of controls, panels and indicators in a subtree. scaleFactor scales all
three at once.
controlRadius: 0
controlRadius: 2
import { Button, Input, Stack, Text } from '@chakra-ui/react'
import { Theme } from '#components/ui/theme'
export const ThemeWithRadius = () => {
return (
<Stack gap="6">
<Theme hasBackground={false} controlRadius={0}>
<Text textStyle="sm" color="fg.muted" mb="2">
controlRadius: 0
</Text>
<Stack direction="row" align="center">
<Input placeholder="Email" maxW="3xs" />
<Button>Subscribe</Button>
</Stack>
</Theme>
<Theme hasBackground={false} controlRadius={2}>
<Text textStyle="sm" color="fg.muted" mb="2">
controlRadius: 2
</Text>
<Stack direction="row" align="center">
<Input placeholder="Email" maxW="3xs" />
<Button>Subscribe</Button>
</Stack>
</Theme>
</Stack>
)
}
Page specific color mode
To lock an entire page to a specific color mode, wrap the page with Theme.
Combine it with ColorModeProvider when you also use the useColorMode hook.
import { ColorModeProvider } from '#components/setup/color-mode/color-mode'
import { Theme } from '#components/ui/theme'
export const ForcedColorMode = ({ children }) => {
return (
<ColorModeProvider forcedTheme="dark">
<Theme appearance="dark">{children}</Theme>
</ColorModeProvider>
)
}Props
| Prop | Default | Type |
|---|---|---|
hasBackground | true | booleanWhether to apply the theme background and foreground colors. Set to false when wrapping content that already has a background, such as portalled panels. |
scaleFactor | '1' | numberScale factor consumed by the Saas UI semantic radius tokens. Scales control, panel and indicator radii at once. |
controlRadius | '1' | numberRadius factor for controls such as Button, Input and Select. |
panelRadius | '1' | numberRadius factor for panels such as Dialog, Drawer and Popover. |
indicatorRadius | '1' | numberRadius factor for indicators such as Badge and Tag. |
overlayEffect | 'blur(10px)' | stringBackdrop effect consumed by the Saas UI overlay layer styles. |
appearance | 'light' | 'dark'The light or dark appearance applied to this subtree. Leave undefined to inherit the current color mode. | |
colorPalette | ColorPaletteThe default color palette for components in this subtree. |