To give components access to the theme object, you must add ThemeProvider
to the root of your application:
import {ThemeProvider} from '@primer/react'function App() {return (<ThemeProvider><div>...</div></ThemeProvider>)}
ThemeProvider
comes with a default theme object that includes colors, spacing, fonts, etc. for building applications at GitHub.
To customize the default theme, you can pass your custom theme to ThemeProvider
using the theme
prop:
import {ThemeProvider, theme} from '@primer/react'import deepmerge from 'deepmerge'const customTheme = deepmerge(theme, {fonts: {mono: 'MonoLisa, monospace'}})function App() {return (<ThemeProvider theme={customTheme}><div>...</div></ThemeProvider>)}
Some components may break if your custom theme does not include all the same keys as the default theme. For that reason, we recommend extending the default theme using deepmerge.
You can reference theme values in your application using the sx
prop, the themeGet
function, or the useTheme
hook.
Only use theme
objects accessed via Primer's theme context to ensure your application’s styling draws from the same theme as Primer components’ internal styling. The sx
prop, styled system props, themeGet
, and useTheme
all use the theme from context.
<Box textShadow="shadow.medium">
Use the theme from the same context as Primer.
import {theme} from '@primer/react'<Box textShadow={theme.shadows.shadow.medium}>
Don't style components with any other instance of theme
sx
propSome system props and sx
prop keys are theme-aware. For example, the bg
prop maps to the colors
theme key which means you can use the bg
prop to reference values in the colors
object:
const theme = {colors: {canvas: {default: '#fff'}}}function App() {return (<ThemeProvider theme={theme}><Box bg="canvas.default"></Box><Box sx={{bg: 'canvas.default'}}></Box></ThemeProvider>)}
See the Styled System Reference Table for a complete list of mappings.
The themeGet
function is a convenient way to reference theme values in styled-components template literals:
import {themeGet} from '@primer/react'import styled from 'styled-components'const Example = styled.div`background-color: ${themeGet('colors.canvas.default')};`
You can use the useTheme
hook to reference theme values from inside any function component nested under the ThemeProvider
:
import {ThemeProvider, useTheme} from '@primer/react'function Example() {const {theme} = useTheme()// theme.colors.canvas.default}function App() {return (<ThemeProvider><Example /></ThemeProvider>)}
Only use useTheme
to reference theme values in places where it's not possible to use system props, the sx
prop, or themeGet
.
The terms "color mode" and "color scheme" are often used interchangeably. However, in Primer React, they are two separate (but related) concepts.
The "color mode" of an application can be either day
, night
, or auto
(i.e. synced with the operating system).
A "color scheme", on the other hand, is a collection of colors that can be associated with a color mode. The default theme includes three color schemes: light
, dark
, and dark_dimmed
. By default, the light
scheme is displayed when the application is in day
mode and the dark
scheme is displayed in night
mode.
By default, Primer React is in day
mode. To change the color mode, use the colorMode
prop on ThemeProvider
or the setColorMode
function from the useTheme
hook:
colorMode
propimport {ThemeProvider} from '@primer/react'function App() {return (// colorMode can be "day" (default), "night", or "auto"<ThemeProvider colorMode="auto"><div>...</div></ThemeProvider>)}
setColorMode
functionimport {useTheme} from '@primer/react'function Example() {const {setColorMode} = useTheme()return <button onClick={() => setColorMode('auto')}>Activate auto mode</button>}
preventSSRMismatch
propIf you are doing server-side rendering, pass the preventSSRMismatch
prop to ensure the rendered output from the server and browser match even when they resolve "auto" color mode differently.
<ThemeProvider colorMode="auto" preventSSRMismatch>...</ThemeProvider>
To choose which color schemes will be displayed in day
and night
mode, use the dayScheme
and nightScheme
props on ThemeProvider
or the setDayScheme
and setNightScheme
functions from the useTheme
hook:
dayScheme
and nightScheme
propsimport {ThemeProvider} from '@primer/react'function App() {return (// The default theme includes `light`, `dark`, and `dark_dimmed` schemes<ThemeProvider dayScheme="light" nightScheme="dark_dimmed"><div>...</div></ThemeProvider>)}
setDayScheme
and setNightScheme
functionsimport {useTheme} from '@primer/react'function Example() {const {setDayScheme, setNightScheme} = useTheme()return <button onClick={() => setNightScheme('auto')}>Activate auto mode</button>}
To customize or add color schemes, update the colorSchemes
object in the theme:
import {ThemeProvider, theme} from '@primer/react'import deepmerge from 'deepmerge'const customTheme = deepmerge(theme, {colorSchemes: {// Customize an existing schemelight: {colors: {text: {primary: '#f00'}}},// Add a new schememy_scheme_name: {colors: {},shadows: {}}}})function App() {return (<ThemeProvider theme={customTheme}><div>...</div></ThemeProvider>)}
If you need to use a color that is not defined in the theme, avoid hard coding the color value like this:
function Example() {return (// BAD: #aaa may not look good in all color schemes<Box bg="#aaa">Hello world</Box>)}
Instead, use the useColorSchemeVar
hook to create a local variable that will update based on the active color scheme:
import {useColorSchemeVar} from '@primer/react'import {colors} from '@primer/primitives'function Example() {// GOOD: The value of `customBg` changes based on the active color schemeconst customBg = useColorSchemeVar({light: colors.light.scale.gray[1],dark: colors.dark.scale.gray[9],dark_dimmed: colors.dark_dimmed.scale.gray[2]})return <Box bg={customBg}>Hello world</Box>}