* feat(tabs): add icon support for tabs - Introduced an `icon` property for tabs to display icons alongside tab labels. - Updated the tabs shortcode and HTML partials to accommodate the new icon feature. - Enhanced documentation for tabs to include examples of using icons in tab definitions. * chore: rebuild css * doc(tabs): add icon support in tab documentation for multiple languages - Enhanced documentation for tabs to include examples of using the `icon` parameter in Persian, Japanese, and Simplified Chinese. - Updated the tab shortcode examples to demonstrate how to display icons alongside tab labels. * chore: regenerate compiled css * fix(a11y): add aria-hidden to decorative tab icons Add aria-hidden="true" to tab icon SVGs so screen readers skip decorative icons and only announce the tab name. Update @example docblock in tab.html to demonstrate the icon parameter. * doc(tabs): improve icon section with better examples and icon page link Rename "Tabs With Icons" heading to "Add Icons" for consistency with other action-oriented section titles. Replace JSON/YAML/TOML icon example with Photos/Music/Videos using photograph, music-note, and film icons that naturally match their labels. Add link to the Icon shortcode page so users can discover available icon names.
103 lines
3.4 KiB
JavaScript
103 lines
3.4 KiB
JavaScript
(function () {
|
|
function updateGroup(container, index) {
|
|
const tabs = Array.from(container.querySelectorAll('.hextra-tabs-toggle'));
|
|
tabs.forEach((tab, i) => {
|
|
tab.dataset.state = i === index ? 'selected' : '';
|
|
if (i === index) {
|
|
tab.setAttribute('aria-selected', 'true');
|
|
tab.tabIndex = 0;
|
|
} else {
|
|
tab.setAttribute('aria-selected', 'false');
|
|
tab.tabIndex = -1;
|
|
}
|
|
});
|
|
const panelsContainer = container.parentElement.nextElementSibling;
|
|
if (!panelsContainer) return;
|
|
Array.from(panelsContainer.children).forEach((panel, i) => {
|
|
panel.dataset.state = i === index ? 'selected' : '';
|
|
panel.setAttribute('aria-hidden', i === index ? 'false' : 'true');
|
|
if (i === index) {
|
|
panel.tabIndex = 0;
|
|
} else {
|
|
panel.removeAttribute('tabindex');
|
|
}
|
|
});
|
|
}
|
|
|
|
const syncGroups = document.querySelectorAll('[data-tab-group]');
|
|
|
|
syncGroups.forEach((group) => {
|
|
const key = encodeURIComponent(group.dataset.tabGroup);
|
|
const saved = localStorage.getItem('hextra-tab-' + key);
|
|
if (saved !== null) {
|
|
updateGroup(group, parseInt(saved, 10));
|
|
}
|
|
});
|
|
|
|
document.querySelectorAll('.hextra-tabs-toggle').forEach((button) => {
|
|
button.addEventListener('click', function (e) {
|
|
const targetButton = e.currentTarget;
|
|
const container = targetButton.parentElement;
|
|
const index = Array.from(container.querySelectorAll('.hextra-tabs-toggle')).indexOf(
|
|
targetButton
|
|
);
|
|
|
|
if (container.dataset.tabGroup) {
|
|
// Sync behavior: update all tab groups with the same name
|
|
const tabGroupValue = container.dataset.tabGroup;
|
|
const key = encodeURIComponent(tabGroupValue);
|
|
document
|
|
.querySelectorAll('[data-tab-group="' + tabGroupValue + '"]')
|
|
.forEach((grp) => updateGroup(grp, index));
|
|
localStorage.setItem('hextra-tab-' + key, index.toString());
|
|
} else {
|
|
// Non-sync behavior: update only this specific tab group
|
|
updateGroup(container, index);
|
|
}
|
|
});
|
|
|
|
// Keyboard navigation for tabs
|
|
button.addEventListener('keydown', function (e) {
|
|
const container = button.parentElement;
|
|
const tabs = Array.from(container.querySelectorAll('.hextra-tabs-toggle'));
|
|
const currentIndex = tabs.indexOf(button);
|
|
let newIndex;
|
|
|
|
switch (e.key) {
|
|
case 'ArrowRight':
|
|
case 'ArrowDown':
|
|
e.preventDefault();
|
|
newIndex = (currentIndex + 1) % tabs.length;
|
|
break;
|
|
case 'ArrowLeft':
|
|
case 'ArrowUp':
|
|
e.preventDefault();
|
|
newIndex = (currentIndex - 1 + tabs.length) % tabs.length;
|
|
break;
|
|
case 'Home':
|
|
e.preventDefault();
|
|
newIndex = 0;
|
|
break;
|
|
case 'End':
|
|
e.preventDefault();
|
|
newIndex = tabs.length - 1;
|
|
break;
|
|
default:
|
|
return;
|
|
}
|
|
|
|
if (container.dataset.tabGroup) {
|
|
const tabGroupValue = container.dataset.tabGroup;
|
|
const key = encodeURIComponent(tabGroupValue);
|
|
document
|
|
.querySelectorAll('[data-tab-group="' + tabGroupValue + '"]')
|
|
.forEach((grp) => updateGroup(grp, newIndex));
|
|
localStorage.setItem('hextra-tab-' + key, newIndex.toString());
|
|
} else {
|
|
updateGroup(container, newIndex);
|
|
}
|
|
tabs[newIndex].focus();
|
|
});
|
|
});
|
|
})();
|