javascript

shadcn-glass-ui: Glassmorphism поверх shadcn/ui без миграции

  • понедельник, 22 декабря 2025 г. в 00:00:07
https://habr.com/ru/articles/979046/

Привет, Хабр! Представляю shadcn-glass-ui — React-библиотеку с glassmorphism-эффектами, которая устанавливается поверх существующих shadcn/ui проектов за 2 команды. Никакой миграции, никакого переписывания кода — просто добавьте glass-варианты ваших компонентов.

Demo
Demo

TL;DR

# Добавьте registry в components.json
npx shadcn@latest add @shadcn-glass-ui/button-glass

# Используйте рядом с обычными компонентами
import { Button } from '@/components/ui/button';
import { ButtonGlass } from '@/components/glass/ui/button-glass';

Ключевые фичи:

  • 🔗 100% совместимость с shadcn/ui — одинаковые API, можно смешивать компоненты

  • 🚀 Progressive enhancement — MVP на базовых компонентах → glassmorphism → кастомный бренд

  • 🎨 57 production-ready компонентов — от кнопок до сложных составных компонентов

  • 🔧 3-слойная токен-система — новая тема за 15 строк CSS, ноль хардкод-значений

  • 🤖 AI-First документация — Context7 MCP, Claude Code, GitHub Copilot

  • 📦 Два способа установки — через shadcn CLI или npm-пакет

  • WCAG 2.1 AA — полная доступность, 1500+ автотестов

Проблема: как добавить glassmorphism в существующий проект?

Glassmorphism — это тренд из iOS/macOS: полупрозрачные элементы с backdrop-filter: blur(), создающие эффект матового стекла. Apple использует его с iOS 15, Microsoft — в Fluent Design.

Текущие решения:

  • 📚 CSS-библиотеки (glass.css) — нет React-компонентов, нужно писать вручную

  • 🔄 Полноценные UI-фреймворки — требуют полной миграции проекта

  • ✍️ Кастомные компоненты — нужно ��исать всё с нуля и поддерживать

Что если у вас уже есть shadcn/ui проект? Переписывать всё на новый фреймворк? Копировать CSS из примеров и адаптировать каждый компонент?

Решение: Progressive Enhancement Workflow

shadcn-glass-ui реализует подход постепенного улучшения:

🏗️ Phase 1: MVP на базовых компонентах
   ↓ shadcn/ui — быстрый старт, проверка идеи
   
🎨 Phase 2: Добавление glassmorphism
   ↓ shadcn-glass-ui — визуальное улучшение без переписывания
   
🔧 Phase 3: Брендинг и кастомизация
   ↓ 3-слойная токен-система — тема под бренд за 15 строк

Для кого это идеально:

  • Стартапы — быстрый MVP → потом полировка дизайна

  • Агентства — шаблонный проект → кастомизация под клиента

  • Enterprise — прототип на shadcn/ui → production-ready с брендингом

  • Фрилансеры — один codebase → разные визуальные стили для клиентов

Drop-in совместимость

shadcn-glass-ui работает поверх существующих shadcn/ui проектов:

// ✅ Ваши существующие компоненты продолжают работать
import { Button } from '@/components/ui/button';
import { Input } from '@/components/ui/input';

// ✅ Glass-варианты добавляются отдельно
import { ButtonGlass } from '@/components/glass/ui/button-glass';
import { InputGlass } from '@/components/glass/ui/input-glass';

function LoginForm() {
  return (
    <form className="space-y-4">
      {/* Стандартный shadcn/ui */}
      <Input placeholder="Email" />
      <Button variant="outline">Обычная кнопка</Button>
      
      {/* Glass-варианты с эффектами */}
      <InputGlass placeholder="Password" type="password" />
      <ButtonGlass variant="primary">Войти с glass-эффектом</ButtonGlass>
    </form>
  );
}

Никакой миграции:

  • ✅ Те же пропсы: variant, size, className

  • ��� Те же коллбэки: onValueChange, onPressedChange

  • ✅ Та же поддержка asChild для полиморфных компонентов

  • ✅ Та же CLI-установка через npx shadcn add

Сравнение API

Компонент

shadcn/ui

shadcn-glass-ui v2.0

Совместимость

Button

variant="default"

variant="default"

✅ 100%

Toggle

pressed, onPressedChange

pressed, onPressedChange

✅ 100%

Slider

value: number[], onValueChange

value: number[], onValueChange

✅ 100%

ComboBox

