GNexus UI Kit

Набор базовых элементов интерфейса.

Typography

Базовая типографика задаёт размеры заголовков, текстовые состояния и моноширинный код. Используй семантические теги, а служебные классы добавляй для вариаций текста.

Heading H1

Heading H2

Heading H3

Heading H4

Heading H5
Heading H6
System label

Lead text выделяет вводный абзац, описание страницы или важный контекст перед набором действий.

Основной текст интерфейса. Используется для контента.

Вторичный текст, комментарии, подписи.

Приглушённый текст, подсказки.

Caption text для технических подписей, footnote и compact metadata.

Состояния текста: success, warning, danger, info.

Inline code npm run build и keyboard hint esc.

Интерфейс должен оставаться читаемым даже в плотных технических сценариях. GNexus UI Kit
Typography HTML
<h1 class="contrast">Dashboard</h1>
<span class="eyebrow">System label</span>
<p class="text-lead">Вводный текст страницы.</p>
<p class="text-primary">Основной текст интерфейса.</p>
<p class="text-muted">Приглушённая подсказка.</p>
<code class="code">npm run build</code>
<span class="kbd">esc</span>

Color Palette

Палитра построена вокруг тёмной базы, светлого primary-текста и ярких статусных цветов. Классы `bg-*` нужны для быстрых цветовых маркеров и демонстрации токенов.

Primary
Secondary
Accent
Info
Success
Warning
Error
Palette HTML
<div class="color-box bg-primary"></div>
<div class="color-box bg-secondary"></div>
<div class="color-box bg-success"></div>
<div class="color-box bg-warning"></div>
<div class="color-box bg-error"></div>

Buttons

Кнопки собираются из базового класса `.btn`, цветового модификатора и опционального размера. Для иконок добавляй `.with-icon`, а состояние загрузки помечай `.loading-state`.

Buttons HTML
<button class="btn btn-primary">Primary</button>
<button class="btn btn-secondary with-icon">
  <i class="ph ph-code"></i>
  Secondary
</button>
<button class="btn btn-warning btn-small">Small</button>
<button class="btn btn-success with-icon loading-state" disabled>
  <i class="ph-bold ph-spinner"></i>
  Loading
</button>

Forms

Формы используют `.form-group`, `.label` и `.input`. Ошибки задаются на label через `.error`, а пояснение выводится соседним `.input-info`.

Field cannot be empty
Looks good
Check before publishing
Date & Time
Fieldset

Upload files

Attach documents, archives, screenshots or product images for review.

Max 12 MB
Field cannot be empty
Forms HTML
<div class="form-group">
  <label class="label error">
    Project name
    <i class="ph ph-user"></i>
    <input class="input" type="text" placeholder="Launch Plan">
  </label>
  <div class="input-info">
    <i class="ph ph-warning-circle"></i>
    Field cannot be empty
  </div>
</div>

<fieldset class="fieldset">
  <legend class="legend">Fieldset</legend>
  <label class="label success">
    Validated
    <input class="input" type="text" value="Release Plan">
  </label>
</fieldset>

<label class="file-upload">
  Upload file
  <input type="file">
</label>

<fieldset class="fieldset">
  <legend class="legend">Date & Time</legend>
  <div class="form-grid">
    <label class="label">
      Date
      <i class="ph ph-calendar-blank"></i>
      <input class="input input-date" type="date" value="2026-04-23" data-date-picker>
    </label>
    <label class="label">
      Time
      <i class="ph ph-clock"></i>
      <input class="input input-time" type="time" value="14:30" data-date-picker>
    </label>
    <label class="label">
      Date & time
      <i class="ph ph-calendar-dots"></i>
      <input class="input input-datetime" type="datetime-local" value="2026-04-23T14:30" data-date-picker>
    </label>
  </div>
</fieldset>

<div class="file-upload-panel">
  <form class="file-upload-form" enctype="multipart/form-data">
    <div class="file-upload-header">
      <div class="file-upload-heading">
        <h3 class="file-upload-title">Upload files</h3>
        <p class="file-upload-description">Attach documents, archives or images.</p>
      </div>
      <span class="badge badge-info">Max 12 MB</span>
    </div>

    <label class="file-upload-dropzone">
      <span class="file-upload-icon" aria-hidden="true">
        <i class="ph ph-cloud-arrow-up"></i>
      </span>
      <span class="file-upload-body">
        <span class="file-upload-primary">Choose files</span>
        <span class="file-upload-secondary">Images get thumbnails, other files show their type</span>
      </span>
      <input type="file" name="files" multiple data-file-upload-input>
    </label>

    <div class="file-upload-preview" data-file-upload-preview hidden></div>

    <div class="file-upload-actions">
      <button class="btn btn-secondary btn-small" type="reset">Reset</button>
      <button class="btn btn-accent btn-small" type="submit">Upload</button>
    </div>
  </form>
