Custom Elements Collection: 147 компонентов двумя строками через CDN

от автора

Custom Elements Collection — библиотека компонентов, которая подключается двумя строками в <head>: один <link> с темой и один <script type="module"> с регистрацией тегов. Без npm, без bundler, без node_modules. После двух строк в разметке становятся доступны hero-блоки, KPI, callout-уведомления, чат-виджеты, графики, формы.

В туториале — минимальный пример: hero-страница с инлайн-метриками и callout-уведомлением. На выходе — HTML-файл, который открывается двойным кликом.

Что внутри

Цифры из package.json и README:

  • 147 web-components, разбитых на 9 групп.

  • Lit 3 как runtime, бандлится в пакет.

  • Light DOM по умолчанию — теги встают в обычный поток DOM, видны в DevTools как обычные элементы, дочерние ноды доступны через children.

  • 10 готовых тем через CSS Custom Properties: light, dark, bauhaus, gruvbox, memphis, muji, neo-brutal, nordic, solarized, swiss. Переключение атрибутом data-ce-theme="..." на <html>.

Группы компонентов (полный каталог — на демо-странице, ссылка в конце):

  • Layout & primitives (38)ce-hero, ce-section, ce-grid, ce-stack, ce-callout, ce-card, ce-tabs, ce-modal, ce-drawer, ce-table.

  • Metrics & charts (11)ce-kpi, ce-sparkline, ce-bar-chart, ce-donut, ce-heatmap, ce-gauge.

  • Comparison & narrative (19)ce-feature-card, ce-pros-cons, ce-matrix, ce-decision-tree, ce-timeline, ce-pricing-tier.

  • Chat surfaces (18)ce-chat-input, ce-chat-bubble, ce-message-group, ce-reasoning, ce-tool-call, ce-source-card, ce-citation — примитивы для LLM-UI.

  • Feedback (11)ce-feedback-bar, ce-rating, ce-comment, ce-tooltip.

  • Forms (16)ce-button, ce-input, ce-textarea, ce-select, ce-checkbox, ce-radio-group.

  • Dashboard (6)ce-clock, ce-counter, ce-gauge, ce-sparkline, ce-status-light.

  • Content (10)ce-image, ce-list, ce-tree, ce-json, ce-diff, ce-qr.

  • Education lesson-* (18)lesson-quiz, lesson-vocab, lesson-match, lesson-reveal для интерактивных уроков.

Web-components — W3C-стандарт, поддерживается во всех evergreen-браузерах (Chrome, Edge, Firefox, Safari 16.4+). Один и тот же <ce-hero> работает в React, Vue 3, Angular 17+, Svelte 5, Astro и в любом SSG; для некоторых фреймворков нужна минимальная настройка (isCustomElement для Vue, CUSTOM_ELEMENTS_SCHEMA для Angular).

Шаг 1. Пустой HTML

index.html в любой папке, без сервера и node:

<!doctype html><html lang="ru"><head>  <meta charset="utf-8">  <title>Custom Elements Collection - первый запуск</title></head><body></body></html>

Двойной клик открывает пустую страницу.

Шаг 2. Две строки CDN

Добавляем в <head> таблицу токенов темы и сам пакет с тегами:

<link rel="stylesheet"      href="https://unpkg.com/custom-elements-collection/dist/tokens/light.css"><script type="module"        src="https://unpkg.com/custom-elements-collection/dist/auto.js"></script>
  • light.css — convenience-таблица светлой темы. Внутри — @import базового tokens.css (--ce-color-*, --ce-space-*, --ce-radius-*, --ce-text-*), переопределение :root под светлую палитру и color-scheme: light. Аналогично есть dark.css (см. Шаг 5) и tokens.css напрямую — с ручным переключением через data-ce-theme="…".

  • auto.js — entry-point с автоматической регистрацией всех 147 тегов в customElements.registry.

unpkg.com раздаёт содержимое npm-пакетов как статику. Версия фиксируется через @unpkg.com/custom-elements-collection@0.7.0/dist/auto.js; без указания версии тянется latest. Для прода версию имеет смысл закрепить.

Шаг 3. Первый

Добавляем в <body>:

<ce-callout type="success" title="Всё работает">  Custom Elements Collection подключена через CDN, сборка не требуется.</ce-callout>

Сохраняем, обновляем браузер — на странице зелёная панель с заголовком, акцент-полосой слева и телом. Это «admonition»-блок.

Атрибуты ce-callout по meta.json:

  • type — тон: info (по умолчанию), success, warn, danger, neutral.

  • title — необязательный заголовок жирным.

  • Тело — обычный children-контент в unnamed-slot. Внутрь можно класть ссылки, абзацы, списки.

Шаг 4. Композиция: +

Заменяем содержимое <body> на hero-блок со встроенными KPI:

