MCPcopy Create free account
hub / github.com/Qinbf/groundmap / StepNav

Function StepNav

web/components/learn/StepNav.tsx:15–74  ·  view source on GitHub ↗
({ count, idPrefix = "step" }: StepNavProps)

Source from the content-addressed store, hash-verified

13 * 移动端隐藏(md: 起显示),由 page 顶部进度条作为窄屏降级。
14 */
15export function StepNav({ count, idPrefix = "step" }: StepNavProps) {
16 const t = useT();
17 const [activeId, setActiveId] = useState(1);
18
19 useEffect(() => {
20 const observer = new IntersectionObserver(
21 (entries) => {
22 // 取最靠近视口顶部的可见步骤
23 const visible = entries
24 .filter((e) => e.isIntersecting)
25 .sort((a, b) => a.boundingClientRect.top - b.boundingClientRect.top);
26 if (visible.length > 0) {
27 const target = visible[0]!;
28 const id = parseInt(target.target.id.replace(`${idPrefix}-`, ""), 10);
29 if (!isNaN(id)) setActiveId(id);
30 }
31 },
32 // rootMargin: 顶部 -25% 让"当前步"出现得更准
33 { rootMargin: "-20% 0px -60% 0px", threshold: 0 },
34 );
35
36 for (let i = 1; i <= count; i++) {
37 const el = document.getElementById(`${idPrefix}-${i}`);
38 if (el) observer.observe(el);
39 }
40 return () => observer.disconnect();
41 }, [count, idPrefix]);
42
43 const handleClick = (id: number) => {
44 const el = document.getElementById(`${idPrefix}-${id}`);
45 if (el) el.scrollIntoView({ behavior: "smooth", block: "start" });
46 };
47
48 return (
49 <nav
50 aria-label={t("learn.scrollnav.label")}
51 className="hidden md:flex flex-col gap-1.5"
52 >
53 {Array.from({ length: count }, (_, i) => i + 1).map((id) => {
54 const isActive = id === activeId;
55 return (
56 <button
57 key={id}
58 type="button"
59 onClick={() => handleClick(id)}
60 aria-label={t("learn.scrollnav.aria", { n: id })}
61 className={
62 "h-8 w-8 rounded-full flex items-center justify-center text-xs font-mono border transition-all " +
63 (isActive
64 ? "bg-foreground text-background border-foreground scale-110"
65 : "bg-card text-muted-foreground border-border hover:border-foreground/50 hover:text-foreground")
66 }
67 >
68 {id}
69 </button>
70 );
71 })}
72 </nav>

Callers

nothing calls this directly

Calls 3

useTFunction · 0.90
handleClickFunction · 0.70
tFunction · 0.50

Tested by

no test coverage detected