88 lines
3.5 KiB
JavaScript
88 lines
3.5 KiB
JavaScript
const NAV = [
|
|
{
|
|
id: 'setup',
|
|
label: 'Setup',
|
|
icon: (
|
|
<svg width="18" height="18" viewBox="0 0 20 20" fill="none" stroke="currentColor" strokeWidth="1.6" strokeLinecap="round">
|
|
<line x1="3" y1="5" x2="17" y2="5"/><circle cx="7" cy="5" r="1.8" fill="white" stroke="currentColor" strokeWidth="1.6"/>
|
|
<line x1="3" y1="10" x2="17" y2="10"/><circle cx="13" cy="10" r="1.8" fill="white" stroke="currentColor" strokeWidth="1.6"/>
|
|
<line x1="3" y1="15" x2="17" y2="15"/><circle cx="8" cy="15" r="1.8" fill="white" stroke="currentColor" strokeWidth="1.6"/>
|
|
</svg>
|
|
)
|
|
},
|
|
{
|
|
id: 'baseline',
|
|
label: 'Baseline',
|
|
icon: (
|
|
<svg width="18" height="18" viewBox="0 0 20 20" fill="none" stroke="currentColor" strokeWidth="1.6" strokeLinecap="round" strokeLinejoin="round">
|
|
<polygon points="10,2 18,7 10,12 2,7"/>
|
|
<polyline points="2,12 10,17 18,12"/>
|
|
</svg>
|
|
)
|
|
},
|
|
{
|
|
id: 'forecast',
|
|
label: 'Forecast',
|
|
icon: (
|
|
<svg width="18" height="18" viewBox="0 0 20 20" fill="none" stroke="currentColor" strokeWidth="1.6" strokeLinecap="round" strokeLinejoin="round">
|
|
<polyline points="2,15 7,9 11,12 18,4"/>
|
|
<polyline points="14,4 18,4 18,8"/>
|
|
</svg>
|
|
)
|
|
},
|
|
]
|
|
|
|
export default function Sidebar({ view, setView, expanded, setExpanded }) {
|
|
return (
|
|
<div
|
|
className="bg-white border-r border-gray-200 flex flex-col shrink-0 overflow-hidden transition-all duration-150"
|
|
style={{ width: expanded ? 200 : 48 }}
|
|
>
|
|
<div className="h-12 flex items-center px-3 border-b border-gray-100 gap-2 shrink-0">
|
|
<button
|
|
onClick={() => setExpanded(e => !e)}
|
|
className="w-8 h-8 flex items-center justify-center rounded hover:bg-gray-100 text-gray-400 shrink-0"
|
|
title="Toggle sidebar"
|
|
>
|
|
<svg width="16" height="16" viewBox="0 0 16 16" fill="none">
|
|
<rect x="1" y="3" width="14" height="1.5" rx="0.75" fill="currentColor"/>
|
|
<rect x="1" y="7.25" width="14" height="1.5" rx="0.75" fill="currentColor"/>
|
|
<rect x="1" y="11.5" width="14" height="1.5" rx="0.75" fill="currentColor"/>
|
|
</svg>
|
|
</button>
|
|
<span
|
|
className="text-xs font-semibold text-gray-600 tracking-wide uppercase whitespace-nowrap transition-opacity duration-100"
|
|
style={{ opacity: expanded ? 1 : 0, pointerEvents: expanded ? 'auto' : 'none' }}
|
|
>
|
|
Pivot Forecast
|
|
</span>
|
|
</div>
|
|
|
|
<nav className="flex flex-col gap-0.5 p-2 flex-1">
|
|
{NAV.map(item => {
|
|
const active = view === item.id
|
|
return (
|
|
<button
|
|
key={item.id}
|
|
onClick={() => setView(item.id)}
|
|
title={!expanded ? item.label : undefined}
|
|
className={`flex items-center gap-3 px-2 py-2 rounded text-left w-full transition-colors ${
|
|
active
|
|
? 'bg-blue-50 text-blue-700'
|
|
: 'text-gray-500 hover:bg-gray-100 hover:text-gray-800'
|
|
}`}
|
|
>
|
|
<span className="shrink-0">{item.icon}</span>
|
|
<span
|
|
className="text-sm whitespace-nowrap transition-opacity duration-100"
|
|
style={{ opacity: expanded ? 1 : 0, pointerEvents: expanded ? 'auto' : 'none', width: expanded ? 'auto' : 0, overflow: 'hidden' }}
|
|
>
|
|
{item.label}
|
|
</span>
|
|
</button>
|
|
)
|
|
})}
|
|
</nav>
|
|
</div>
|
|
)
|
|
} |