终端左侧新增可收缩导航面板:折叠/展开切换,中英文标签
Menu 按钮切换展开/收起,52px 折叠态图标栏 → 172px 展开态带标签面板。6 个导航入口:天气合约、交易信号、分析图表、自选监控、实时预警、市场概览。
This commit is contained in:
@@ -7,6 +7,7 @@ import {
|
|||||||
BarChart3,
|
BarChart3,
|
||||||
Bell,
|
Bell,
|
||||||
ChevronDown,
|
ChevronDown,
|
||||||
|
ChevronLeft,
|
||||||
ChevronRight,
|
ChevronRight,
|
||||||
CloudSun,
|
CloudSun,
|
||||||
CreditCard,
|
CreditCard,
|
||||||
@@ -354,6 +355,18 @@ function PolyWeatherTerminal({
|
|||||||
.slice(0, 8);
|
.slice(0, 8);
|
||||||
const selectedSignal = selectedRow ? getSignalState(selectedRow) : "data" as const;
|
const selectedSignal = selectedRow ? getSignalState(selectedRow) : "data" as const;
|
||||||
const selectedLabel = selectedRow ? getSignalLabel(selectedSignal, isEn) : "";
|
const selectedLabel = selectedRow ? getSignalLabel(selectedSignal, isEn) : "";
|
||||||
|
const [navExpanded, setNavExpanded] = useState(false);
|
||||||
|
const [activeNavKey, setActiveNavKey] = useState<string>("contracts");
|
||||||
|
|
||||||
|
const NAV_ITEMS = [
|
||||||
|
{ key: "contracts", Icon: Table2, labelEn: "Contracts", labelZh: "天气合约" },
|
||||||
|
{ key: "signals", Icon: LineChart, labelEn: "Signals", labelZh: "交易信号" },
|
||||||
|
{ key: "analytics", Icon: BarChart3, labelEn: "Analytics", labelZh: "分析图表" },
|
||||||
|
{ key: "watchlist", Icon: Gauge, labelEn: "Watchlist", labelZh: "自选监控" },
|
||||||
|
{ key: "alerts", Icon: Bell, labelEn: "Alerts", labelZh: "实时预警" },
|
||||||
|
{ key: "markets", Icon: Activity, labelEn: "Markets", labelZh: "市场概览" },
|
||||||
|
];
|
||||||
|
|
||||||
const continentGroups = useMemo(
|
const continentGroups = useMemo(
|
||||||
() => buildContinentGroups(rows, isEn),
|
() => buildContinentGroups(rows, isEn),
|
||||||
[rows, isEn]
|
[rows, isEn]
|
||||||
@@ -379,29 +392,86 @@ function PolyWeatherTerminal({
|
|||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="flex h-screen w-full overflow-hidden bg-[#e9edf3] text-[#202833]">
|
<div className="flex h-screen w-full overflow-hidden bg-[#e9edf3] text-[#202833]">
|
||||||
<aside className="flex w-[52px] shrink-0 flex-col items-center gap-2 bg-[#11161d] py-3 text-slate-400">
|
<aside
|
||||||
<Link
|
className={clsx(
|
||||||
href="/"
|
"flex shrink-0 flex-col bg-[#11161d] py-3 text-slate-400 transition-all duration-200",
|
||||||
className="mb-2 block h-7 w-7 overflow-hidden rounded transition hover:opacity-90"
|
navExpanded ? "w-[172px] items-start px-3" : "w-[52px] items-center gap-2",
|
||||||
title="PolyWeather"
|
)}
|
||||||
>
|
>
|
||||||
<img src="/apple-touch-icon.png" alt="PolyWeather" className="h-full w-full object-cover" />
|
{/* Logo row */}
|
||||||
</Link>
|
<div className={clsx(
|
||||||
<Menu size={20} className="mb-2 hover:text-white cursor-pointer" />
|
"flex items-center w-full",
|
||||||
{[CloudSun, Table2, BarChart3, LineChart, Gauge, Bell].map((Icon, i) => (
|
navExpanded ? "gap-3 mb-3 px-1" : "justify-center mb-2",
|
||||||
<button
|
)}>
|
||||||
key={i}
|
<Link
|
||||||
className={clsx(
|
href="/"
|
||||||
"grid h-9 w-full place-items-center border-l-4 transition-colors",
|
className="block h-7 w-7 shrink-0 overflow-hidden rounded transition hover:opacity-90"
|
||||||
i === 0
|
title="PolyWeather"
|
||||||
? "border-blue-500 bg-white/5 text-white"
|
|
||||||
: "border-transparent hover:bg-white/5 hover:text-white",
|
|
||||||
)}
|
|
||||||
type="button"
|
|
||||||
>
|
>
|
||||||
<Icon size={16} />
|
<img src="/apple-touch-icon.png" alt="PolyWeather" className="h-full w-full object-cover" />
|
||||||
</button>
|
</Link>
|
||||||
))}
|
{navExpanded && (
|
||||||
|
<span className="text-sm font-black text-white tracking-tight truncate">
|
||||||
|
PolyWeather
|
||||||
|
</span>
|
||||||
|
)}
|
||||||
|
</div>
|
||||||
|
|
||||||
|
{/* Toggle button */}
|
||||||
|
<button
|
||||||
|
type="button"
|
||||||
|
onClick={() => setNavExpanded((prev) => !prev)}
|
||||||
|
className={clsx(
|
||||||
|
"flex items-center gap-3 transition-colors hover:text-white",
|
||||||
|
navExpanded
|
||||||
|
? "w-full h-8 px-1 mb-2"
|
||||||
|
: "grid h-9 w-full place-items-center mb-2",
|
||||||
|
)}
|
||||||
|
>
|
||||||
|
{navExpanded ? (
|
||||||
|
<>
|
||||||
|
<ChevronLeft size={14} />
|
||||||
|
<span className="text-[11px] font-bold uppercase tracking-wide text-slate-500">
|
||||||
|
{isEn ? "Collapse" : "收起"}
|
||||||
|
</span>
|
||||||
|
</>
|
||||||
|
) : (
|
||||||
|
<Menu size={18} />
|
||||||
|
)}
|
||||||
|
</button>
|
||||||
|
|
||||||
|
{/* Nav items */}
|
||||||
|
{NAV_ITEMS.map(({ key, Icon, labelEn, labelZh }) => {
|
||||||
|
const isActive = activeNavKey === key;
|
||||||
|
return (
|
||||||
|
<button
|
||||||
|
key={key}
|
||||||
|
type="button"
|
||||||
|
onClick={() => { setActiveNavKey(key); }}
|
||||||
|
className={clsx(
|
||||||
|
"flex items-center gap-3 transition-colors rounded",
|
||||||
|
navExpanded
|
||||||
|
? "w-full h-9 px-2 text-left"
|
||||||
|
: "grid h-9 w-full place-items-center border-l-4",
|
||||||
|
isActive
|
||||||
|
? navExpanded
|
||||||
|
? "bg-white/8 text-white"
|
||||||
|
: "border-blue-500 bg-white/5 text-white"
|
||||||
|
: navExpanded
|
||||||
|
? "hover:bg-white/5 hover:text-white"
|
||||||
|
: "border-transparent hover:bg-white/5 hover:text-white",
|
||||||
|
)}
|
||||||
|
title={isEn ? labelEn : labelZh}
|
||||||
|
>
|
||||||
|
<Icon size={16} className="shrink-0" />
|
||||||
|
{navExpanded && (
|
||||||
|
<span className="text-xs font-semibold whitespace-nowrap">
|
||||||
|
{isEn ? labelEn : labelZh}
|
||||||
|
</span>
|
||||||
|
)}
|
||||||
|
</button>
|
||||||
|
);
|
||||||
|
})}
|
||||||
</aside>
|
</aside>
|
||||||
|
|
||||||
<div className="flex min-w-0 flex-1 flex-col">
|
<div className="flex min-w-0 flex-1 flex-col">
|
||||||
|
|||||||
Reference in New Issue
Block a user