value, onValueChange

value, onValueChange

✅ 100%

Дополнительно:

  • 🎨 Glassmorphism-эффекты из коробки

  • ⚙️ Дополнительные пропсы: loading, icon, intensity

  • 🧩 Compound Components API для сложных компонентов

Установка: два способа

Способ 1: shadcn CLI (рекомендуется)

Библиотека добавлена в registry.directory.

Шаг 1: Добавьте registry в components.json:

{
  "registries": {
    "@shadcn-glass-ui": {
      "url": "https://raw.githubusercontent.com/Yhooi2/shadcn-glass-ui-library/main/public/r"
    }
  }
}

Шаг 2: Установите нужные компоненты:

# Одна команда — один компонент
npx shadcn@latest add @shadcn-glass-ui/button-glass
npx shadcn@latest add @shadcn-glass-ui/input-glass
npx shadcn@latest add @shadcn-glass-ui/modal-glass

# Или сразу несколько
npx shadcn@latest add @shadcn-glass-ui/button-glass @shadcn-glass-ui/input-glass

Преимущества:

  • ✅ Минимальный бандл — только то, что используете

  • ✅ Код копируется в проект — полный контроль

  • ✅ Можно модифицировать под свои нужды

  • ✅ Нет зависимости от npm-пакета

Способ 2: npm-пакет

npm install shadcn-glass-ui
import { ButtonGlass, InputGlass, ThemeProvider } from 'shadcn-glass-ui';
import 'shadcn-glass-ui/dist/styles.css';

function App() {
  return (
    <ThemeProvider defaultTheme="glass">
      <div className="p-8 space-y-4">
        <ButtonGlass variant="primary" size="lg">
          Кликни меня! ✨
        </ButtonGlass>
        <InputGlass placeholder="Введите текст..." />
      </div>
    </ThemeProvider>
  );
}

Преимущества:

  • ✅ Быстрая установка одной командой

  • ✅ Автоматические обновления через npm

  • ✅ Tree-shaking — неиспользуемый код не попадёт в бандл

3-слойная токен-система: ноль хардкода

Главная архитектурная идея v2.0 — полное отсутствие хардкод-значений. Все цвета определяются через CSS variables на трёх уровнях:

┌─────────────────────────────────────────────────────────────┐
│ Layer 3: Component Tokens (280+ переменных)                 │
│ --btn-primary-bg, --modal-surface, --input-border           │
│         ↓ автоматически наследуют                           │
│ Layer 2: Semantic Tokens (~15 на тему)                      │
│ --semantic-primary, --semantic-surface, --semantic-border   │
│         ↓ ссылаются на                                      │
│ Layer 1: Primitive Tokens (225 OKLCH-цветов)                │
│ --oklch-purple-500, --oklch-slate-900                       │
└─────────────────────────────────────────────────────────────┘

Как это работает

Layer 1 — палитра из 225 OKLCH-цветов, определённая один раз для всех тем:

:root {
  --oklch-purple-500: oklch(0.55 0.25 270);
  --oklch-slate-900: oklch(0.15 0.02 250);
  --oklch-emerald-500: oklch(0.55 0.20 160);
  --oklch-cyan-400: oklch(0.70 0.15 195);
  /* ... ещё 221 цвет */
}

Layer 2 — каждая тема определяет ~15 семантических токенов:

[data-theme='glass'] {
  --semantic-primary: var(--oklch-purple-500);
  --semantic-surface: var(--oklch-slate-900);
  --semantic-text: var(--oklch-white-95);
  --semantic-border: var(--oklch-slate-700);
  --semantic-glow: var(--oklch-purple-500);
  /* ... ещё 10 токенов */
}

Layer 3 — компоненты автоматически наследуют из семантики:

:root {
  --btn-primary-bg: var(--semantic-primary);
  --btn-primary-glow: var(--semantic-glow);
  --modal-surface: var(--semantic-surface);
  --input-border: var(--semantic-border);
  /* ... 280+ компонентных токенов */
}

Новая тема за 15 строк CSS

Хотите создать неоновую тему? Переопределите только семантич��ский слой:

