Category Tabs
Scrollable category tab bars for POS product browsing with icons, badges, and color coding. Supports indicator, pill, and bordered styles with size variants.
Basic Category Tabs
Preview
<div class="category-tabs category-tabs-bordered category-tabs-indicator-style">
<button class="category-tabs-item category-tabs-item-active">
<span class="category-tabs-icon">
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><rect x="3" y="3" width="7" height="7"/><rect x="14" y="3" width="7" height="7"/><rect x="3" y="14" width="7" height="7"/><rect x="14" y="14" width="7" height="7"/></svg>
</span>
<span class="category-tabs-label">All</span>
</button>
<button class="category-tabs-item">
<span class="category-tabs-icon">
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M18 8h1a4 4 0 0 1 0 8h-1"/><path d="M2 8h16v9a4 4 0 0 1-4 4H6a4 4 0 0 1-4-4V8z"/><line x1="6" y1="1" x2="6" y2="4"/><line x1="10" y1="1" x2="10" y2="4"/><line x1="14" y1="1" x2="14" y2="4"/></svg>
</span>
<span class="category-tabs-label">Drinks</span>
</button>
<button class="category-tabs-item">
<span class="category-tabs-icon">
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M17 8c0-5-5-5-5-5s-5 0-5 5c0 3 2 5 5 9 3-4 5-6 5-9z"/><circle cx="12" cy="8" r="2"/></svg>
</span>
<span class="category-tabs-label">Food</span>
</button>
<button class="category-tabs-item">
<span class="category-tabs-icon">
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M20.59 13.41l-7.17 7.17a2 2 0 01-2.83 0L2 12V2h10l8.59 8.59a2 2 0 010 2.82z"/><line x1="7" y1="7" x2="7.01" y2="7"/></svg>
</span>
<span class="category-tabs-label">Specials</span>
</button>
<button class="category-tabs-item">
<span class="category-tabs-label">Desserts</span>
</button>
<button class="category-tabs-item category-tabs-item-disabled">
<span class="category-tabs-label">Seasonal</span>
</button>
<div class="category-tabs-indicator" style="left: 0; width: 64px;"></div>
</div> Requires: ux.min.css
<div class="flex items-center relative gap-2 px-4 py-2 bg-base-100 overflow-x-auto border-b border-base-300" style="scrollbar-width: none;">
<button class="relative flex items-center justify-center whitespace-nowrap cursor-pointer border-none bg-transparent text-primary font-medium text-sm min-h-12 px-6 transition-colors">
<svg class="w-5 h-5 shrink-0 mr-1" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><rect x="3" y="3" width="7" height="7"/><rect x="14" y="3" width="7" height="7"/><rect x="3" y="14" width="7" height="7"/><rect x="14" y="14" width="7" height="7"/></svg>
All
</button>
<button class="relative flex items-center justify-center whitespace-nowrap cursor-pointer border-none bg-transparent text-base-content/60 hover:text-base-content font-medium text-sm min-h-12 px-6 transition-colors">
<svg class="w-5 h-5 shrink-0 mr-1" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><path d="M18 8h1a4 4 0 0 1 0 8h-1"/><path d="M2 8h16v9a4 4 0 0 1-4 4H6a4 4 0 0 1-4-4V8z"/></svg>
Drinks
</button>
<button class="relative flex items-center justify-center whitespace-nowrap cursor-pointer border-none bg-transparent text-base-content/60 hover:text-base-content font-medium text-sm min-h-12 px-6 transition-colors">
Food
</button>
<button class="relative flex items-center justify-center whitespace-nowrap cursor-pointer border-none bg-transparent text-base-content/60 hover:text-base-content font-medium text-sm min-h-12 px-6 transition-colors">
Specials
</button>
<!-- Sliding indicator bar -->
<div class="absolute bottom-0 h-0.75 bg-primary rounded-t transition-all duration-300" style="left: 0; width: 64px;"></div>
</div> Requires: tw.min.css
// Switch active tab and move indicator
document.querySelectorAll('.category-tabs').forEach(tabs => {
const indicator = tabs.querySelector('.category-tabs-indicator');
const items = tabs.querySelectorAll('.category-tabs-item');
items.forEach(item => {
item.addEventListener('click', () => {
// Remove active from all
items.forEach(i => i.classList.remove('category-tabs-item-active'));
item.classList.add('category-tabs-item-active');
// Move indicator
if (indicator) {
indicator.style.left = item.offsetLeft + 'px';
indicator.style.width = item.offsetWidth + 'px';
}
});
});
}); Pill Variant
Preview
<div class="category-tabs category-tabs-pill">
<button class="category-tabs-item category-tabs-item-active">
<span class="category-tabs-label">All Items</span>
</button>
<button class="category-tabs-item">
<span class="category-tabs-label">Burgers</span>
</button>
<button class="category-tabs-item">
<span class="category-tabs-label">Sides</span>
</button>
<button class="category-tabs-item">
<span class="category-tabs-label">Drinks</span>
</button>
<button class="category-tabs-item">
<span class="category-tabs-label">Combos</span>
</button>
<button class="category-tabs-item">
<span class="category-tabs-label">Kids Menu</span>
</button>
</div> Requires: ux.min.css
<div class="flex items-center gap-1 p-1 bg-base-200 rounded-xl overflow-x-auto" style="scrollbar-width: none;">
<button class="flex items-center justify-center whitespace-nowrap cursor-pointer border-none min-h-9 px-4 rounded-full bg-base-100 text-base-content font-medium text-sm shadow-sm">All Items</button>
<button class="flex items-center justify-center whitespace-nowrap cursor-pointer border-none min-h-9 px-4 rounded-full bg-transparent text-base-content/60 hover:text-base-content font-medium text-sm">Burgers</button>
<button class="flex items-center justify-center whitespace-nowrap cursor-pointer border-none min-h-9 px-4 rounded-full bg-transparent text-base-content/60 hover:text-base-content font-medium text-sm">Sides</button>
<button class="flex items-center justify-center whitespace-nowrap cursor-pointer border-none min-h-9 px-4 rounded-full bg-transparent text-base-content/60 hover:text-base-content font-medium text-sm">Drinks</button>
<button class="flex items-center justify-center whitespace-nowrap cursor-pointer border-none min-h-9 px-4 rounded-full bg-transparent text-base-content/60 hover:text-base-content font-medium text-sm">Combos</button>
<button class="flex items-center justify-center whitespace-nowrap cursor-pointer border-none min-h-9 px-4 rounded-full bg-transparent text-base-content/60 hover:text-base-content font-medium text-sm">Kids Menu</button>
</div> Requires: tw.min.css
// Pill variant tab switching
document.querySelectorAll('.category-tabs-pill .category-tabs-item').forEach(item => {
item.addEventListener('click', () => {
const parent = item.closest('.category-tabs-pill');
parent.querySelectorAll('.category-tabs-item').forEach(i =>
i.classList.remove('category-tabs-item-active')
);
item.classList.add('category-tabs-item-active');
});
}); Color Variants
Preview
<div class="flex flex-col gap-4">
<!-- Primary color -->
<div class="category-tabs category-tabs-bordered category-tabs-primary category-tabs-indicator-style">
<button class="category-tabs-item category-tabs-item-active">
<span class="category-tabs-label">ERPlora POS</span>
</button>
<button class="category-tabs-item">
<span class="category-tabs-label">Appetizers</span>
</button>
<button class="category-tabs-item">
<span class="category-tabs-label">Main Course</span>
</button>
<button class="category-tabs-item">
<span class="category-tabs-label">Beverages</span>
</button>
<div class="category-tabs-indicator" style="left: 0; width: 100px;"></div>
</div>
<!-- Success color -->
<div class="category-tabs category-tabs-bordered category-tabs-success category-tabs-indicator-style">
<button class="category-tabs-item category-tabs-item-active">
<span class="category-tabs-label">Organic</span>
</button>
<button class="category-tabs-item">
<span class="category-tabs-label">Vegan</span>
</button>
<button class="category-tabs-item">
<span class="category-tabs-label">Gluten-Free</span>
</button>
<button class="category-tabs-item">
<span class="category-tabs-label">Local</span>
</button>
<div class="category-tabs-indicator" style="left: 0; width: 80px;"></div>
</div>
<!-- Danger color -->
<div class="category-tabs category-tabs-bordered category-tabs-danger category-tabs-indicator-style">
<button class="category-tabs-item category-tabs-item-active">
<span class="category-tabs-label">Hot & Spicy</span>
</button>
<button class="category-tabs-item">
<span class="category-tabs-label">BBQ</span>
</button>
<button class="category-tabs-item">
<span class="category-tabs-label">Grill</span>
</button>
<div class="category-tabs-indicator" style="left: 0; width: 96px;"></div>
</div>
</div> Requires: ux.min.css
<div class="flex flex-col gap-4">
<!-- Primary color -->
<div class="flex items-center relative gap-2 px-4 py-2 bg-base-100 overflow-x-auto border-b border-base-300" style="scrollbar-width: none;">
<button class="relative flex items-center justify-center whitespace-nowrap cursor-pointer border-none bg-transparent text-primary font-medium text-sm min-h-12 px-6">ERPlora POS</button>
<button class="relative flex items-center justify-center whitespace-nowrap cursor-pointer border-none bg-transparent text-base-content/60 hover:text-base-content font-medium text-sm min-h-12 px-6">Appetizers</button>
<button class="relative flex items-center justify-center whitespace-nowrap cursor-pointer border-none bg-transparent text-base-content/60 hover:text-base-content font-medium text-sm min-h-12 px-6">Main Course</button>
<button class="relative flex items-center justify-center whitespace-nowrap cursor-pointer border-none bg-transparent text-base-content/60 hover:text-base-content font-medium text-sm min-h-12 px-6">Beverages</button>
<div class="absolute bottom-0 h-0.75 bg-primary rounded-t transition-all duration-300" style="left: 0; width: 100px;"></div>
</div>
<!-- Success color -->
<div class="flex items-center relative gap-2 px-4 py-2 bg-base-100 overflow-x-auto border-b border-base-300" style="scrollbar-width: none;">
<button class="relative flex items-center justify-center whitespace-nowrap cursor-pointer border-none bg-transparent text-success font-medium text-sm min-h-12 px-6">Organic</button>
<button class="relative flex items-center justify-center whitespace-nowrap cursor-pointer border-none bg-transparent text-base-content/60 hover:text-base-content font-medium text-sm min-h-12 px-6">Vegan</button>
<button class="relative flex items-center justify-center whitespace-nowrap cursor-pointer border-none bg-transparent text-base-content/60 hover:text-base-content font-medium text-sm min-h-12 px-6">Gluten-Free</button>
<button class="relative flex items-center justify-center whitespace-nowrap cursor-pointer border-none bg-transparent text-base-content/60 hover:text-base-content font-medium text-sm min-h-12 px-6">Local</button>
<div class="absolute bottom-0 h-0.75 bg-success rounded-t transition-all duration-300" style="left: 0; width: 80px;"></div>
</div>
<!-- Danger color -->
<div class="flex items-center relative gap-2 px-4 py-2 bg-base-100 overflow-x-auto border-b border-base-300" style="scrollbar-width: none;">
<button class="relative flex items-center justify-center whitespace-nowrap cursor-pointer border-none bg-transparent text-error font-medium text-sm min-h-12 px-6">Hot & Spicy</button>
<button class="relative flex items-center justify-center whitespace-nowrap cursor-pointer border-none bg-transparent text-base-content/60 hover:text-base-content font-medium text-sm min-h-12 px-6">BBQ</button>
<button class="relative flex items-center justify-center whitespace-nowrap cursor-pointer border-none bg-transparent text-base-content/60 hover:text-base-content font-medium text-sm min-h-12 px-6">Grill</button>
<div class="absolute bottom-0 h-0.75 bg-error rounded-t transition-all duration-300" style="left: 0; width: 96px;"></div>
</div>
</div> Requires: tw.min.css
// Color-coded categories for ERPlora POS system
const categoryConfig = {
'Hot & Spicy': { color: 'danger', icon: 'flame' },
'Organic': { color: 'success', icon: 'leaf' },
'ERPlora POS': { color: 'primary', icon: 'grid' }
};
function applyTabColor(tabsEl, color) {
tabsEl.classList.remove('category-tabs-primary', 'category-tabs-success', 'category-tabs-danger');
tabsEl.classList.add('category-tabs-' + color);
} Size Variants & Glass
Preview
<div class="flex flex-col gap-4">
<!-- Small -->
<div class="category-tabs category-tabs-bordered category-tabs-sm category-tabs-indicator-style">
<button class="category-tabs-item category-tabs-item-active">
<span class="category-tabs-label">Small</span>
</button>
<button class="category-tabs-item">
<span class="category-tabs-label">Compact</span>
</button>
<button class="category-tabs-item">
<span class="category-tabs-label">Dense</span>
</button>
<div class="category-tabs-indicator" style="left: 0; width: 64px;"></div>
</div>
<!-- Large -->
<div class="category-tabs category-tabs-bordered category-tabs-lg category-tabs-indicator-style">
<button class="category-tabs-item category-tabs-item-active">
<span class="category-tabs-icon">
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><rect x="3" y="3" width="7" height="7"/><rect x="14" y="3" width="7" height="7"/><rect x="3" y="14" width="7" height="7"/><rect x="14" y="14" width="7" height="7"/></svg>
</span>
<span class="category-tabs-label">Large Tabs</span>
</button>
<button class="category-tabs-item">
<span class="category-tabs-label">Touchscreen</span>
</button>
<button class="category-tabs-item">
<span class="category-tabs-label">POS Display</span>
</button>
<div class="category-tabs-indicator" style="left: 0; width: 120px;"></div>
</div>
<!-- Glass pill -->
<div class="p-4 rounded-box" style="background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);">
<div class="category-tabs category-tabs-pill glass">
<button class="category-tabs-item category-tabs-item-active">
<span class="category-tabs-label">ERPlora Menu</span>
</button>
<button class="category-tabs-item">
<span class="category-tabs-label">Popular</span>
</button>
<button class="category-tabs-item">
<span class="category-tabs-label">New</span>
</button>
<button class="category-tabs-item">
<span class="category-tabs-label">Promo</span>
</button>
</div>
</div>
</div> Requires: ux.min.css
<div class="flex flex-col gap-4">
<!-- Small -->
<div class="flex items-center relative gap-2 px-4 py-2 bg-base-100 overflow-x-auto border-b border-base-300" style="scrollbar-width: none;">
<button class="relative flex items-center justify-center whitespace-nowrap cursor-pointer border-none bg-transparent text-primary font-medium text-xs min-h-9 px-4">Small</button>
<button class="relative flex items-center justify-center whitespace-nowrap cursor-pointer border-none bg-transparent text-base-content/60 hover:text-base-content font-medium text-xs min-h-9 px-4">Compact</button>
<button class="relative flex items-center justify-center whitespace-nowrap cursor-pointer border-none bg-transparent text-base-content/60 hover:text-base-content font-medium text-xs min-h-9 px-4">Dense</button>
<div class="absolute bottom-0 h-0.5 bg-primary rounded-t transition-all duration-300" style="left: 0; width: 64px;"></div>
</div>
<!-- Large -->
<div class="flex items-center relative gap-2 px-4 py-2 bg-base-100 overflow-x-auto border-b border-base-300" style="scrollbar-width: none;">
<button class="relative flex items-center justify-center whitespace-nowrap cursor-pointer border-none bg-transparent text-primary font-medium text-base min-h-14 px-8">
<svg class="w-6 h-6 shrink-0 mr-1" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><rect x="3" y="3" width="7" height="7"/><rect x="14" y="3" width="7" height="7"/><rect x="3" y="14" width="7" height="7"/><rect x="14" y="14" width="7" height="7"/></svg>
Large Tabs
</button>
<button class="relative flex items-center justify-center whitespace-nowrap cursor-pointer border-none bg-transparent text-base-content/60 hover:text-base-content font-medium text-base min-h-14 px-8">Touchscreen</button>
<button class="relative flex items-center justify-center whitespace-nowrap cursor-pointer border-none bg-transparent text-base-content/60 hover:text-base-content font-medium text-base min-h-14 px-8">POS Display</button>
<div class="absolute bottom-0 h-1 bg-primary rounded-t transition-all duration-300" style="left: 0; width: 120px;"></div>
</div>
<!-- Glass pill -->
<div class="p-4 rounded-box" style="background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);">
<div class="flex items-center gap-1 p-1 rounded-xl glass">
<button class="flex items-center justify-center whitespace-nowrap cursor-pointer border-none min-h-9 px-4 rounded-full font-medium text-sm shadow-sm" style="background-color: color-mix(in oklch, var(--color-base-100) 85%, transparent);">ERPlora Menu</button>
<button class="flex items-center justify-center whitespace-nowrap cursor-pointer border-none min-h-9 px-4 rounded-full bg-transparent text-white/70 hover:text-white font-medium text-sm">Popular</button>
<button class="flex items-center justify-center whitespace-nowrap cursor-pointer border-none min-h-9 px-4 rounded-full bg-transparent text-white/70 hover:text-white font-medium text-sm">New</button>
<button class="flex items-center justify-center whitespace-nowrap cursor-pointer border-none min-h-9 px-4 rounded-full bg-transparent text-white/70 hover:text-white font-medium text-sm">Promo</button>
</div>
</div>
</div> Requires: tw.min.css
// Responsive: auto-switch to small tabs on narrow screens
function autoSizeTabs(tabsEl, breakpoint = 640) {
const observer = new ResizeObserver(entries => {
for (const entry of entries) {
const width = entry.contentRect.width;
tabsEl.classList.toggle('category-tabs-sm', width < breakpoint);
tabsEl.classList.toggle('category-tabs-lg', width > 1024);
}
});
observer.observe(tabsEl.parentElement);
} Classes Reference
| Class | Description |
|---|---|
category-tabs | Base scrollable tab container with hidden scrollbar |
category-tabs-bordered | Adds bottom border to container |
category-tabs-indicator-style | Enables relative positioning for sliding indicator |
category-tabs-pill | Pill/segment style with rounded background |
category-tabs-sm | Small size variant (36px height, text-xs) |
category-tabs-lg | Large size variant (56px height, text-base) |
category-tabs-primary | Primary color for active tab and indicator |
category-tabs-success | Success color for active tab and indicator |
category-tabs-danger | Danger/error color for active tab and indicator |
category-tabs-item | Individual tab button |
category-tabs-item-active | Active tab state (primary color by default) |
category-tabs-item-disabled | Disabled tab (reduced opacity, no pointer events) |
category-tabs-item-icon-only | Icon-only tab (hides label, removes icon margin) |
category-tabs-icon | Icon container inside a tab item |
category-tabs-label | Text label inside a tab item |
category-tabs-indicator | Sliding bottom indicator bar (position via JS) |