sunatest / frontend /src /components /ui /fancy-tabs.tsx
llama1's picture
Upload 781 files
5da4770 verified
'use client';
import React from 'react';
import { LucideIcon } from 'lucide-react';
import { cn } from '@/lib/utils';
import { useTheme } from 'next-themes';
export interface TabConfig {
value: string;
icon: LucideIcon;
label: string;
shortLabel?: string;
}
interface FancyTabsProps {
tabs: TabConfig[];
activeTab: string;
onTabChange: (value: string) => void;
className?: string;
}
interface TabButtonProps {
value: string;
isActive: boolean;
onClick: () => void;
children: React.ReactNode;
}
const TabButton = ({ value, isActive, onClick, children }: TabButtonProps) => {
const { theme } = useTheme();
const isDark = theme === 'dark';
return (
<button
onClick={onClick}
className={cn(
"relative flex items-center justify-center gap-2 rounded-2xl px-4 py-2.5 text-sm font-medium transition-all duration-300 ease-out",
// Only apply hover background when not active - subtle and elegant
!isActive && (isDark ? "hover:bg-white/8" : "hover:bg-muted/60"),
isActive
? isDark ? "text-white" : "text-foreground bg-background border border-border/50"
: isDark ? "text-white/60 hover:text-white/85" : "text-muted-foreground hover:text-foreground"
)}
style={isActive && isDark ? {
background: 'linear-gradient(135deg, rgba(255, 255, 255, 0.15), rgba(255, 255, 255, 0.08))',
backdropFilter: 'blur(12px)',
boxShadow: `
0 4px 8px rgba(0, 0, 0, 0.1),
0 0 20px rgba(255, 255, 255, 0.1),
0 0 40px rgba(255, 255, 255, 0.1),
inset 0 1px 0 rgba(255, 255, 255, 0.2)
`
} : undefined}
>
{isActive && isDark && (
<div
className="absolute inset-0 rounded-2xl opacity-40 blur-sm"
style={{
background: 'linear-gradient(45deg, rgba(255, 255, 255, 0.2), rgba(255, 255, 255, 0.1))',
zIndex: -1
}}
/>
)}
{children}
</button>
);
};
export const FancyTabs = ({ tabs, activeTab, onTabChange, className }: FancyTabsProps) => {
const { theme } = useTheme();
const isDark = theme === 'dark';
return (
<div
className={cn(
"overflow-hidden grid w-full max-w-lg mx-auto rounded-3xl p-1.5",
isDark ? "border-white/5" : "border-border/20 bg-muted",
className
)}
style={{
gridTemplateColumns: `repeat(${tabs.length}, 1fr)`,
...(isDark ? {
background: 'rgba(255, 255, 255, 0.05)',
backdropFilter: 'blur(20px)',
} : {})
}}
>
{tabs.map((tab) => {
const Icon = tab.icon;
return (
<TabButton
key={tab.value}
value={tab.value}
isActive={activeTab === tab.value}
onClick={() => onTabChange(tab.value)}
>
<Icon className="h-4 w-4" />
<span className="hidden sm:inline">{tab.label}</span>
{tab.shortLabel && (
<span className="sm:hidden">{tab.shortLabel}</span>
)}
</TabButton>
);
})}
</div>
);
};