[data-theme='neon'] {
  --semantic-primary: var(--oklch-cyan-400);
  --semantic-secondary: var(--oklch-purple-400);
  --semantic-surface: var(--oklch-black-10);
  --semantic-surface-elevated: var(--oklch-slate-950);
  --semantic-text: var(--oklch-white-98);
  --semantic-text-muted: var(--oklch-slate-400);
  --semantic-border: var(--oklch-cyan-500);
  --semantic-border-subtle: var(--oklch-slate-800);
  --semantic-glow: var(--oklch-cyan-400);
  --semantic-success: var(--oklch-emerald-500);
  --semantic-warning: var(--oklch-amber-500);
  --semantic-destructive: var(--oklch-red-500);
  --semantic-info: var(--oklch-blue-500);
}

Результат:

  • ✅ Все 57 компонентов автоматически подхватят новые цвета

  • ✅ Переключение темы мгновенное — меняется только CSS, без перерендера React

  • ✅ 280+ компонентных токенов обновятся автоматически

Use Case: От MVP до Production

Сценарий: SaaS-стартап разрабатывает dashboard для аналитики.

Week 1-2: MVP на shadcn/ui

// Быстрый прототип с базовыми компонентами
import { Button, Input, Card } from '@/components/ui';

function Dashboard() {
  return (
    <div>
      <Card>
        <h2>Metrics</h2>
        <Input placeholder="Search..." />
        <Button>Export</Button>
      </Card>
    </div>
  );
}

Week 3: Добавляем glassmorphism

# Одна команда — visual upgrade
npx shadcn@latest add @shadcn-glass-ui/card-glass
npx shadcn@latest add @shadcn-glass-ui/button-glass
npx shadcn@latest add @shadcn-glass-ui/input-glass
// Меняем только импорты — API идентичный
import { ButtonGlass, InputGlass, CardGlass } from '@/components/glass/ui';

function Dashboard() {
  return (
    <div>
      <CardGlass> {/* Теперь с blur и glow эффектами */}
        <h2>Metrics</h2>
        <InputGlass placeholder="Search..." />
        <ButtonGlass>Export</ButtonGlass>
      </CardGlass>
    </div>
  );
}

Week 4: Брендинг под корпоративные цвета

/* 15 строк — вся компания в бренде */
[data-theme='company'] {
  --semantic-primary: var(--oklch-blue-600);      /* Корп. синий */
  --semantic-secondary: var(--oklch-orange-500);  /* Корп. оранжевый */
  --semantic-surface: var(--oklch-slate-900);     /* Тёмный фон */
  --semantic-glow: var(--oklch-blue-400);         /* Синее свечение */
  /* ... остальные 10 токенов */
}

Результат:

  • 0 переписанного кода — только замена импортов

  • 🎨 Полный ребрендинг за 15 строк CSS

  • 🚀 От идеи до production за месяц

До и после

Метрика

v1.x (старая архитектура)

v2.0 (токен-система)

Хардкод-значения OKLCH

~280 на тему

0

CSS-переменных на тему

~85

296+ (автонаследование)

Строк для новой темы

~280

~15

Переключение темы

Перерендер React

Instant CSS swap

AI-First: документация для ассистентов

В 2024–2025 разработчики активно используют AI-ассистенты (Claude, Copilot, ChatGPT). Проблема — большинство библиотек плохо индексируются: неявные API, устаревшая документация в обучающих данных.

shadcn-glass-ui оптимизирована для AI:

AI-инструмент

Интеграция

Что даёт

Context7 MCP

Автоиндексация

41 правило, автофетч актуальной документации

Claude Code

CLAUDE.md

365 строк контекста проекта, паттерны, примеры

GitHub Copilot

TypeScript strict + JSDoc

Точные автодополнения с примерами

ChatGPT/GPT-4

EXPORTS_MAP.json

Machine-readable реестр компонентов

Пример работы с Context7 MCP

Context7 — это Model Context Protocol для индексации документации. AI-ассистенты запрашивают актуальную документацию в реальном времени вместо того, чтобы полагаться на устаревшие обучающие данные.

Типичный workflow:

Разработчик: "Добавь stepper в checkout flow с тремя шагами"

→ Claude Code запрашивает документацию через Context7 MCP
→ Context7 возвращает актуальную документацию StepperGlass
→ Claude видит: "compound API, linear mode для визардов, 3 варианта"
→ Claude генерирует корректный код:
<StepperGlass.Root mode="linear" currentStep={step}>
  <StepperGlass.Step value={0}>
    <StepperGlass.Trigger>
      <StepperGlass.Icon />
      Доставка
    </StepperGlass.Trigger>
    <StepperGlass.Content>
      <AddressForm />
    </StepperGlass.Content>
  </StepperGlass.Step>
  
  <StepperGlass.Step value={1}>
    <StepperGlass.Trigger>
      <StepperGlass.Icon />
      Оплата
    </StepperGlass.Trigger>
    <StepperGlass.Content>
      <PaymentForm />
    </StepperGlass.Content>
  </StepperGlass.Step>
  
  <StepperGlass.Step value={2}>
    <StepperGlass.Trigger>
      <StepperGlass.Icon />
      Подтверждение
    </StepperGlass.Trigger>
    <StepperGlass.Content>
      <OrderSummary />
    </StepperGlass.Content>
  </StepperGlass.Step>
