useColorMode и useColorModeValue

Механизм цветовых режимов — одна из ключевых возможностей библиотеки Chakra UI. Он позволяет реализовать переключение между светлой и тёмной темой интерфейса, автоматически применять соответствующие цвета компонентов и сохранять выбор пользователя.

Основой системы является хук useColorMode. Он предоставляет доступ к текущему режиму и функциям управления им.

Базовое использование

Хук импортируется из пакета Chakra UI:

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

При вызове хука возвращается объект с несколькими свойствами:

const { colorMode, toggleColorMode, setColorMode } = useColorMode()

Основные элементы:

Свойство Назначение
colorMode текущий режим (light или dark)
toggleColorMode переключение между режимами
setColorMode установка конкретного режима

Пример простого переключателя темы:

import { Button, useColorMode } from "@chakra-ui/react"

function ThemeToggle() {
  const { colorMode, toggleColorMode } = useColorMode()

  return (
    <Button onCl ick={toggleColorMode}>
      Текущий режим: {colorMode}
    </Button>
  )
}

При нажатии кнопки происходит переключение между светлой и тёмной темой.


Архитектура системы цветовых режимов

Система цветовых режимов Chakra UI построена вокруг нескольких механизмов:

1. Контекст React

Информация о режиме хранится в контексте, который создаётся внутри ChakraProvider.

2. CSS-переменные

Большинство цветов библиотеки представлены через CSS-переменные, которые автоматически изменяются при смене режима.

3. Хранение состояния

Выбранная тема сохраняется:

  • в localStorage
  • либо определяется через настройки системы пользователя (prefers-color-scheme)

Провайдер ColorModeScript

Для корректной работы цветовых режимов используется компонент ColorModeScript. Он вставляет небольшой скрипт, который устанавливает тему до загрузки React, предотвращая визуальное “мигание” интерфейса.

Пример использования в корневом файле приложения:

import { ChakraProvider, ColorModeScript } from "@chakra-ui/react"
import theme from "./theme"

function App() {
  return (
    <ChakraProvider theme={theme}>
      <ColorModeScript initialColorMode={theme.config.initialColorMode} />
      <MainApp />
    </ChakraProvider>
  )
}

Свойство colorMode

colorMode возвращает строку, отражающую текущий режим:

const { colorMode } = useColorMode()

Возможные значения:

  • "light"
  • "dark"

Использование в логике интерфейса:

const { colorMode } = useColorMode()

const text = colorMode === "light"
  ? "Светлая тема"
  : "Тёмная тема"

Функция toggleColorMode

Функция toggleColorMode переключает режим на противоположный.

const { toggleColorMode } = useColorMode()

Типичный пример — кнопка смены темы:

<Button onCl ick={toggleColorMode}>
  Переключить тему
</Button>

Алгоритм работы:

  1. Проверяется текущий режим
  2. Если light → устанавливается dark
  3. Если dark → устанавливается light
  4. Значение сохраняется в localStorage
  5. Обновляются CSS-переменные темы

Функция setColorMode

Иногда требуется явно установить определённый режим, а не переключать его.

Для этого используется setColorMode.

const { setColorMode } = useColorMode()

setColorMode("dark")

Пример интерфейса с явным выбором темы:

function ThemeButtons() {
  const { setColorMode } = useColorMode()

  return (
    <>
      <Button onCl ick={() => setColorMode("light")}>
        Светлая тема
      </Button>

      <Button onCl ick={() => setColorMode("dark")}>
        Тёмная тема
      </Button>
    </>
  )
}

Хук useColorModeValue

Хук useColorModeValue предназначен для выбора значения в зависимости от текущего режима темы.

Он избавляет от ручных условий if.

Синтаксис

const value = useColorModeValue(lightValue, darkValue)

Параметры:

Параметр Назначение
lightValue значение для светлой темы
darkValue значение для тёмной темы

Пример изменения цвета текста

import { Text, useColorModeValue } from "@chakra-ui/react"

function Title() {
  const color = useColorModeValue("gray.800", "gray.100")

  return <Text color={color}>Заголовок</Text>
}

Поведение:

  • светлая тема → gray.800
  • тёмная тема → gray.100

Пример динамического фона

import { Box, useColorModeValue } from "@chakra-ui/react"

function Card() {
  const bg = useColorModeValue("white", "gray.700")

  return (
    <Box p="6" bg={bg} borderRadius="md">
      Контент
    </Box>
  )
}