</div>

Utilities

Utilities дают предсказуемую систему отступов, размеров, раскладки и текстовых правок без создания новых компонентов. Spacing scale используется и в SCSS-переменных, и в utility-классах.

Spacing scale

Spacing tokens
Token Value Alias Utility examples
$space-0 0 - m-0 p-0 g-0
$space-1 5px $space-xs mt-1 px-1
$space-2 8px $space-sm mb-2 g-2
$space-3 12px - p-3 gy-3
$space-4 15px $space-md mx-4 gx-4
$space-5 18px - pt-5 pb-5
$space-6 22px $space-lg my-6 g-6
$space-8 34px $space-xl mt-8 p-8
$space-10 48px $space-xxl mb-10 py-10
$space-12 80px - mt-12 pb-12

Utility groups

Margin
m-* mt-* mr-* mb-* ml-* mx-* my-*
Padding
p-* pt-* pr-* pb-* pl-* px-* py-*
Gap
g-* gx-* gy-*
Layout
row column f-grid grid grid-2 grid-3
Alignment
items-center justify-between justify-end
Text
fs-sm text-center text-uppercase text-nowrap

Spacing preview

g-4
p-5
px-6 py-3
Utilities HTML
<div class="grid-2 g-4 items-center">
  <div class="p-5">Panel</div>
  <div class="px-6 py-3 text-right">Actions</div>
</div>

Editable String

Editable String превращает обычный контейнер с текстом в inline-редактор. Компонент возвращает DOM-элемент с API `editableString`.

Hello world
Editable String HTML
<div class="editable-example">Hello world</div>
Editable String JS
const editor = editableString(document.querySelector(".editable-example"));

editor.editableString.onChange(component => {
  console.log(component.value);
});

Lists

Списки покрывают обычные перечни, навигацию, definition list и строки с действиями. Для интерактивных пунктов используй `.list-nav`, `.list-action`, `.list-label` и `.list-meta`.

Unordered list

  • Dashboard
  • Projects
  • Reports
  • Automations
  • Settings

Ordered list

  1. Create workspace
  2. Invite team
  3. Configure permissions
  4. Verify status

List with icons

  • Bathroom
  • Toilet
  • Workspace

Definition list

Item
Базовая сущность интерфейса
Group
Логическая группа элементов
Flow
Набор действий, выполняемых последовательно

Navigation / interactive list

List with actions

  • Release Plan
    192.168.2.21
  • Analytics Sync
    192.168.2.34
  • Archive Job
    Offline
Navigation List HTML
<ul class="list list-nav">
  <li class="list-item list-item-active">
    <button class="list-action" type="button">
      <span class="list-label">
        <i class="ph ph-lightbulb"></i>
        Projects
      </span>
      <span class="list-meta">12</span>
    </button>
  </li>
</ul>

Badges & Status

Badges используются для коротких статусов, счётчиков и меток состояния. Цветовой модификатор выбирается по смыслу: success, warning, error, info и так далее.

Primary Secondary Success Warning Error Info
Badges HTML
<span class="badge badge-success">Online</span>
<span class="badge badge-warning">Degraded</span>
<span class="badge badge-error">Offline</span>
<span class="badge badge-info">Info</span>

Alerts

Alerts подходят для заметных системных сообщений внутри контента. Используй `.alert` и один цветовой модификатор.

This is a primary alert—check it out!
This is a success alert—check it out!
This is a secondary alert—check it out!
This is a info alert—check it out!
This is a warning alert—check it out!
This is a error/danger alert—check it out!
Alerts HTML
<div class="alert alert-primary">Primary message</div>
<div class="alert alert-success">Operation completed</div>
<div class="alert alert-warning">Check settings</div>
<div class="alert alert-error">Action failed</div>

Tables

Таблицы используют базовый класс `.table`, semantic table markup и дополнительные элементы: `.table-caption`, `.table-head`, `.table-body`, `.table-foot`.

Basic table

Projects list
Project Status Owner Updated Actions
Website Redesign Online @design 2 min ago
Billing API Degraded @backend 1 hour ago
Archive Import Offline @ops Yesterday
Total: 3 projects