</StepperGlass.Root>

Без Context7 AI пришлось бы:

  1. Полагаться на устаревшую документацию из обучающих данных

  2. Гадать по названию API (может step вместо value?)

  3. Не знать про режим linear для визардов

  4. Пропустить StepperGlass.Icon и другие подкомпоненты

Decision Trees для AI

Дополнительно в репозитории есть деревья решений — какой компонент выбрать для конкретной задачи:

Нужно показать метрику?
├─ Один показатель → MetricCardGlass
├─ Сравнение нескольких → MetricsGridGlass
├─ С динамикой (sparkline) → SparklineGlass
└─ Круговая диаграмма → CircularMetricGlass

Нужна модалка?
├─ Простое подтверждение → AlertGlass
├─ Форма с несколькими полями → ModalGlass.Root (compound)
└─ Toast-уведомление → NotificationGlass

Rich JSDoc для всех компонентов

Каждый компонент содержит детальную JSDoc с примерами:

/**
 * Glass-styled button with glassmorphism effect
 * 
 * @example
 * // Primary button with loading state
 * <ButtonGlass variant="primary" size="lg" loading>
 *   Загрузка...
 * </ButtonGlass>
 * 
 * @example
 * // As link with React Router (polymorphic)
 * <ButtonGlass asChild>
 *   <Link to="/profile">Профиль</Link>
 * </ButtonGlass>
 * 
 * @example
 * // With icon
 * <ButtonGlass icon={<CheckIcon />} variant="ghost">
 *   Сохранено
 * </ButtonGlass>
 * 
 * @accessibility 
 * - Keyboard navigation (Enter, Space)
 * - Focus visible ring (2px inner + 4px outer)
 * - Touch target minimum 44x44px (Apple HIG)
 * - Loading state disables interaction
 */
export const ButtonGlass: React.FC<ButtonGlassProps> = ({ 
  variant = "default",
  size = "md",
  loading = false,
  icon,
  asChild = false,
  ...props 
}) => { /* ... */ };

AI видит примеры прямо в типах и генерирует корректный код с первого раза.

Компоненты: 57 production-ready

shadcn-glass-ui предоставляет 57 компонентов в 6 категориях:

Категория

Кол-во

Описание

Примеры

Core UI

18

Базовые building blocks

ButtonGlass, InputGlass, ModalGlass, TabsGlass, CheckboxGlass, SliderGlass

Atomic

7

Простые однофункциональные

SearchBoxGlass, ThemeToggleGlass, IconButtonGlass, StatItemGlass

Composite

13

Готовые сложные виджеты

MetricCardGlass, AICardGlass, RepositoryCardGlass, UserInfoGlass

Sections

7

Полноценные секции страниц

HeaderNavGlass, ProfileHeaderGlass, CareerStatsGlass, ProjectsListGlass

Specialized

10

Специализированные компоненты

SparklineGlass, StepperGlass (3 варианта), RainbowProgressGlass

Primitives

3

Низкоуровневые примитивы

TouchTarget, FormFieldWrapper, InteractiveCard

Три встроенные темы

  • Glass (тёмная) — классический glassmorphism с фиолетовыми акцентами и glow-эффектами

  • Light (светлая) — минималистичная светлая тема с тонкими стеклянными эффектами

  • Aurora (градиенты) — яркие градиенты в стиле северного сияния

import { ThemeProvider, useTheme } from 'shadcn-glass-ui';

function ThemeSwitcher() {
  const { theme, cycleTheme } = useTheme();
  
  return (
    <button onClick={cycleTheme}>
      Текущая тема: {theme}
    </button>
  );
}

Compound Components API

Сложные компоненты используют паттерн Compound Components для максимальной гибкости:

