Update overview layout

This commit is contained in:
Xin Wang
2026-02-11 14:55:43 +08:00
parent 2ab4075fcd
commit 44ad52669f

View File

@@ -13,8 +13,12 @@ export const DashboardPage: React.FC = () => {
const [selectedAssistantId, setSelectedAssistantId] = useState<string>('all');
const [assistants, setAssistants] = useState<Assistant[]>([]);
const [topRailHeight, setTopRailHeight] = useState(0);
const [isOverviewVisible, setIsOverviewVisible] = useState(true);
const [scrollRootCenterX, setScrollRootCenterX] = useState<number | null>(null);
const scrollRootRef = useRef<HTMLDivElement>(null);
const topRailRef = useRef<HTMLDivElement>(null);
const overviewRef = useRef<HTMLElement>(null);
const workflowRef = useRef<HTMLDivElement>(null);
const aboutRef = useRef<HTMLDivElement>(null);
@@ -56,12 +60,53 @@ export const DashboardPage: React.FC = () => {
};
}, []);
useEffect(() => {
if (!scrollRootRef.current || !overviewRef.current) return;
const observer = new IntersectionObserver(
([entry]) => {
setIsOverviewVisible(entry.isIntersecting);
},
{
root: scrollRootRef.current,
threshold: 0.35,
}
);
observer.observe(overviewRef.current);
return () => observer.disconnect();
}, []);
useEffect(() => {
const updateScrollRootCenter = () => {
if (!scrollRootRef.current) return;
const rect = scrollRootRef.current.getBoundingClientRect();
setScrollRootCenterX(rect.left + rect.width / 2);
};
updateScrollRootCenter();
const observer = new ResizeObserver(() => {
updateScrollRootCenter();
});
if (scrollRootRef.current) {
observer.observe(scrollRootRef.current);
}
window.addEventListener('resize', updateScrollRootCenter);
return () => {
observer.disconnect();
window.removeEventListener('resize', updateScrollRootCenter);
};
}, []);
const scrollToNext = (ref: React.RefObject<HTMLDivElement>) => {
ref.current?.scrollIntoView({ behavior: 'smooth' });
};
return (
<div className="h-[calc(100vh-5rem)] overflow-y-auto snap-y snap-mandatory custom-scrollbar relative scroll-smooth bg-background">
<div ref={scrollRootRef} className="h-[calc(100vh-5rem)] overflow-y-auto snap-y snap-mandatory custom-scrollbar relative scroll-smooth bg-background">
<div ref={topRailRef} className="sticky top-0 z-40 bg-gradient-to-b from-background via-background/95 to-transparent pb-3">
<div className="mx-auto w-full max-w-[1600px] px-6 lg:px-12 pt-3">
<div className="flex justify-end items-center gap-3 rounded-2xl border border-white/10 bg-background/75 px-3 py-2 backdrop-blur-xl shadow-[0_8px_30px_rgba(0,0,0,0.25)]">
@@ -77,6 +122,7 @@ export const DashboardPage: React.FC = () => {
{/* SECTION 1: METRICS & CHARTS */}
<section
ref={overviewRef}
className="min-h-full snap-start flex flex-col pb-4 relative"
style={{ paddingTop: `${topRailHeight + 8}px` }}
>
@@ -212,17 +258,25 @@ export const DashboardPage: React.FC = () => {
</div>
</div>
{/* Scroll Indicator */}
</section>
{/* Scroll Indicator (Overview, fixed to viewport bottom) */}
{isOverviewVisible && (
<div
onClick={() => scrollToNext(workflowRef)}
className="mt-3 mb-1 self-center flex flex-col items-center gap-2 cursor-pointer group animate-bounce-slow opacity-35 hover:opacity-100 transition-all duration-500 hover:scale-110"
className="pointer-events-none fixed bottom-4 z-30 -translate-x-1/2"
style={{ left: scrollRootCenterX ? `${scrollRootCenterX}px` : '50%' }}
>
<span className="text-[10px] font-bold text-primary tracking-[0.3em] uppercase group-hover:tracking-[0.5em] transition-all"></span>
<div className="p-2 rounded-full bg-primary/10 border border-primary/20 backdrop-blur-sm group-hover:bg-primary group-hover:text-black transition-colors">
<ArrowDown className="w-5 h-5" />
<div
onClick={() => scrollToNext(workflowRef)}
className="pointer-events-auto flex flex-col items-center gap-2 cursor-pointer group animate-bounce-slow opacity-45 hover:opacity-100 transition-all duration-500 hover:scale-110"
>
<span className="text-[10px] font-bold text-primary tracking-[0.3em] uppercase group-hover:tracking-[0.5em] transition-all"></span>
<div className="p-2 rounded-full bg-primary/10 border border-primary/20 backdrop-blur-sm group-hover:bg-primary group-hover:text-black transition-colors">
<ArrowDown className="w-5 h-5" />
</div>
</div>
</div>
</section>
)}
{/* SECTION 2: WORKFLOW LOGIC */}
<section
@@ -282,10 +336,12 @@ export const DashboardPage: React.FC = () => {
{/* Scroll Indicator */}
<div
onClick={() => scrollToNext(aboutRef)}
className="absolute bottom-10 left-1/2 -translate-x-1/2 cursor-pointer opacity-30 hover:opacity-100 transition-opacity p-4 flex flex-col items-center gap-2 hover:scale-110 duration-300"
className="absolute bottom-8 left-1/2 -translate-x-1/2 flex flex-col items-center gap-2 cursor-pointer group animate-bounce-slow opacity-45 hover:opacity-100 transition-all duration-500 hover:scale-110"
>
<span className="text-[10px] text-muted-foreground tracking-widest font-bold"></span>
<ArrowDown className="w-6 h-6 text-white animate-bounce" />
<span className="text-[10px] font-bold text-primary tracking-[0.3em] uppercase group-hover:tracking-[0.5em] transition-all"></span>
<div className="p-2 rounded-full bg-primary/10 border border-primary/20 backdrop-blur-sm group-hover:bg-primary group-hover:text-black transition-colors">
<ArrowDown className="w-5 h-5" />
</div>
</div>
</section>