Compact table

Recent jobs
Job State Runtime Run ID Actions
Sync catalog Done 18s run_1048
Import archive Running 2m 14s run_1047
Export report Failed 4s run_1046
Tables HTML
<table class="table">
  <caption class="table-caption">Projects list</caption>
  <thead class="table-head">
    <tr class="table-row">
      <th scope="col">Project</th>
      <th scope="col">Status</th>
    </tr>
  </thead>
  <tbody class="table-body">
    <tr class="table-row">
      <td>Website Redesign</td>
      <td><span class="badge badge-success">Online</span></td>
    </tr>
  </tbody>
</table>
Compact Table HTML
<table class="table table-compact">
  <caption class="table-caption">Recent jobs</caption>
  <thead class="table-head">
    <tr class="table-row">
      <th scope="col">Job</th>
      <th scope="col">State</th>
      <th scope="col">Run ID</th>
    </tr>
  </thead>
  <tbody class="table-body">
    <tr class="table-row">
      <td>Sync catalog</td>
      <td><span class="badge badge-success">Done</span></td>
      <td class="table-cell-mono">run_1048</td>
    </tr>
  </tbody>
</table>

Data Patterns

Toolbar, search field, pagination, empty state и skeleton закрывают типовые состояния таблиц, списков и страниц с данными.

Projects

24 items
https://

No results

Nothing matched the current filters. Reset the query or create a new item.

Toolbar HTML
<div class="toolbar">
  <div class="toolbar-group">
    <div>
      <h3 class="toolbar-title">Projects</h3>
      <span class="toolbar-meta">24 items</span>
    </div>
  </div>
  <div class="toolbar-group">
    <div class="input-group input-group-compact search-field">
      <span class="input-group-addon"><i class="ph ph-magnifying-glass"></i></span>
      <input class="input-group-input" type="search" placeholder="Search">
      <button class="input-group-action" type="button" data-input-clear aria-label="Clear search">
        <i class="ph ph-x"></i>
      </button>
    </div>
    <button class="btn btn-accent btn-small">Create</button>
  </div>
</div>
Input Group HTML
<div class="input-group">
  <span class="input-group-addon">https://</span>
  <input class="input-group-input" type="text" placeholder="Domain">
  <button class="input-group-action" type="button">Save</button>
</div>
Pagination HTML
<nav class="pagination" aria-label="Pagination">
  <button class="pagination-item" type="button" disabled>Prev</button>
  <button class="pagination-item pagination-item-active" type="button" aria-current="page">1</button>
  <button class="pagination-item" type="button">2</button>
  <span class="pagination-ellipsis">...</span>
  <button class="pagination-item" type="button">12</button>
  <button class="pagination-item" type="button">Next</button>
</nav>
Empty State HTML
<div class="empty-state">
  <div class="empty-state-icon"><i class="ph ph-package"></i></div>
  <h3 class="empty-state-title">No results</h3>
  <p class="empty-state-text">Nothing matched the current filters.</p>
  <div class="empty-state-actions">
    <button class="btn btn-secondary btn-small">Reset</button>
    <button class="btn btn-accent btn-small">Create</button>
  </div>
</div>
Skeleton HTML
<div class="skeleton-stack" aria-label="Loading preview">
  <span class="skeleton skeleton-title"></span>
  <span class="skeleton skeleton-line"></span>
  <span class="skeleton skeleton-line" style="width: 84%"></span>
  <span class="skeleton skeleton-block"></span>
</div>
Input Patterns JS
InputPatterns.init();

// Available on the global namespace too:
GNexusUIKit.InputPatterns.init();

Key-Value

Description List подходит для read-only деталей сущности: ID, владельцы, статусы, даты и короткие metadata values.

Project
Website Redesign
Status
Online All checks passed
Owner
@design
Updated
2026-04-11 22:12
Run ID
run_1048
Runtime
18s
Result
Queued
Description List HTML
<dl class="description-list">
  <div class="description-list-row">
    <dt class="description-list-term">Project</dt>
    <dd class="description-list-value">Website Redesign</dd>
  </div>
  <div class="description-list-row">
    <dt class="description-list-term">Status</dt>
    <dd class="description-list-value">
      <span class="badge badge-success">Online</span>
      <span class="description-list-value-muted">All checks passed</span>
    </dd>
  </div>