<ModalGlass.Root open={isOpen} onOpenChange={setIsOpen}>
  <ModalGlass.Overlay />
  <ModalGlass.Content>
    <ModalGlass.Header>
      <ModalGlass.Title>Подтверждение действия</ModalGlass.Title>
      <ModalGlass.Description>
        Это действие нельзя будет отменить
      </ModalGlass.Description>
      <ModalGlass.Close />
    </ModalGlass.Header>
    
    <ModalGlass.Body>
      <p>Вы уверены, что хотите удалить этот элемент?</p>
    </ModalGlass.Body>
    
    <ModalGlass.Footer>
      <ButtonGlass variant="ghost" onClick={() => setIsOpen(false)}>
        Отмена
      </ButtonGlass>
      <ButtonGlass variant="destructive" onClick={handleDelete}>
        Удалить
      </ButtonGlass>
    </ModalGlass.Footer>
  </ModalGlass.Content>
</ModalGlass.Root>

Преимущества:

  • 🧩 Гибкая композиция — можно пропустить Footer или добавить Description

  • 📦 Tree-shaking — неиспользуемые части не попадают в бандл

  • 📖 Понятная структура — DOM-иерархия видна без документации

Полиморфные компоненты (asChild)

Все интерактивные компоненты поддерживают паттерн asChild из Radix UI:

import { ButtonGlass } from 'shadcn-glass-ui';
import { Link } from 'react-router-dom';

// Рендерим button как React Router Link
<ButtonGlass asChild variant="primary">
  <Link to="/dashboard">Перейти в панель</Link>
</ButtonGlass>

// Рендерим button как обычный <a>
<ButtonGlass asChild variant="ghost">
  <a href="https://github.com" target="_blank" rel="noopener">
    GitHub
  </a>
</ButtonGlass>

// Рендерим button как кастомный компонент
<ButtonGlass asChild>
  <motion.button
    whileHover={{ scale: 1.05 }}
    whileTap={{ scale: 0.95 }}
  >
    Анимированная кнопка
  </motion.button>
</ButtonGlass>

Доступность и тестирование

Все компоненты соответствуют WCAG 2.1 уровня AA:

  • Контраст — минимум 4.5:1 для текста

  • Клавиатура — полная навигация через Tab, Enter, Arrow keys

  • Touch target — минимум 44×44px (Apple Human Interface Guidelines)

  • Screen readers — правильные ARIA-атрибуты и семантический HTML

  • Focus indicators — 2px внутреннее + 4px внешнее кольцо

  • Reduced motion — автоотключение анимаций при prefers-reduced-motion

Тестовое покрытие: 1500+ автотестов

Категория

Кол-во

Инструменты

Pass rate

Design System Compliance

650+

Vitest + custom matchers

99.5%

Visual Regression

580

Playwright + screenshots

99.5%

Unit Tests

270+

Vitest

99.5%

Design System Compliance проверяет:

  • Все компоненты используют токены (не хардкод)

  • Touch targets минимум 44×44px

  • Цветовой контраст 4.5:1+

  • Правильная структура compound components

Visual Regression отлавливает:

  • Случайные изменения в отображении

  • Баги в темизации

  • Проблемы с responsive-дизайном

CLI-утилиты

shadcn-glass-ui поставляется с CLI для быстрой работы:

# Информация о компоненте (fuzzy search)
npx shadcn-glass-ui info button
npx shadcn-glass-ui info modal

# Список всех компонентов
npx shadcn-glass-ui list

# Фильтр по категории
npx shadcn-glass-ui list --category=core
npx shadcn-glass-ui list --category=composite

Ссылки и ресурсы

Заключение

shadcn-glass-ui решает четыре главные проблемы:

  1. "Как добавить glassmorphism без переписывания проекта?"
    → Drop-in совместимость с shadcn/ui, установка через CLI

  2. "Как быстро перейти от MVP к production-ready дизайну?"
    → Progressive enhancement: базовые компоненты → glassmorphism → брендинг

  3. "Как создавать темы без копипасты сотен значений?"
    → 3-слойная токен-система, новая тема за 15 строк

  4. "Как сделать библиотеку понятной для AI-ассистентов?"
    → Context7 MCP, rich JSDoc, decision trees

Типичный workflow:

Week 1-2: Прототип на shadcn/ui
    ↓
Week 3: Добавляем glassmorphism (npm install)
    ↓
Week 4: Кастомная тема под бренд (15 строк CSS)
    ↓
Production-ready за месяц 🚀

Буду рад фидбеку и контрибьюшенам! Вопросы — в комментариях или GitHub Issues.


P.S. Если статья была полезна — поставьте ⭐ на GitHub!