Files
smart-go/web/components/layout/TabStrip.tsx
T
2026-04-23 18:58:13 +08:00

100 lines
3.1 KiB
TypeScript
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
'use client';
import { usePathname, useRouter } from 'next/navigation';
import { useCallback, useEffect, useRef } from 'react';
import { useTabStore } from '@/stores/tab-store';
/** 多页签条:与路由联动;左右滚动占位(后续可接完整滚动实现)。 */
export function TabStrip() {
const router = useRouter();
const pathname = usePathname() ?? '';
const scrollRef = useRef<HTMLDivElement>(null);
const { tabs, activeId, close, activate } = useTabStore();
useEffect(() => {
if (!pathname.startsWith('/dashboard')) {
return;
}
useTabStore.getState().syncFromPath(pathname);
}, [pathname]);
const onTabClick = useCallback(
(id: string, path: string) => {
activate(id);
router.push(path);
},
[activate, router],
);
const scrollBy = (delta: number) => {
scrollRef.current?.scrollBy({ left: delta, behavior: 'smooth' });
};
return (
<div className="flex items-end gap-0 border-b border-neutral-200 bg-white px-1 pb-0 pt-1">
<button
type="button"
className="mb-px shrink-0 cursor-pointer rounded px-1 py-1 text-neutral-500 hover:bg-neutral-100 disabled:opacity-40"
aria-label="页签向左滚动"
onClick={() => scrollBy(-120)}
>
</button>
<div
ref={scrollRef}
role="tablist"
className="flex min-w-0 flex-1 items-end gap-2 overflow-x-auto"
>
{tabs.map((t) => {
const isActive = activeId === t.id;
return (
<button
key={t.id}
type="button"
role="tab"
aria-selected={isActive}
tabIndex={isActive ? 0 : -1}
onClick={() => onTabClick(t.id, t.path)}
className={`flex shrink-0 cursor-pointer items-end gap-1 rounded-t px-3 pb-1.5 pt-2 text-sm ${
isActive
? 'bg-neutral-100 font-medium text-neutral-900'
: 'text-neutral-600'
}`}
>
<span>{t.title}</span>
{!t.pinned ? (
<span
className="cursor-pointer text-neutral-400 hover:text-neutral-700"
onClick={(e) => {
e.stopPropagation();
const next = close(t.id);
if (next) router.push(next);
}}
onKeyDown={(e) => {
if (e.key === 'Enter' || e.key === ' ') {
e.stopPropagation();
e.preventDefault();
const next = close(t.id);
if (next) router.push(next);
}
}}
>
×
</span>
) : null}
</button>
);
})}
</div>
<button
type="button"
className="mb-px shrink-0 cursor-pointer rounded px-1 py-1 text-neutral-500 hover:bg-neutral-100 disabled:opacity-40"
aria-label="页签向右滚动"
onClick={() => scrollBy(120)}
>
</button>
</div>
);
}