104 lines
3.5 KiB
TypeScript
104 lines
3.5 KiB
TypeScript
// FloatContent.tsx — Float 서브탭 래퍼
|
|
|
|
import { useState } from 'react';
|
|
import type { DesignTheme } from './designTheme';
|
|
import { FloatModalContent } from './float/FloatModalContent';
|
|
import { FloatDropdownContent } from './float/FloatDropdownContent';
|
|
import { FloatOverlayContent } from './float/FloatOverlayContent';
|
|
import { FloatToastContent } from './float/FloatToastContent';
|
|
|
|
type FloatSubTab = 'modal' | 'dropdown' | 'overlay' | 'toast';
|
|
|
|
const SUB_TABS: { id: FloatSubTab; label: string; desc: string }[] = [
|
|
{ id: 'modal', label: 'Modal', desc: 'Dialog · Confirm' },
|
|
{ id: 'dropdown', label: 'Dropdown', desc: 'ComboBox · Select' },
|
|
{ id: 'overlay', label: 'Overlay', desc: 'Map Layer · Popup' },
|
|
{ id: 'toast', label: 'Toast', desc: 'Notification · Alert' },
|
|
];
|
|
|
|
interface FloatContentProps {
|
|
theme: DesignTheme;
|
|
}
|
|
|
|
export const FloatContent = ({ theme }: FloatContentProps) => {
|
|
const [activeSubTab, setActiveSubTab] = useState<FloatSubTab>('modal');
|
|
const t = theme;
|
|
const isDark = t.mode === 'dark';
|
|
|
|
const renderSubContent = () => {
|
|
switch (activeSubTab) {
|
|
case 'modal':
|
|
return <FloatModalContent theme={t} />;
|
|
case 'dropdown':
|
|
return <FloatDropdownContent theme={t} />;
|
|
case 'overlay':
|
|
return <FloatOverlayContent theme={t} />;
|
|
case 'toast':
|
|
return <FloatToastContent theme={t} />;
|
|
}
|
|
};
|
|
|
|
return (
|
|
<div className="flex flex-col h-full">
|
|
{/* 서브탭 헤더 */}
|
|
<div
|
|
className="px-8 pt-6 pb-0 border-b border-solid shrink-0"
|
|
style={{ borderColor: isDark ? 'rgba(66,71,84,0.20)' : '#e2e8f0' }}
|
|
>
|
|
<div className="flex flex-col gap-4">
|
|
<div>
|
|
<h1 className="font-sans text-2xl leading-8 font-bold" style={{ color: t.textPrimary }}>
|
|
Float
|
|
</h1>
|
|
<p
|
|
className="font-korean text-body-2 leading-5 mt-1"
|
|
style={{ color: t.textSecondary }}
|
|
>
|
|
화면 위에 떠서 표시되는 UI 패턴 카탈로그 — Modal, Dropdown, Overlay, Toast
|
|
</p>
|
|
</div>
|
|
|
|
{/* 서브탭 바 */}
|
|
<nav className="flex flex-row gap-1">
|
|
{SUB_TABS.map(({ id, label, desc }) => {
|
|
const isActive = activeSubTab === id;
|
|
return (
|
|
<button
|
|
key={id}
|
|
type="button"
|
|
onClick={() => setActiveSubTab(id)}
|
|
className="flex flex-col items-start px-4 pb-3 pt-1 cursor-pointer bg-transparent relative"
|
|
style={{
|
|
borderBottom: isActive ? `2px solid ${t.textAccent}` : '2px solid transparent',
|
|
}}
|
|
>
|
|
<span
|
|
className="font-sans text-body-2 font-bold leading-5"
|
|
style={{ color: isActive ? t.textAccent : t.textMuted }}
|
|
>
|
|
{label}
|
|
</span>
|
|
<span
|
|
className="font-mono text-caption leading-4"
|
|
style={{
|
|
color: isActive ? t.textAccent : t.textMuted,
|
|
opacity: isActive ? 0.7 : 0.5,
|
|
}}
|
|
>
|
|
{desc}
|
|
</span>
|
|
</button>
|
|
);
|
|
})}
|
|
</nav>
|
|
</div>
|
|
</div>
|
|
|
|
{/* 서브탭 콘텐츠 */}
|
|
<div className="flex-1 overflow-y-auto">{renderSubContent()}</div>
|
|
</div>
|
|
);
|
|
};
|
|
|
|
export default FloatContent;
|