Динамическая загрузка тем

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


Основы работы с темами

В Chakra UI тема — это объект, который задаёт значения для ключевых аспектов интерфейса:

  • colors – палитра цветов для элементов и фонов;
  • fonts – настройки шрифтов;
  • fontSizes, fontWeights, lineHeights – типографические параметры;
  • space, sizes – размеры отступов, элементов и блоков;
  • components – кастомизация стилей конкретных компонентов.

Базовая тема создаётся с помощью функции extendTheme:

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

const customTheme = extendTheme({
  colors: {
    brand: {
      100: "#f7fafc",
      500: "#3182ce",
      900: "#1a365d",
    },
  },
  fonts: {
    heading: "Montserrat, sans-serif",
    body: "Inter, sans-serif",
  },
});

export default customTheme;

Подключение темы через ChakraProvider

Для использования темы её необходимо передать в ChakraProvider на верхнем уровне приложения:

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

function App() {
  return (
    <ChakraProvider theme={customTheme}>
      <Main />
    </ChakraProvider>
  );
}

Это позволяет всем компонентам в дереве наследовать стили из выбранной темы.


Динамическое переключение тем

Chakra UI поддерживает динамическое переключение тем через механизм Color Mode (light / dark). Для этого используется useColorMode:

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

function ToggleThemeButton() {
  const { colorMode, toggleColorMode } = useColorMode();

  return (
    <Button onCl ick={toggleColorMode}>
      Переключить на {colorMode === "light" ? "тёмную" : "светлую"} тему
    </Button>
  );
}
  • colorMode хранит текущий режим ("light" или "dark").
  • toggleColorMode переключает режим автоматически.
  • Chakra UI подставляет соответствующие значения цветов для всех компонентов, использующих токены из темы ("gray.50", "blue.500" и т.д.).

Создание нескольких пользовательских тем

Можно определить несколько отдельных тем и переключать их динамически через состояние React:

import { ChakraProvider } from "@chakra-ui/react";
import { useState } from "react";
import lightTheme from "./themes/light";
import darkTheme from "./themes/dark";

function App() {
  const [theme, setTheme] = useState(lightTheme);

  const switchTheme = () => {
    setTheme(theme === lightTheme ? darkTheme : lightTheme);
  };

  return (
    <ChakraProvider theme={theme}>
      <button onCl ick={switchTheme}>Сменить тему</button>
      <MainContent />
    </ChakraProvider>
  );
}

Такой подход позволяет создавать неограниченное количество кастомных тем и применять их в зависимости от действий пользователя или внешних условий (например, времени суток).


Использование CSS Variables для динамических стилей

Chakra UI поддерживает подстановку CSS-переменных в тему, что позволяет менять стили без пересоздания темы:

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

const theme = extendTheme({
  colors: {
    primary: "var(--color-primary)",
  },
});

export default theme;

Затем динамически менять переменные через Jav * aScript:

document.documentElement.style.setProperty("--color-primary", "#ff0000");

Это полезно для анимаций, кастомных переключателей и мгновенной смены цвета без полной перезагрузки React-компонентов.


Динамическая кастомизация компонентов

Chakra UI позволяет настраивать компоненты на лету с помощью useStyleConfig или useMultiStyleConfig:

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

function CustomCard({ variant }) {
  const styles = useStyleConfig("Card", { variant });

  return <Box __css={styles}>Содержимое карточки</Box>;
}
  • variant может быть динамически выбран на основе состояния или темы.
  • Можно комбинировать с colorMode для адаптивного стиля в светлой и тёмной темах.

Интеграция с локальным хранилищем и внешними настройками

Для сохранения выбранной темы между сессиями используют localStorage:

const savedTheme = localStorage.getItem("app-theme");
const [theme, setTheme] = useState(savedTheme === "dark" ? darkTheme : lightTheme);

const switchTheme = () => {
  const newTheme = theme === lightTheme ? darkTheme : lightTheme;
  setTheme(newTheme);
  localStorage.setItem("app-theme", newTheme === darkTheme ? "dark" : "light");
};

Это гарантирует, что пользователь всегда видит интерфейс в предпочитаемой теме при повторном посещении приложения.


Динамическая загрузка тем с сервера

Для корпоративных приложений или SaaS можно загружать темы с сервера в формате JSON:

import { ChakraProvider, extendTheme } from "@chakra-ui/react";
import { useEffect, useState } from "react";

function App() {
  const [theme, setTheme] = useState(null);

  useEffect(() => {
    fetch("/api/theme")
      .then(res => res.json())
      .then(data => setTheme(extendTheme(data)));
  }, []);

  if (!theme) return null;

  return <ChakraProvider theme={theme}><Main /></ChakraProvider>;
}
  • JSON может содержать любые параметры темы: цвета, шрифты, отступы.
  • Позволяет централизованно управлять стилями для всех клиентов.

Применение динамических тем к глобальному стилю

Помимо компонентов, можно управлять глобальными стилями через styles.global:

const theme = extendTheme({
  styles: {
    global: (props) => ({
      body: {
        bg: props.colorMode === "dark" ? "gray.900" : "gray.100",
        color: props.colorMode === "dark" ? "whiteAlpha.900" : "gray.800",
      },
    }),
  },
});

Это позволяет адаптировать весь интерфейс под выбранную тему, включая сторонние компоненты и нестандартные элементы.


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