-
Notifications
You must be signed in to change notification settings - Fork 2
Expand file tree
/
Copy pathuseScrollableTabs.ts
More file actions
81 lines (67 loc) · 2.11 KB
/
useScrollableTabs.ts
File metadata and controls
81 lines (67 loc) · 2.11 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
import { useEffect, useRef, useState } from "react";
const HEADER_HEIGHT = 56;
const TAB_BAR_HEIGHT = 46;
export function useScrollableTabs() {
const productInfoRef = useRef<HTMLDivElement>(null);
const reviewRef = useRef<HTMLDivElement>(null);
const recommendRef = useRef<HTMLDivElement>(null);
const [activeTab, setActiveTab] = useState<
"product-info" | "review" | "recommend"
>("product-info");
// IntersectionObserver로 현재 섹션 감지
useEffect(() => {
const observerOptions = {
// 섹션이 화면의 중앙 즈음에 올 때
rootMargin: `-${window.innerHeight / 2}px 0px -${window.innerHeight / 2}px 0px`,
threshold: 0,
};
const observerCallback = (entries: IntersectionObserverEntry[]) => {
entries.forEach((entry) => {
if (entry.isIntersecting) {
const sectionId = entry.target.getAttribute("data-section") as
| "product-info"
| "review"
| "recommend";
if (sectionId) {
setActiveTab(sectionId);
}
}
});
};
const sectionObserver = new IntersectionObserver(
observerCallback,
observerOptions
);
// 각 섹션 관찰 시작
if (productInfoRef.current) sectionObserver.observe(productInfoRef.current);
if (reviewRef.current) sectionObserver.observe(reviewRef.current);
if (recommendRef.current) sectionObserver.observe(recommendRef.current);
return () => {
sectionObserver.disconnect();
};
}, []);
// 탭 클릭 시 해당 섹션으로 스크롤
const handleTabClick = (tab: "product-info" | "review" | "recommend") => {
const sectionRefMap = {
"product-info": productInfoRef,
review: reviewRef,
recommend: recommendRef,
};
const targetRef = sectionRefMap[tab];
if (targetRef.current) {
const offsetTop =
targetRef.current.offsetTop - HEADER_HEIGHT - TAB_BAR_HEIGHT;
window.scrollTo({
top: offsetTop,
behavior: "smooth",
});
}
};
return {
productInfoRef,
reviewRef,
recommendRef,
activeTab,
handleTabClick,
};
}