</dl>
Compact List HTML
<dl class="description-list description-list-compact">
  <div class="description-list-row">
    <dt class="description-list-term">Run ID</dt>
    <dd class="description-list-value"><code class="code">run_1048</code></dd>
  </div>
  <div class="description-list-row">
    <dt class="description-list-term">Runtime</dt>
    <dd class="description-list-value">18s</dd>
  </div>
</dl>

Progress

Progress закрывает загрузку, usage meters и staged progress для операций с понятным состоянием выполнения.

Bars

Build 64%
Sync 42%

Storage 78%

312 GB used from 400 GB limit.

Queued Build Deploy Verify
Loading state
Progress Bar HTML
<div class="progress" role="progressbar" aria-label="Build progress" aria-valuemin="0" aria-valuemax="100" aria-valuenow="64" style="--progress-value: 64%">
  <div class="progress-header">
    <span>Build</span>
    <span class="progress-value">64%</span>
  </div>
  <div class="progress-track">
    <span class="progress-bar"></span>
  </div>
</div>
Usage Meter HTML
<div class="usage-meter">
  <h3 class="usage-meter-title">
    Storage
    <span class="usage-meter-value">78%</span>
  </h3>
  <div class="progress progress-success" role="progressbar" aria-valuemin="0" aria-valuemax="100" aria-valuenow="78" style="--progress-value: 78%">
    <div class="progress-track">
      <span class="progress-bar"></span>
    </div>
  </div>
  <p class="usage-meter-meta">312 GB used from 400 GB limit.</p>
</div>
Staged Progress HTML
<div class="progress-stages" aria-label="Deploy stages">
  <span class="progress-stage progress-stage-complete">Queued</span>
  <span class="progress-stage progress-stage-complete">Build</span>
  <span class="progress-stage progress-stage-current">Deploy</span>
  <span class="progress-stage">Verify</span>
</div>

Steps

Steps описывает wizard-flow, onboarding и последовательные процессы с текущим, завершенным и недоступным шагом.

  1. Account

    Basic profile data is ready.

  2. Plan

    Billing plan is selected.

  3. 3

    Confirm

    Review settings before launch.

  4. 4

    Launch

    Available after confirmation.

  1. Queued

    Job accepted and waiting for worker slot.

  2. 2

    Running

    Current task is processing input data.

  3. 3

    Report

    Final summary appears after completion.

Steps HTML
<ol class="steps">
  <li class="step step-complete">
    <span class="step-marker"><i class="ph ph-check"></i></span>
    <h3 class="step-title">Account</h3>
    <p class="step-text">Basic profile data is ready.</p>
  </li>
  <li class="step step-current" aria-current="step">
    <span class="step-marker">2</span>
    <h3 class="step-title">Confirm</h3>
    <p class="step-text">Review settings before launch.</p>
  </li>
  <li class="step step-disabled">
    <span class="step-marker">3</span>
    <h3 class="step-title">Launch</h3>
    <p class="step-text">Available after confirmation.</p>
  </li>
</ol>
Vertical Steps HTML
<ol class="steps steps-vertical">
  <li class="step step-complete">
    <span class="step-marker"><i class="ph ph-check"></i></span>
    <h3 class="step-title">Queued</h3>
    <p class="step-text">Job accepted and waiting for worker slot.</p>
  </li>
  <li class="step step-current" aria-current="step">
    <span class="step-marker">2</span>
    <h3 class="step-title">Running</h3>
    <p class="step-text">Current task is processing input data.</p>
  </li>
</ol>

Chips

Chips используются для фильтров, коротких labels, selectable states и removable tokens.

Static chips

Primary Secondary Success Warning Error Filtered

Selectable chips

Removable chips

Frontend Design Review
Static Chips HTML
<div class="chip-group">
  <span class="chip chip-primary">Primary</span>
  <span class="chip chip-secondary">Secondary</span>
  <span class="chip chip-success">Success</span>
  <span class="chip">
    <i class="ph ph-funnel"></i>
    Filtered
  </span>
</div>
Selectable Chips HTML
<div class="chip-group" aria-label="Filter chips">
  <button class="chip chip-selected" type="button" aria-pressed="true">Active</button>
  <button class="chip" type="button" aria-pressed="false">Queued</button>
  <button class="chip" type="button" aria-pressed="false">Failed</button>
</div>
Removable Chips HTML
<span class="chip">
  Frontend
  <button class="chip-remove" type="button" aria-label="Remove Frontend">
    <i class="ph ph-x"></i>
  </button>
</span>

Avatar

Avatar и Identity показывают пользователя, команду, сервис или объект с initials, icon, image и status marker.

Avatar variants

AV GN UI GNexus mark

