b0nes
Version:
Zero-dependency component library and SSR/SSG framework
64 lines (58 loc) • 1.98 kB
JavaScript
import { processSlot } from '../../utils/processSlot.js';
/**
* Tabs component - Interactive tabbed interface
* Requires b0nes.js for client-side interactivity
*
* @param {Object} props
* @param {Array} props.tabs - Array of tab objects: [{ label: 'Tab 1', content: '...' }]
* @param {string} [props.className] - Additional CSS classes
* @param {string} [props.attrs] - Additional HTML attributes
* @returns {string} HTML string
*
* @example
* tabs({
* tabs: [
* { label: 'Home', content: '<p>Home content</p>' },
* { label: 'About', content: '<p>About content</p>' }
* ]
* })
*/
export const tabs = ({ tabs = [], className, attrs }) => {
if (!Array.isArray(tabs) || tabs.length === 0) {
return '';
}
attrs = attrs ? ` ${attrs}` : '';
className = className ? ` ${className}` : '';
// Generate tab buttons
const tabButtons = tabs.map((tab, index) => {
const activeClass = index === 0 ? ' active' : '';
const ariaSelected = index === 0 ? 'true' : 'false';
return `<button
class="tab-button${activeClass}"
role="tab"
aria-selected="${ariaSelected}"
aria-controls="tab-panel-${index}"
data-tab-index="${index}"
>${tab.label}</button>`;
}).join('');
// Generate tab panels
const tabPanels = tabs.map((tab, index) => {
const activeClass = index === 0 ? ' active' : '';
const hidden = index === 0 ? '' : ' hidden';
const content = processSlot(tab.content) ?? '';
return `<div
class="tab-panel${activeClass}"
role="tabpanel"
id="tab-panel-${index}"
${hidden}
>${content}</div>`;
}).join('');
return `<div class="tabs${className}" data-b0nes="molecules:tabs" role="tablist"${attrs}>
<div class="tab-buttons">
${tabButtons}
</div>
<div class="tab-panels">
${tabPanels}
</div>
</div>`;
};