<ce-hero  kicker="Туториал"  title="Custom Elements Collection - за 10 минут"  lede="147 готовых web-components, две строки CDN, ноль сборки.">  <ce-kpi slot="stats" value="147" label="Компоненты"  color="green"></ce-kpi>  <ce-kpi slot="stats" value="10"  label="Тем"         color="blue"></ce-kpi>  <ce-kpi slot="stats" value="0"   label="Шагов npm"   color="purple"></ce-kpi></ce-hero><ce-callout type="success" title="Всё работает">  Custom Elements Collection подключена через CDN, сборка не требуется.</ce-callout>
  • <ce-hero> принимает строковые атрибуты kicker (надстрочный лейбл), title и lede (подзаголовок). Это страничный header-блок с радиальным градиентом; атрибут flat градиент отключает.

  • <ce-kpi> — leaf-компонент. Атрибуты: value (крупное значение), label (мелкий лейбл), color (neutral | green | red | amber | blue | purple | cyan), trend (строка вида +12% или -3ms с автоматической расцветкой по знаку).

  • slot="stats" — именованный slot: hero показывает KPI-блоки в отдельной строке внизу header’а. Список слотов — публичная часть API, описанная в hero.meta.json.

Шаг 5. Тёмная тема — смена одной ссылки

Custom Elements Collection включает 10 готовых тем. Переключаемся подменой <link>light.css на dark.css:

<link rel="stylesheet"      href="https://unpkg.com/custom-elements-collection/dist/tokens/dark.css">

Обновляем браузер — фон, текст, границы и все цветовые токены --ce-color-* переключаются на тёмную палитру; color-scheme: dark перекрашивает канвас. Аналогично работают solarized.css, nordic.css, gruvbox.css, bauhaus.css, memphis.css, muji.css, neo-brutal.css, swiss.css.

Runtime-переключение темы и prefers-color-scheme

Если тему нужно менять во время работы страницы — подключаем tokens.css напрямую (внутри палитры всех 10 тем) и переключаемся атрибутом data-ce-theme="dark" на <html>. В этом туториале статический выбор через <link> короче.

Для системной темы через prefers-color-scheme хватает небольшого скрипта на matchMedia('(prefers-color-scheme: dark)') — отдельная тема следующих туториалов.

Финальный файл

<!doctype html><html lang="ru"><head>  <meta charset="utf-8">  <title>Custom Elements Collection — первый запуск</title>  <link rel="stylesheet"        href="https://unpkg.com/custom-elements-collection/dist/tokens/dark.css">  <script type="module"          src="https://unpkg.com/custom-elements-collection/dist/auto.js"></script></head><body>  <ce-hero    kicker="Туториал"    title="Custom Elements Collection — за 10 минут"    lede="147 готовых web-components, две строки CDN, ноль сборки.">    <ce-kpi slot="stats" value="147" label="Компоненты" color="green"></ce-kpi>    <ce-kpi slot="stats" value="10"  label="Тем"        color="blue"></ce-kpi>    <ce-kpi slot="stats" value="0"   label="Шагов npm"  color="purple"></ce-kpi>  </ce-hero>  <ce-callout type="success" title="Всё работает">    Custom Elements Collection подключена через CDN, сборка не требуется.  </ce-callout></body></html>

Открывается двойным кликом — модули подтягиваются с CDN по file://, страница рендерится.

Light DOM vs Shadow DOM — без оценки

Компоненты по умолчанию рендерятся в light DOM: разметка видна в обычном DOM, доступна через document.querySelector и innerHTML, дочерние элементы лежат в children. Решение зафиксировано в ADR-002 проекта — оно упрощает интеграцию с server-side markdown, со скриптами, ищущими элементы по селекторам, и инспектирование в DevTools.

У Shadow DOM другая модель — изоляция стилей и encapsulated DOM. Сильная сторона — shadow-tree не «течёт» в host-страницу, что критично для embeddable виджетов на чужих сайтах. У light DOM сильнее интеграционная модель, но стили host-страницы могут затечь в компоненты, если небрежно работать с селекторами. В Custom Elements Collection Shadow DOM опт-ин — отдельные компоненты используют его, когда нужны :host()-селекторы; снаружи API одинаков: атрибуты, slots и CSS Custom Properties.

Когда CDN подходит — а когда лучше npm

CDN через unpkg.com подходит когда:

  • прототип, лендинг или одностраничник — пайплайн сборки лишний;

  • документация и блог-пост — markdown + один <script> в head шаблона;

  • демо к OSS-библиотеке — посетитель открывает страницу, всё работает;

  • встроенный виджет на чужом сайте — особенно если у сайта нет bundler’а;

  • онбординг разработчиков — первый рабочий пример без node_modules.

CDN начинает мешать когда:

  • проект уже на bundler (Vite, webpack, esbuild) — естественнее pnpm add custom-elements-collection и tree-shakable import "custom-elements-collection/hero", чтобы платить байтами только за используемые теги;

  • нужна детерминированная версия и offline-сборкаunpkg.com тянется по сети;

  • CSP-политика запрещает внешние script-источники — CDN исключён архитектурно;

  • используется SSR<script type="module"> исполняется только в браузере; для SSR (Astro, Nuxt, Next.js) нужен npm-режим с правильной hydration-стратегией.

Как попробовать в своём проекте

ссылка на оригинал статьи https://habr.com/ru/articles/1042520/