Identity row

AK Alex Kim Product Designer

Avatar stack

AK JS MR +4
Avatar HTML
<span class="avatar avatar-secondary is-online">
  AK
  <span class="avatar-status"></span>
</span>

<span class="avatar avatar-outline">
  <i class="ph ph-user"></i>
</span>

<span class="avatar">
  <img src="/assets/imgs/gnexus-mark.svg" alt="GNexus mark">
</span>
Identity HTML
<div class="identity">
  <span class="avatar avatar-secondary is-online">
    AK
    <span class="avatar-status"></span>
  </span>
  <span class="identity-content">
    <span class="identity-title">Alex Kim</span>
    <span class="identity-meta">Product Designer</span>
  </span>
</div>
Avatar Stack HTML
<div class="avatar-stack" aria-label="Assigned users">
  <span class="avatar avatar-sm">AK</span>
  <span class="avatar avatar-sm avatar-secondary">JS</span>
  <span class="avatar avatar-sm avatar-warning">MR</span>
  <span class="avatar-stack-count">+4</span>
</div>

Timeline

Timeline и Activity Log показывают историю событий, audit trail, job updates и системные изменения.

  1. Build completed

    Production bundle finished without warnings.

    Done CI
  2. Review requested

    Design tokens changed and need one visual pass before release.

    Review
  3. Commit pushed

    Component documentation and demo examples were updated.

Build completed Done
Review requested Pending
Commit pushed Info
Timeline HTML
<ol class="timeline">
  <li class="timeline-item timeline-item-success">
    <span class="timeline-marker"><i class="ph ph-check-circle"></i></span>
    <div class="timeline-content">
      <article class="timeline-card">
        <div class="timeline-header">
          <h3 class="timeline-title">Build completed</h3>
          <time class="timeline-time" datetime="2026-04-11T22:24:00">22:24</time>
        </div>
        <p class="timeline-text">Production bundle finished without warnings.</p>
      </article>
    </div>
  </li>
</ol>
Activity Log HTML
<div class="activity-log">
  <div class="activity-log-row">
    <time class="activity-log-time" datetime="2026-04-11T22:24:00">22:24</time>
    <span class="activity-log-title">Build completed</span>
    <span class="badge badge-success">Done</span>
  </div>
</div>

Accordion

Accordion и Disclosure используют native <details> / <summary>, а раскрытие анимируется через Accordion.init().

Release checklist

Check component states, copy examples, keyboard focus, and responsive layout before release.

Documentation notes

Keep component copy short and include code examples for the smallest useful markup.

Runtime behavior

Use native disclosure behavior when the component does not need custom animation or async content.

Compact disclosure

Use this variant for a single expandable group inside forms or metadata blocks.

Accordion HTML
<div class="accordion">
  <details class="accordion-item" open>
    <summary class="accordion-summary">
      <span class="accordion-summary-content">
        <i class="ph ph-list-checks"></i>
        Release checklist
      </span>
      <i class="ph ph-caret-down accordion-icon"></i>
    </summary>
    <div class="accordion-panel">
      <p>Check component states, copy examples, keyboard focus, and responsive layout.</p>
    </div>
  </details>
</div>
Disclosure HTML
<details class="disclosure">
  <summary class="accordion-summary">
    <span class="accordion-summary-content">Compact disclosure</span>
    <i class="ph ph-caret-down accordion-icon"></i>
  </summary>
  <div class="accordion-panel">
    <p>Use this variant for a single expandable group.</p>
  </div>
</details>

Tabs

Tabs переключают связанные панели внутри одного контекста. Компонент поддерживает click, keyboard navigation и ARIA state через Tabs.init().

Overview keeps the primary status, totals, and next actions visible without leaving the current screen.

Activity contains the latest events, audit notes, and handoff messages for the same record.

Settings groups secondary options that affect this context but do not need full page navigation.

Use compact tabs in dense panels, settings pages, and narrow metadata blocks.

Disabled tabs can stay visible when a feature is unavailable for the current object.

Billing content is disabled in this example.

Vertical tabs work well when labels are longer or the panel needs a stable left rail.

Use them for account details, admin records, or focused configuration groups.

On smaller screens the tab rail becomes a horizontal scrollable list.

Tabs HTML
<div class="tabs" data-tabs>
  <div class="tabs-list" aria-label="Project sections">
    <button class="tab tab-active" type="button" aria-controls="panel-overview">Overview</button>
    <button class="tab" type="button" aria-controls="panel-activity">Activity</button>
  </div>
  <div class="tabs-panels">
    <div class="tab-panel tab-panel-active" id="panel-overview">Overview content</div>
    <div class="tab-panel" id="panel-activity">Activity content</div>
  </div>
