This repository has been archived on 2026-04-03. You can view files and clone it. You cannot open issues or pull requests or push a commit.
Files
core/src/js/sw/primitives/tabs.js
gobha 4f1abc6321 Changeset 0.37.2 (#214)
Co-authored-by: gobha <jasafpro@gmail.com>
Co-committed-by: gobha <jasafpro@gmail.com>
2026-03-20 23:52:55 +00:00

61 lines
2.3 KiB
JavaScript

/**
* Tabs primitive — horizontal tab bar with overflow scroll arrows
* tabs: [{ label, value, icon?, disabled? }]
*/
const { html } = window;
const { useRef, useEffect, useState, useCallback } = hooks;
export function Tabs({ tabs = [], active, onChange }) {
const scrollRef = useRef(null);
const [overflow, setOverflow] = useState({ left: false, right: false });
const checkOverflow = useCallback(() => {
const el = scrollRef.current;
if (!el) return;
setOverflow({
left: el.scrollLeft > 0,
right: el.scrollLeft + el.clientWidth < el.scrollWidth - 1,
});
}, []);
useEffect(() => {
checkOverflow();
const el = scrollRef.current;
if (el) el.addEventListener('scroll', checkOverflow, { passive: true });
window.addEventListener('resize', checkOverflow);
return () => {
if (el) el.removeEventListener('scroll', checkOverflow);
window.removeEventListener('resize', checkOverflow);
};
}, [checkOverflow, tabs]);
const scroll = (dir) => {
const el = scrollRef.current;
if (el) el.scrollBy({ left: dir * 150, behavior: 'smooth' });
};
return html`
<div class="sw-tabs">
${overflow.left && html`
<button class="sw-tabs__arrow sw-tabs__arrow--left" onClick=${() => scroll(-1)} aria-label="Scroll left">\u2039</button>
`}
<div class="sw-tabs__scroll" ref=${scrollRef}>
${tabs.map(tab => html`
<button
class="sw-tabs__tab ${tab.value === active ? 'sw-tabs__tab--active' : ''} ${tab.disabled ? 'sw-tabs__tab--disabled' : ''}"
disabled=${tab.disabled}
onClick=${() => !tab.disabled && onChange && onChange(tab.value)}
role="tab"
aria-selected=${tab.value === active}>
${tab.icon && html`<span class="sw-tabs__icon">${tab.icon}</span>`}
${tab.label}
</button>
`)}
</div>
${overflow.right && html`
<button class="sw-tabs__arrow sw-tabs__arrow--right" onClick=${() => scroll(1)} aria-label="Scroll right">\u203a</button>
`}
</div>
`;
}