Использование внутри компонентов Chakra

Хук часто применяется вместе со свойствами компонентов:

const bg = useColorModeValue("gray.50", "gray.800")
const border = useColorModeValue("gray.200", "gray.600")

<Box bg={bg} border="1px solid" borderColor={border}>
  Контент
</Box>

Работа с тенями

Тени интерфейса могут отличаться для разных режимов.

const shadow = useColorModeValue(
  "0 2px 8px rgba(0,0,0,0.1)",
  "0 2px 8px rgba(0,0,0,0.6)"
)

Использование с иконками

Частый паттерн — отображение разных иконок для разных режимов.

import { SunIcon, MoonIcon } from "@chakra-ui/icons"

function ThemeIcon() {
  const { colorMode } = useColorMode()

  return colorMode === "light"
    ? <MoonIcon />
    : <SunIcon />
}

Комбинирование useColorMode и useColorModeValue

Оба хука часто используются совместно.

function ThemeButton() {
  const { toggleColorMode } = useColorMode()
  const bg = useColorModeValue("gray.200", "gray.700")

  return (
    <Button bg={bg} onCl ick={toggleColorMode}>
      Переключить тему
    </Button>
  )
}

Использование внутри пользовательских хуков

Цветовые режимы можно инкапсулировать в собственные хуки.

function useCardStyles() {
  return {
    bg: useColorModeValue("white", "gray.700"),
    border: useColorModeValue("gray.200", "gray.600")
  }
}

Использование:

const styles = useCardStyles()

<Box bg={styles.bg} borderColor={styles.border}>
  Карточка
</Box>

Конфигурация темы

Поведение системы цветовых режимов можно настроить в конфигурации темы.

const config = {
  initialColorMode: "light",
  useSystemColorMode: false
}

Параметры:

Свойство Назначение
initialColorMode начальный режим
useSystemColorMode использовать настройки системы

Создание темы:

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

const theme = extendTheme({ config })

Использование системных настроек

Если включить useSystemColorMode, Chakra UI будет использовать настройки операционной системы пользователя.

const config = {
  initialColorMode: "light",
  useSystemColorMode: true
}

При этом применяется медиазапрос:

prefers-color-scheme

Сохранение выбранной темы

Chakra UI автоматически сохраняет выбранный режим в localStorage.

Ключ хранения:

chakra-ui-color-mode

При повторной загрузке страницы тема восстанавливается.


Управление цветами через тему

Цвета компонентов можно задавать с учётом режимов внутри темы.

const styles = {
  global: (props) => ({
    body: {
      bg: props.colorMode === "dark"
        ? "gray.900"
        : "gray.50"
    }
  })
}

Типичные паттерны использования

Карточки интерфейса

const bg = useColorModeValue("white", "gray.800")

Текст

const color = useColorModeValue("gray.700", "gray.200")

Бордеры

const border = useColorModeValue("gray.200", "gray.600")

Ховер-эффекты

const hover = useColorModeValue("gray.100", "gray.700")

Производительность

useColorModeValue реализован максимально эффективно:

  • не вызывает лишних перерендеров
  • работает через контекст
  • быстро переключает CSS-переменные

При переключении темы Chakra UI обновляет только те компоненты, которые используют цветовые значения.


Распространённые ошибки

Использование вне ChakraProvider

Хуки цветовых режимов работают только внутри ChakraProvider.

Неправильно:

useColorMode()

вне дерева провайдера.


Ручные проверки вместо useColorModeValue

Неправильно:

const { colorMode } = useColorMode()

const color =
  colorMode === "light"
    ? "gray.800"
    : "gray.100"

Правильнее:

const color = useColorModeValue("gray.800", "gray.100")

Отсутствие ColorModeScript

Если не использовать ColorModeScript, при загрузке страницы может возникать кратковременная смена темы (flash of incorrect theme).


Практическая архитектура использования

Обычно система цветовых режимов строится следующим образом:

1. Конфигурация темы

theme.config

2. Провайдер

ChakraProvider

3. Скрипт инициализации

ColorModeScript

4. Управление режимом

useColorMode

5. Динамические значения

useColorModeValue

Такая архитектура позволяет реализовать полноценную поддержку светлой и тёмной темы с минимальным количеством кода и без необходимости вручную управлять CSS.