Методы, события и отмена перехода
Включите запрет и попробуйте открыть настройки. Затем освободите экземпляры и создайте их повторно.
Экземпляры готовы.
Ожидание действий
<div class="tabs-demo-toolbar">
<button type="button" class="btn btn-surface btn-sm" id="tabs-api-open">Открыть настройки</button>
<button type="button" class="btn btn-surface btn-sm" id="tabs-api-dispose">Освободить экземпляры</button>
<button type="button" class="btn btn-surface btn-sm" id="tabs-api-init">Инициализировать</button>
<label><input type="checkbox" id="tabs-api-lock"> Запретить переход в настройки</label>
</div>
<div class="tabs-demo" id="tabs-api-demo">
<div class="vg-tabs">
<div class="vg-tabs-panel" role="tablist" aria-label="Разделы примера">
<div class="vg-tabs-item"><button type="button" class="vg-tabs-link active" id="tabs-api-0-tab" data-vg-toggle="tab" data-vg-target="#tabs-api-0" aria-controls="tabs-api-0">Обзор</button></div>
<div class="vg-tabs-item"><button type="button" class="vg-tabs-link" id="tabs-api-1-tab" data-vg-toggle="tab" data-vg-target="#tabs-api-1" aria-controls="tabs-api-1">Настройки</button></div>
</div>
</div>
<div class="vg-tabs-content tabs-demo-content">
<div class="vg-tabs-pane show active" id="tabs-api-0" tabindex="0">Кнопки выше используют публичные методы VGTabs.</div>
<div class="vg-tabs-pane" id="tabs-api-1" tabindex="0">Настройки открыты. События ниже показывают предыдущую и следующую вкладки.</div>
</div>
</div>
<p id="tabs-api-status" role="status">Экземпляры готовы.</p>
<pre class="tabs-demo-log" id="tabs-api-log" aria-label="Журнал событий" aria-live="polite">Ожидание действий</pre>
/**
* Описание: публичное управление VGTabs.
* Возможности: инициализация, show, dispose, отмена перехода и журнал событий.
*/
import { VGTabs } from 'vgapp';
function initTabsDemo() {
const root = document.querySelector('#tabs-api-demo');
if (!root || root.dataset.ready) return;
root.dataset.ready = 'true';
const tabs = [...root.querySelectorAll('[data-vg-toggle="tab"]')];
const status = document.querySelector('#tabs-api-status');
const log = document.querySelector('#tabs-api-log');
const entries = [];
const init = () => {
tabs.forEach(tab => VGTabs.getOrCreateInstance(tab, { slide: true }));
status.textContent = 'Экземпляры готовы: ' + tabs.filter(tab => VGTabs.getInstance(tab)).length;
};
for (const name of ['hide', 'show', 'hidden', 'shown']) {
root.addEventListener('vg.tabs.' + name, event => {
if (name === 'show' && event.target === tabs[1] && document.querySelector('#tabs-api-lock').checked) {
event.preventDefault();
}
entries.unshift(name + ': ' + event.target.textContent.trim() +
' ← relatedTarget: ' + (event.relatedTarget?.textContent.trim() || 'нет') +
(event.defaultPrevented ? ' [отменено]' : ''));
log.textContent = entries.slice(0, 8).join('\n');
});
}
document.querySelector('#tabs-api-open').addEventListener('click', () => {
VGTabs.getOrCreateInstance(tabs[1], { slide: true }).show();
});
document.querySelector('#tabs-api-dispose').addEventListener('click', () => {
tabs.forEach(tab => VGTabs.getInstance(tab)?.dispose());
status.textContent = 'Экземпляры освобождены. Data API остаётся подключён: клик создаст экземпляр заново.';
});
document.querySelector('#tabs-api-init').addEventListener('click', init);
init();
}
initTabsDemo();
/* Токены OKAUX в демо настроены с префиксом vg; состояние темы общее. */
.tabs-demo { min-width: 0; }
.tabs-demo-content {
margin-top: 1rem;
padding: 1rem;
border: 1px solid var(--vg-border-default);
border-radius: var(--vg-radius-md);
background: var(--vg-bg-secondary);
overflow-wrap: anywhere;
}
.tabs-demo-custom {
--vg-tabs-panel-gap: 0.35rem;
--vg-tabs-link-padding-x: 0.75rem;
--vg-tabs-slider-border-radius: 999px;
--vg-tabs-track-slider-border-radius: 999px;
}
.tabs-demo-vertical {
display: grid;
grid-template-columns: 150px minmax(0, 1fr);
align-items: start;
gap: 1rem;
}
.tabs-demo-vertical > .tabs-demo-content { margin-top: 0; }
@media (max-width: 575.98px) {
.tabs-demo-vertical { grid-template-columns: minmax(0, 1fr); }
}
.tabs-demo-toolbar { display: flex; flex-wrap: wrap; align-items: center; gap: 0.75rem; margin-bottom: 1rem; }
.tabs-demo-status { margin-top: 1rem; }
.tabs-demo-log { max-width: 100%; white-space: pre-wrap; overflow-wrap: anywhere; font-size: 0.85rem; }