Готов · июль 2026 г.
Forge
Headless-библиотека компонентов для насыщенных данными дашбордов

- 30
- Компоненты
- 628
- Тесты
- 94%
- Покрытие
Задача
shadcn даёт кнопки и диалоги. Он не даёт тяжёлых, насыщенных данными частей, которые дашборду нужны на самом деле: грид, остающийся плавным на десятках тысяч строк, конструктор фильтров, собирающий вложенную AND/OR-логику, асинхронный combobox, который по-настоящему доступен. Forge — этот недостающий слой, построенный headless-first, чтобы поведение переиспользовалось, а стилизация оставалась вашей.
DataGrid
Грид — центр и самый сложный компонент. Он виртуализирует обе оси, держит в DOM ограниченное число ячеек независимо от размера набора данных и закрепляет замороженные колонки отдельным непрозрачным слоем, потому что sticky-позиционирование ломается внутри трансформа виртуализации. Три layout-бага подряд: перекрывающиеся замороженные ячейки, overscan-строки, вылезающие за нижнюю кромку, и контент скролла, просвечивающий сквозь прозрачный оверлей. Все три научили одному. Чистые инварианты вёрстки невидимы и для jsdom, и для код-ревью, и каждый пришлось ловить в реальном браузере, измеряя вычисленный paint.
Доступность была отдельным проектом: полный ARIA-паттерн грида, roving-фокус, переживающий уход ячейки за пределы виртуального окна, и видимое кольцо фокуса, зеркалимое на обрезанные замороженные ячейки.

Что вышло
Тридцать компонентов — от DataGrid и FilterBuilder до инпутов, оверлеев и карточек дашборда. Всего 628 тестов: 498 юнитов плюс 130, которые гоняют сторис в настоящем браузере, с нулём нарушений доступности на наборе сторис и покрытием около 94 процентов. DataGrid держит бюджет кадра при скролле десяти тысяч строк и сохраняет постоянное число ячеек на ста тысячах.
Библиотека не просто дописана, а опубликована. Пакет лежит на npm как @sergeyhorse/forge, только ESM, рядом — сайт документации с живыми примерами каждого компонента и Storybook. В тарбол уезжает собранный dist, README и лицензия: ни исходников, ни тестов, ни сторис.

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