</div>

Drawer

Drawer подходит для контекстных деталей, quick edit и длинных вторичных сценариев без ухода со страницы. По API он близок к Modal, но панель закреплена у края экрана.

Examples

Используй Drawer, когда нужно сохранить контекст основного экрана и раскрыть боковую область с формой, метаданными или журналом.

Drawer JS
Drawer.create("details-drawer", {
  title: "Details",
  bodyHtml: `
    <p class="text">Context content, forms, logs, metadata.</p>
  `,
  actions: drawer => {
    const close = document.createElement("button");
    close.className = "btn btn-primary";
    close.textContent = "Close";
    close.addEventListener("click", () => drawer.close());
    return [close];
  }
}).show();
Left Position
Drawer.create("navigation-drawer", {
  title: "Navigation",
  position: "left",
  bodyText: "Left drawer content"
}).show();

Toasts

Toasts создаются из JS и добавляются в `body` вызовом `.show()`. Для коротких уведомлений доступны методы `createInfo`, `createSuccess`, `createWarning`, `createDanger`.

Triggers (demo buttons)

Toasts JS
Toasts.createSuccess(
  "Success",
  "Операция выполнена успешно",
  { lifetime: 4000, alone: true }
).show();

Toasts.createDanger("Error", "Произошла ошибка").show();

Cards

Card подходит для компактных виджетов и контентных блоков. Цветовые состояния карточек задаются модификаторами `card-success`, `card-warning`, `card-error`, `card-info`.

Card title

Карточка для контента, виджетов, статусов.

Status title
OK

Primary status card with a short description.

Default

Neutral card for a module, widget, or section.

Pending

Warning state for items that need attention.

Failed

Error state for failed actions or blocked flows.

Info

Informational card for contextual metadata.

Queued

Secondary state for queued or background work.

Monthly usage

84.2%

+12.8% vs previous period
Quick action

Create workflow

Use action cards for primary next steps, onboarding prompts, and compact empty state actions.

Cards HTML
<div class="card status-card card-success">
  <span class="card-title">Status title</span>
  <div class="card-content">
    <div class="status-icon-container">
      <div class="status-icon">
        <i class="ph ph-check-circle"></i>
        OK
      </div>
    </div>
    <p class="status-name">Primary status card.</p>
  </div>
</div>
Metric Card HTML
<div class="card metric-card">
  <div class="card-content">
    <div class="metric-card-header">
      <p class="metric-card-label">Monthly usage</p>
      <span class="metric-card-icon"><i class="ph ph-chart-line-up"></i></span>
    </div>
    <p class="metric-card-value">84.2%</p>
    <div class="metric-card-meta">
      <span class="metric-card-delta">+12.8%</span>
      <span>vs previous period</span>
    </div>
  </div>
</div>
Action Card HTML
<div class="card action-card">
  <div class="card-content">
    <span class="action-card-kicker">Quick action</span>
    <h3 class="action-card-title">Create workflow</h3>
    <p class="action-card-text">
      Use action cards for primary next steps and compact empty state actions.
    </p>
    <div class="action-card-actions">
      <button class="btn btn-secondary btn-small">Preview</button>
      <button class="btn btn-accent btn-small">Create</button>
    </div>
  </div>
</div>

Modals

Modal создаётся из JS через `Modals.create`. Для обычного текста используй `bodyText`; HTML-контент передавай явно через `bodyHtml` или DOM-элемент.

Open triggers

Modals JS
Modals.create("demo-modal", {
  title: "Demo modal",
  bodyText: "Modal content",
  actions: modal => {
    const close = document.createElement("button");
    close.className = "btn btn-primary";
    close.textContent = "Close";
    close.addEventListener("click", () => modal.close());
    return [close];
  }
}).show();

Confirm Dialog

Confirm Dialog использует существующий `confirmPopup` поверх Modal. Он нужен для коротких подтверждений перед опасными или необратимыми действиями.

Trigger

Confirm JS
confirmPopup(
  "This action cannot be undone.",
  () => Toasts.createSuccess("Confirmed", "Action accepted").show(),
  () => Toasts.createInfo("Canceled", "Action skipped").show()
);
Global Namespace
GNexusUIKit.confirmPopup(
  "Apply this change?",
  () => console.log("confirmed"),
  () => console.log("canceled")
);