Cosmic UI: компоненты React, темы и практические примеры
Разбираем Cosmic UI на практических сценариях: настраиваем тему, показываем состояния кнопки, открываем диалог и проверяем клавиатуру. Площадка с примерами и пояснениями к коду.

У интерфейса космического терминала есть узнаваемый язык: угловатые рамки, светящиеся акценты, технические подписи и панели с чётким ритмом. Но посетитель всё равно хочет выполнить обычную задачу — выбрать режим, заполнить поле, подтвердить действие. Разберём Cosmic UI с этой точки зрения: как получить выразительный React-интерфейс и сохранить понятное поведение его элементов.
Декоративная рамка задаёт характер, действия остаются привычными, а логика состояний управляет открытием, выбором и фокусом.
Увеличить изображение ⤢Что такое Cosmic UI и для каких задач он подходит
Cosmic UI — набор компонентов с оформлением в духе научной фантастики. На официальном сайте есть отдельные примеры для React и Vue; здесь рассматриваем React. Кнопки, поля, диалоги и вкладки используют общий визуальный язык. Его характерная часть — Frame, SVG-декорация с несколькими контурами, срезанными углами и настраиваемыми цветами.
Удобная область применения — небольшая панель управления, демонстрация продукта, игровой кабинет или необычная страница проекта. Сначала выделите несколько повторяемых элементов: основное действие, переключение разделов, форму настройки. Затем дайте им одинаковые правила цвета, отступов и подписей. Такой подход помогает построить цельный экран, а не коллекцию эффектных деталей.
Если на странице много текста, оставьте ему спокойную область и обычный читаемый шрифт. Яркую рамку лучше поставить вокруг важного блока, чем вокруг каждого предложения. Цвет тоже должен иметь назначение: основной акцент ведёт к следующему действию, предупреждение объясняет риск, подтверждение показывает результат. Вид интерфейса можно сделать необычным, сохранив привычную логику.
Компоненты добавляются в исходники проекта. Это позволяет изучать их разметку и менять оболочку под свою задачу. При этом установка одной кнопки не подключает готовую бизнес-логику: отправку формы, проверку доступа и обработку ответа сервера разработчик задаёт отдельно.
Учебная площадка: смотрите на сценарий, а не только на форму
Площадка ниже предназначена для проверки оформления и поведения. Поменяйте параметры примера, попробуйте действия мышью и клавиатурой, сравните состояния элементов. Тексты и настройки здесь нужны для демонстрации интерфейса; они не означают отправку заявки, запуск оборудования или сохранение данных в вашем проекте.
На площадке разбираем восемь групп: кнопки, поля, флажки и переключатели, вкладки, аккордеон, диалог, меню и уведомления. Палитра и сила свечения относятся к нашей оболочке примеров. Сначала выберите знакомый элемент, затем проверьте его в другом оформлении: поведение должно оставаться предсказуемым.
Выберите пример, измените акцент и проверьте кнопки, формы, вкладки и диалоги. Настройки остаются в вашем браузере. Отдельная вкладка удобна для просмотра компонентов и кода рядом. Скриншот нашей интерактивной площадки. Выберите компонент, измените палитру и попробуйте действие; затем скопируйте пример для своего React-проекта.Попробуйте компоненты Cosmic UI
- Начните с обычного состояния. Видно ли, какая кнопка главная? Понятно ли назначение поля без пояснения автора?
- Выполните действие. Дождитесь результата. Обратите внимание, остаётся ли интерфейс понятным в промежуточном состоянии.
- Повторите без мыши. Перейдите к элементу клавишей Tab, активируйте его и найдите способ вернуться назад.
- Измените условия. Выберите длинную подпись или узкий экран. Проверьте, что рамка, текст и зона нажатия продолжают работать вместе.
Хороший результат — не просто красивый первый кадр. Посетитель должен различать выбранный режим и наведение, понимать причину недоступного действия и видеть подтверждение после завершения операции. Если это теряется при смене цвета, сначала поправьте контраст и подписи, затем добавляйте свечение.
Подключение: проект, стили и CLI решают разные задачи
Для самостоятельного React-примера официальный маршрут предполагает проект с TypeScript, сборку Vite и Tailwind CSS. Tailwind создаёт используемые компонентами классы, CSS-переменные задают цвета, а CLI переносит нужные файлы и находит их зависимости. Эти части нужны вместе: файл кнопки без её рамки или без собранных стилей не даст ожидаемый результат.
В React-проекте, где уже настроены Tailwind 4 и алиас @, можно начать с таких команд. Дополнительно устанавливаем CSS-анимации. Версия CLI указана явно; серверный реестр компонентов при этом может обновляться независимо от неё.
npx @left4code/cosmic-ui-cli@0.1.0 init --framework react
npx @left4code/cosmic-ui-cli@0.1.0 add button dialog tabs
npm install tw-animate-css
npm run dev
init создаёт cosmic.json и файл цветовых токенов. При стандартном каталоге src/components это src/cosmic-ui.css. add записывает выбранные компоненты, связанные файлы и предлагает установить npm-зависимости. Например, диалог использует общие части для портала, присутствия на странице и рамки. Проверьте предложенный состав, затем откройте простой экран с одним элементом.
В конфигурации проекта понадобится алиас @ к src: он должен разрешаться и TypeScript, и Vite. Входной CSS должен подключать Tailwind и токены. Зависимости анимации и SVG-отрисовки тоже должны присутствовать, если их использует выбранный компонент. Точный порядок первоначальной настройки приведён в официальной инструкции подключения.
Темы: меняйте смысловые токены, а не каждый элемент отдельно
Токен — именованная переменная для повторяемого решения. --color-primary задаёт основной акцент, --color-primary-foreground — текст для этого акцента. Аналогичные пары есть для дополнительных, успешных и опасных действий. Рамки используют эти цвета через собственные переменные штриха и заливки, поэтому согласованная палитра затрагивает несколько компонентов сразу.
Ниже — небольшой собственный пример настройки. Он рассчитан на CSS-вход Tailwind 4 и уже созданный CLI-файл токенов. Класс cosmic-preview — наша область демонстрации; его нужно поставить на контейнер с примерами.
@import "tailwindcss";
@import "tw-animate-css";
@import "./cosmic-ui.css";
.cosmic-preview {
--color-primary: #76d7ff;
--color-primary-foreground: #f5fbff;
--color-accent: #ffc48a;
--color-accent-foreground: #fff8f0;
--color-background: #102332;
--color-foreground: #edf5fb;
background: var(--color-background);
color: var(--color-foreground);
}
.cosmic-preview button:focus-visible {
outline: 2px solid var(--color-primary);
outline-offset: 4px;
}
Перед изменением палитры определите фон экрана и фон самого элемента. Полупрозрачная заливка смешивается с окружением: один и тот же цвет на светлой карточке и тёмной панели воспринимается по-разному. Поэтому проверяйте кнопку на настоящем фоне, включая наведение, выбранное состояние и недоступное действие.
Переменные контейнера наследуют его потомки. У диалога, который переносится через портал в document.body, другая ветка DOM. Если тема нужна всему приложению, задайте её на общем корне документа; если только отдельному виджету — предусмотрите передачу темы к его порталу. Иначе панель может быть бирюзовой, а открывшееся окно получит исходную палитру.
Не называйте изменение двух цветов полноценной дизайн-системой. Для последовательного результата нужны ещё размеры текста, отступы, состояния, правила использования и проверка контраста. Начните с одной пары «фон — текст», затем добавьте акценты и только после этого декоративные эффекты.
Кнопка: показывайте действие, ожидание и результат
У Button есть варианты default, accent, secondary, success и destructive. Форма задаётся отдельно: например, flat упрощает декорацию, а simple меняет контур. Выберите вариант по назначению действия. Подпись «Сохранить настройки» объясняет больше, чем «Активировать протокол», если речь идёт об обычном сохранении.
Для длительного действия заведите понятные состояния. В нашем примере это «готово к работе», «сохраняем», «получилось» и «ошибка». Функция saveProject передаётся извне: именно она выполняет реальную работу и возвращает Promise. Цвет кнопки лишь сообщает, что произошло.
import { useState } from "react";
import { Button } from "@/components/ui/button";
export function SaveControl({ saveProject }: {
saveProject: () => Promise<void>;
}) {
const [state, setState] = useState<"idle" | "saving" | "done" | "error">("idle");
const busy = state === "saving";
async function save() {
if (busy) return;
setState("saving");
try { await saveProject(); setState("done"); }
catch { setState("error"); }
}
return <>
<Button type="button" disabled={busy} aria-busy={busy}
variant={state === "error" ? "destructive" : "default"}
onClick={save}>
{busy ? "Сохраняем…" : "Сохранить настройки"}
</Button>
<p aria-live="polite">
{state === "done" ? "Настройки сохранены." :
state === "error" ? "Не удалось сохранить. Повторите попытку." : ""}
</p>
</>;
}
Пока операция идёт, повторное нажатие недоступно; после ошибки пользователь получает способ повторить действие. Успех показываем только после завершения Promise. В настоящем приложении дополните сообщение полезной причиной сбоя, а на сервере предусмотрите защиту от повторной обработки важной операции.
aria-busy сообщает о промежуточном состоянии, aria-live помогает озвучить результат без ручного перевода фокуса. Они не заменяют видимую подпись. Не сообщайте об успешном сохранении только зелёной рамкой: её значение должно подтверждаться текстом.
Диалоги и вкладки: поведение важнее декоративной рамки
Часть интерактивных компонентов Cosmic UI использует Zag.js. Его машина состояний определяет, какие переходы допустимы, а connect связывает их с DOM-атрибутами и событиями. Для диалога важны открытие, закрытие и фокус; для вкладок — выбранный раздел и перемещение между переключателями. Это отдельная задача от бизнес-состояний кнопки сохранения выше.
Польза такого подхода проявляется при нескольких способах управления одним элементом. Окно можно открыть кнопкой, закрыть Escape или действием внутри; приложение тоже может изменить open. Согласованная логика должна привести все эти пути к одному результату. Упрощённо маршрут выглядит так:
| Исходное состояние | Событие | Что меняется для пользователя |
|---|---|---|
| Окно закрыто | Активирована кнопка открытия | Окно появляется, фокус переходит внутрь |
| Окно открыто | Нажата Tab | Фокус движется между доступными элементами окна |
| Окно открыто | Нажата Escape или кнопка отмены | Окно закрывается, фокус возвращается к вызвавшему элементу |
Таблица описывает ожидаемое поведение модального режима, а не внутренние имена узлов Zag. Разработчику полезно мыслить такими переходами: тогда после смены разметки он проверяет целый сценарий, а не только значение одного boolean.
Модальный диалог подходит для короткого действия, требующего внимания. Заголовок объясняет цель, описание — последствия, кнопки позволяют продолжить или отказаться. Собственный пример ниже использует реальные части API Cosmic UI; callback resetDraft задаёт действие приложения.
import { useState } from "react";
import { Button } from "@/components/ui/button";
import { DialogRoot, DialogTrigger, DialogContent, DialogTitle,
DialogDescription, DialogCloseTrigger } from "@/components/ui/dialog";
export function ResetDialog({ resetDraft }: { resetDraft: () => void }) {
const [open, setOpen] = useState(false);
return <DialogRoot open={open} onOpenChange={({ open }) => setOpen(open)}>
<DialogTrigger>Сбросить черновик</DialogTrigger>
<DialogContent>
<DialogTitle>Вернуть начальные настройки?</DialogTitle>
<DialogDescription>Текущие настройки черновика будут заменены.</DialogDescription>
<DialogCloseTrigger asChild>
<Button type="button" variant="secondary">Оставить как есть</Button>
</DialogCloseTrigger>
<Button type="button" variant="destructive" onClick={() => {
resetDraft(); setOpen(false);
}}>Сбросить</Button>
</DialogContent>
</DialogRoot>;
}
Здесь состояние open контролирует наше приложение. DialogContent уже включает портал и подложку, поэтому дополнительная внешняя подложка не нужна. asChild у закрывающего элемента позволяет передать действие обычному Button. Это свойство не следует автоматически переносить на все остальные части API.
Проверьте, что после открытия фокус оказался внутри окна, Tab не уходит в фон страницы, Escape закрывает окно, а затем фокус возвращается к вызвавшей его кнопке. Для необратимого действия первым доступным выбором удобно оставить отказ. Если сохранение асинхронное, не закрывайте окно до ответа: покажите ожидание и ошибку внутри него.
Для вкладок используйте TabsRoot, TabsList, TabsTrigger и TabsContent. Значение value переключателя должно совпадать со значением его панели; defaultValue задаёт начальный раздел. Вкладки помогают переключать представления одного контекста, например «Обзор», «Параметры», «Журнал». Разные страницы сайта лучше оставлять ссылками с отдельными адресами.
В проверенном исходнике Cosmic UI содержимое TabsContent обёрнуто в параграф. Короткий текст туда подходит; сложная форма, таблица или вложенные блочные элементы требуют пересмотра этой разметки. Проверяйте полученный DOM, а не только внешний вид: библиотечный пример может нуждаться в адаптации под ваш сценарий.
Доступность и мобильный экран: проверьте реальную задачу
Наличие машины состояний помогает с клавиатурой и ARIA, но не гарантирует доступность готового экрана. Названия, контраст, размеры, порядок элементов и содержимое задаёт автор приложения. Декоративная рамка тоже не должна перехватывать нажатия или заменять настоящий button.
- Клавиатура. Пройдите экран Tab и Shift+Tab. Фокус должен быть заметным. Обычная кнопка должна срабатывать с клавиатуры, а порядок переходов — соответствовать чтению страницы.
- Поля. Дайте каждому полю видимую подпись. Placeholder может исчезнуть после ввода, поэтому он не заменяет label. Ошибка должна объяснять, что исправить.
- Цвет. Проверяйте текст на фактическом фоне и не кодируйте смысл только оттенком. Выбранный режим должен отличаться от простого наведения.
- Движение. Для добавленных анимаций учитывайте
prefers-reduced-motion. Состояние и результат должны быть понятны при отключённых эффектах. - Мобильный экран. Уберите жёсткую ширину, проверьте длинные русские подписи, перенос действий и прокрутку открытого диалога. Эффект наведения не должен быть единственным способом узнать назначение элемента.
Проверяйте доступность в конкретном сценарии: открыть настройки, изменить значение, сохранить, увидеть результат, вернуться к исходному экрану. Такой маршрут быстро выявляет исчезающий фокус, кнопку за пределами окна и непонятную ошибку. Красивый скриншот этих проблем не показывает.
Как перенести пример в проект и развивать его дальше
Начните с одного небольшого экрана и нескольких нужных компонентов. Отделите настройки темы от содержимого, а демонстрационные действия — от реальной логики приложения. После первого рабочего сценария добавляйте поля, уведомления и дополнительные панели. Это позволяет проверять целое действие после каждого изменения.
Архив на площадке содержит наш учебный проект и README. После распаковки выполните npm ci, затем npm run setup и npm run dev. Setup получает официальные компоненты из зафиксированной ревизии репозитория и проверяет контрольные суммы файлов. Такой путь отличается от CLI-команд выше, которые предназначены для добавления компонентов в ваш существующий проект и обращаются к текущему реестру.
В исходниках примера полезно сохранять README, lockfile, перечень зависимостей и точную версию использованных компонентов. CLI переносит код в проект, поэтому обновление требует сравнения собственных изменений с новым исходником. Не заменяйте настроенные файлы вслепую: сначала посмотрите различия, затем проверьте импорт, тему, клавиатуру и основной сценарий.
Условия разных частей проекта тоже проверяйте отдельно. На дату подготовки материала MIT указана в package.json официального CLI; отдельный общий файл LICENSE для корня репозитория не обнаружен. Это не основание объявлять весь набор компонентов и его ресурсы MIT. Инструкции установки и примеры доступны на официальном сайте Cosmic UI; для распространяемого проекта сохраняйте фактические уведомления и сведения о его составе.
Характер интерфейса появляется из согласованных решений: одна палитра, понятные действия, аккуратные состояния и устойчивое поведение. Начните с кнопки и небольшого окна настроек, проверьте их без мыши и на телефоне, затем расширяйте экран. Так Cosmic UI становится основой полезного интерфейса, а декоративные детали поддерживают его задачу.
