Atomico — библиотека для создания веб-компонентов на базе JavaScript, предоставляющая минималистичный, но мощный API для декларативного управления состоянием и интерфейсом. Одной из ключевых возможностей является динамическое управление стилями компонентов, что позволяет адаптировать внешний вид элементов под состояние приложения без необходимости изменения глобальных CSS-файлов.
В Atomico стили задаются через функцию css или в виде
объекта внутри компонента. Основная особенность — возможность связывать
CSS с реактивными свойствами.
import { c, css, useState } from "atomico";
const buttonStyles = css`
:host {
display: inline-block;
padding: 10px 20px;
border-radius: 5px;
background-color: var(--bg-color, #3498db);
color: var(--text-color, #fff);
cursor: pointer;
transition: background-color 0.3s;
}
`;
function Button() {
const [hover, setHover] = useState(false);
return (
<host shadowDom>
<buttonStyles />
<button
onMouseEn ter={() => setHover(true)}
onMouseLe ave={() => setHover(false)}
style={{
"--bg-color": hover ? "#2980b9" : "#3498db"
}}
>
Кнопка
</button>
</host>
);
}
customElements.define("x-button", c(Button));
Особенности подхода:
:host позволяет задавать стили для самого
веб-компонента.useState напрямую влияет на
свойства стиля.Atomico поддерживает реактивное обновление стилей через свойства
компонента. Можно определять стили на основе пропсов или состояния
компонента, используя объектную форму style или
css с функцией.
function Card({ highlight }) {
return (
<host shadowDom>
<style>
{`
:host {
display: block;
padding: 20px;
border-radius: 10px;
background-color: ${highlight ? "#f1c40f" : "#ecf0f1"};
transition: background-color 0.5s;
}
`}
</style>
<div>Контент карточки</div>
</host>
);
}
customElements.define("x-card", c(Card));
Ключевой момент: использование шаблонных литералов позволяет вычислять значения стилей динамически при каждом рендере, что обеспечивает гибкость интерфейса.
styleMapДля более сложных случаев применяется объектный синтаксис с
styleMap, позволяющий динамически менять несколько свойств
одновременно.
import { useState } from "atomico";
import { styleMap } from "atomico/utils";
function Box() {
const [size, setSize] = useState(100);
return (
<host shadowDom>
<div
style={styleMap({
width: `${size}px`,
height: `${size}px`,
backgroundColor: size > 150 ? "#e74c3c" : "#2ecc71",
transition: "all 0.3s"
})}
>
Динамический блок
</div>
<button onCl ick={() => setSize(size + 10)}>Увеличить</button>
</host>
);
}
customElements.define("x-box", c(Box));
Преимущества styleMap:
Atomico по умолчанию работает с Shadow DOM, что обеспечивает изоляцию стилей компонентов. Это позволяет не беспокоиться о конфликте с глобальными CSS и упрощает управление динамическими стилями.
function Badge({ active }) {
return (
<host shadowDom>
<style>
{`
:host {
display: inline-block;
padding: 5px 15px;
border-radius: 12px;
background-color: ${active ? "#27ae60" : "#95a5a6"};
color: #fff;
font-weight: bold;
}
`}
</style>
Статус
</host>
);
}
customElements.define("x-badge", c(Badge));
Использование shadowDom гарантирует, что динамические
стили будут применяться только к конкретному компоненту, независимо от
глобальных классов или внешнего CSS.
Динамические стили в Atomico удобно использовать для реализации темизации. Например, переключение светлой и тёмной темы через CSS-переменные:
function ThemedPanel({ theme }) {
return (
<host shadowDom>
<style>
{`
:host {
display: block;
padding: 20px;
border-radius: 10px;
background-color: var(--bg-color, #fff);
color: var(--text-color, #000);
}
`}
</style>
<div
style={{
"--bg-color": theme === "dark" ? "#2c3e50" : "#ecf0f1",
"--text-color": theme === "dark" ? "#ecf0f1" : "#2c3e50"
}}
>
Панель с темой {theme}
</div>
</host>
);
}
customElements.define("x-themed-panel", c(ThemedPanel));
Помимо прямого назначения стилей через style, Atomico
позволяет управлять CSS-классами динамически с помощью привязки через
объект или функцию:
function ToggleButton({ active }) {
return (
<host shadowDom>
<style>
{`
.active {
background-color: #e67e22;
color: #fff;
}
.inactive {
background-color: #bdc3c7;
color: #2c3e50;
}
`}
</style>
<button class={active ? "active" : "inactive"}>
{active ? "Включено" : "Выключено"}
</button>
</host>
);
}
customElements.define("x-toggle-button", c(ToggleButton));
Такой подход позволяет комбинировать преимущества CSS-классов с реактивностью JavaScript и динамическими переменными.
useState
обеспечивает эффективный ререндер только изменяющихся частей.Atomico предоставляет мощный и гибкий инструмент для работы с динамическими стилями, позволяя строить адаптивные, реактивные и изолированные интерфейсы без сложной работы с внешними CSS-файлами.