// Dependencies: react ^18, lucide-react
import React, { useState } from 'react';
import { MoreHorizontal } from 'lucide-react';
function cn(...classes: (string | false | null | undefined)[]) {
return classes.filter(Boolean).join(' ');
}
const ALL_TABS = [
'Overview',
'Deployments',
'Analytics',
'Logs',
'Speed Insights',
'Firewall',
'Storage',
'Domains',
'Settings',
];
const MAX_VISIBLE = 5;
export function TabBarOverflow() {
const [activeIdx, setActiveIdx] = useState(0);
const [overflowOpen, setOverflowOpen] = useState(false);
const { visibleIndices, overflowIndices } = computeLayout(activeIdx);
return (
<div className="w-full max-w-[640px] bg-zinc-900 border border-white/[0.08] rounded-xl overflow-visible">
<div className="flex items-center gap-2 px-5 pt-4 pb-2 border-b border-white/[0.06]">
<div className="w-5 h-5 rounded bg-indigo-500 flex items-center justify-center shrink-0">
<span className="text-[10px] font-bold text-white">A</span>
</div>
<span className="text-sm font-semibold text-white">acme-corp</span>
<span className="text-zinc-600">/</span>
<span className="text-sm font-semibold text-zinc-300">web-platform</span>
</div>
<div className="relative flex items-end gap-0 px-3 pt-2">
{visibleIndices.map((idx) => (
<button
key={idx}
onClick={() => setActiveIdx(idx)}
className={cn(
'relative px-3 pt-1.5 pb-3 text-sm font-medium transition-colors',
activeIdx === idx
? 'text-white'
: 'text-zinc-500 hover:text-zinc-200'
)}
>
{ALL_TABS[idx]}
{activeIdx === idx && (
<span className="absolute bottom-0 left-1 right-1 h-[2px] rounded-full bg-indigo-500" />
)}
</button>
))}
{overflowIndices.length > 0 && (
<div className="relative ml-auto pb-2">
<button
onClick={() => setOverflowOpen((v) => !v)}
onBlur={() => setTimeout(() => setOverflowOpen(false), 100)}
className="flex items-center gap-1 px-2 py-1 rounded-md text-zinc-500 hover:text-zinc-200 hover:bg-white/[0.05] transition-colors"
aria-label="More tabs"
>
<MoreHorizontal className="w-4 h-4" />
</button>
{overflowOpen && (
<div className="absolute right-0 top-full mt-1 z-50 min-w-[180px] bg-[#1a1a1a] border border-[#2a2a2a] rounded-lg shadow-2xl py-1">
{overflowIndices.map((idx) => (
<button
key={idx}
onMouseDown={(e) => {
e.preventDefault();
setActiveIdx(idx);
setOverflowOpen(false);
}}
className="w-full text-left px-3 py-1.5 text-xs text-zinc-300 hover:bg-white/[0.06] hover:text-white transition-colors"
>
{ALL_TABS[idx]}
</button>
))}
</div>
)}
</div>
)}
</div>
<div className="h-px bg-white/[0.06]" />
<div className="px-5 py-6 min-h-[140px] flex items-center gap-3">
<div className="w-2 h-2 rounded-full bg-emerald-400 animate-pulse shrink-0" />
<span className="text-sm text-zinc-400">{ALL_TABS[activeIdx]} content</span>
</div>
</div>
);
}
function computeLayout(activeIdx: number) {
const allIndices = ALL_TABS.map((_, i) => i);
if (activeIdx < MAX_VISIBLE) {
return {
visibleIndices: allIndices.slice(0, MAX_VISIBLE),
overflowIndices: allIndices.slice(MAX_VISIBLE),
};
}
const head = allIndices.slice(0, MAX_VISIBLE - 1);
return {
visibleIndices: [...head, activeIdx],
overflowIndices: allIndices
.slice(MAX_VISIBLE - 1)
.filter((i) => i !== activeIdx),
};
}