CSS переменные и темизация

Atomico — это современная библиотека для создания веб-компонентов на базе JavaScript и JSX-подобного синтаксиса. Одной из ключевых особенностей её подхода к стилям является удобная работа с CSS-переменными и поддержка динамической темизации, что позволяет строить гибкие, переиспользуемые компоненты.

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

CSS-переменные (Custom Properties) позволяют задавать значения стилей в одном месте и переиспользовать их по всему компоненту. В Atomico это реализуется через объект css или через прямое определение стилей внутри компонента.

Пример базового использования:

import { c, css } from "atomico";

const buttonStyles = css`
    :host {
        --button-bg: #6200ee;
        --button-color: #ffffff;
        display: inline-block;
        padding: 0.5em 1em;
        border-radius: 4px;
        background-color: var(--button-bg);
        color: var(--button-color);
        cursor: pointer;
        transition: background-color 0.3s ease;
    }

    :host(:hover) {
        background-color: #3700b3;
    }
`;

function Button() {
    return <host>Кнопка</host>;
}

Button.styles = buttonStyles;

customElements.define("my-button", c(Button));

Ключевые моменты:

  • :host используется для стилизации самого веб-компонента.
  • CSS-переменные определяются через --имя-переменной и могут быть переопределены при использовании компонента.
  • Переменные подключаются через var(--имя-переменной), что обеспечивает гибкость и повторное использование стилей.

Темизация компонентов

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

Пример темизации:

const themeLight = {
    "--bg-color": "#ffffff",
    "--text-color": "#000000"
};

const themeDark = {
    "--bg-color": "#121212",
    "--text-color": "#ffffff"
};

function applyTheme(theme) {
    Object.entries(theme).forEach(([key, value]) => {
        document.documentElement.style.setProperty(key, value);
    });
}

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

const cardStyles = css`
    :host {
        display: block;
        padding: 1em;
        background-color: var(--bg-color);
        color: var(--text-color);
        border-radius: 6px;
        box-shadow: 0 2px 8px rgba(0,0,0,0.1);
    }
`;

function Card() {
    return <host>Карточка с темой</host>;
}

Card.styles = cardStyles;

customElements.define("my-card", c(Card));

Темизация позволяет:

  • Создавать светлые и тёмные версии компонентов без изменения их исходного кода.
  • Менять визуальные параметры динамически, включая шрифты, размеры, цвета и тени.
  • Поддерживать модульность и переиспользуемость, делая компоненты независимыми от конкретной темы.

Динамическая смена тем

Atomico поддерживает реактивность через useEffect и useState, что позволяет менять темы без перезагрузки страницы:

import { useState, useEffect } from "atomico";

function ThemeSwitcher() {
    const [darkMode, setDarkMode] = useState(false);

    useEffect(() => {
        applyTheme(darkMode ? themeDark : themeLight);
    }, [darkMode]);

    return (
        <host>
            <button onCl ick={() => setDarkMode(!darkMode)}>
                Переключить тему
            </button>
            <my-card>Пример карточки</my-card>
        </host>
    );
}

customElements.define("theme-switcher", c(ThemeSwitcher));

Особенности подхода:

  • Использование реактивных хуков для управления состоянием темы.
  • Автоматическое обновление CSS-переменных, что мгновенно отражается на всех компонентах, использующих эти переменные.
  • Возможность объединять несколько тем, создавая настраиваемые схемы для разных разделов интерфейса.

Локальные и глобальные переменные

CSS-переменные могут быть локальными для компонента или глобальными для всей страницы:

  • Локальные: определяются внутри :host компонента.
  • Глобальные: задаются на :root или через document.documentElement.style.setProperty.

Пример комбинированного подхода:

const globalStyles = css`
    :root {
        --font-family: "Roboto", sans-serif;
        --border-radius: 8px;
    }
`;

document.head.appendChild(globalStyles);

Компоненты могут использовать как глобальные переменные, так и переопределять их локально:

:host {
    font-family: var(--font-family);
    border-radius: var(--border-radius);
}

Интеграция с JavaScript

С CSS-переменными удобно работать напрямую из JavaScript. Например, для анимации цвета:

const card = document.querySelector("my-card");
let hue = 0;

setInterval(() => {
    hue = (hue + 1) % 360;
    card.style.setProperty("--bg-color", `hsl(${hue}, 70%, 80%)`);
}, 50);

Такой подход позволяет создавать динамические визуальные эффекты, сохраняя преимущества реактивной стилизации и темизации.

Практические рекомендации

  • Использовать CSS-переменные для всех повторяющихся значений стилей: цвета, шрифты, отступы, тени.
  • Разделять темы на отдельные объекты и управлять ими через глобальные переменные.
  • Комбинировать локальные и глобальные переменные для обеспечения максимальной гибкости компонентов.
  • Использовать реактивные хуки Atomico для динамической смены тем без перезагрузки интерфейса.
  • Всегда задавать fallback значения через var(--name, fallback) для обеспечения корректного отображения при отсутствии переменной.

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