Sergey Horse
RUEN
Проекты

Готов · июль 2026 г.

Forge

Headless-библиотека компонентов для насыщенных данными дашбордов

  • design-system
  • react
  • typescript
30
Компоненты
628
Тесты
94%
Покрытие

Задача

shadcn даёт кнопки и диалоги. Он не даёт тяжёлых, насыщенных данными частей, которые дашборду нужны на самом деле: грид, остающийся плавным на десятках тысяч строк, конструктор фильтров, собирающий вложенную AND/OR-логику, асинхронный combobox, который по-настоящему доступен. Forge — этот недостающий слой, построенный headless-first, чтобы поведение переиспользовалось, а стилизация оставалась вашей.

DataGrid: липкий заголовок держится при вертикальном скролле, а замороженные колонки ID и Name остаются закреплёнными, пока остальное уезжает под них.

DataGrid

Грид — центр и самый сложный компонент. Он виртуализирует обе оси, держит в DOM ограниченное число ячеек независимо от размера набора данных и закрепляет замороженные колонки отдельным непрозрачным слоем, потому что sticky-позиционирование ломается внутри трансформа виртуализации. Три layout-бага подряд: перекрывающиеся замороженные ячейки, overscan-строки, вылезающие за нижнюю кромку, и контент скролла, просвечивающий сквозь прозрачный оверлей. Все три научили одному. Чистые инварианты вёрстки невидимы и для jsdom, и для код-ревью, и каждый пришлось ловить в реальном браузере, измеряя вычисленный paint.

Доступность была отдельным проектом: полный ARIA-паттерн грида, roving-фокус, переживающий уход ячейки за пределы виртуального окна, и видимое кольцо фокуса, зеркалимое на обрезанные замороженные ячейки.

Панель доступности Storybook: ноль нарушений
Панель доступности Storybook: ноль нарушений, девятнадцать проходов на наборе сторис.

Что вышло

Тридцать компонентов — от DataGrid и FilterBuilder до инпутов, оверлеев и карточек дашборда. Всего 628 тестов: 498 юнитов плюс 130, которые гоняют сторис в настоящем браузере, с нулём нарушений доступности на наборе сторис и покрытием около 94 процентов. DataGrid держит бюджет кадра при скролле десяти тысяч строк и сохраняет постоянное число ячеек на ста тысячах.

Библиотека не просто дописана, а опубликована. Пакет лежит на npm как @sergeyhorse/forge, только ESM, рядом — сайт документации с живыми примерами каждого компонента и Storybook. В тарбол уезжает собранный dist, README и лицензия: ни исходников, ни тестов, ни сторис.

FilterBuilder собирает вложенный запрос: корневой AND с дочерней группой, переключённой в OR.
KPI-карточки дашборда Forge
Примитивы дашборда: KPI-карточки с дельтами вверх, вниз и нейтральной.

Чему я научился

Контраст может пройти автоматический аудит и всё равно быть неверным. Поскольку палитра задана в oklch, аудит отдаёт контраст как incomplete, а не как провал, поэтому реальный провал на тёмной дельте проехал мимо всех автоматических прогонов. Поймать его удалось только вычислением отношения вручную, и теперь я сам проверяю значимые пары, а не полагаюсь на зелёную галочку.