@@ -2,7 +2,6 @@ import { useGetContents } from '@/services/hooks/content/get-content.hook'
22import { useRef , useState , useEffect } from 'react'
33import Analytics from '@/analytics'
44import { getFaviconFromUrl } from '@/common/utils/icon'
5- import { HiOutlineLightBulb } from 'react-icons/hi2'
65
76interface LinkItem {
87 name : string
@@ -27,10 +26,12 @@ export function ExplorerContent() {
2726 const scrollContainerRef = useRef < HTMLDivElement > ( null )
2827
2928 useEffect ( ( ) => {
29+ if ( ! catalogData ?. contents || ! scrollContainerRef . current ) return
30+
3031 const observerOptions = {
3132 root : scrollContainerRef . current ,
32- rootMargin : '-10% 0px -80 % 0px' ,
33- threshold : 0 ,
33+ rootMargin : '0px 0px -40 % 0px' ,
34+ threshold : 0.1 ,
3435 }
3536
3637 const observerCallback = ( entries : IntersectionObserverEntry [ ] ) => {
@@ -42,43 +43,48 @@ export function ExplorerContent() {
4243 }
4344
4445 const observer = new IntersectionObserver ( observerCallback , observerOptions )
45- Object . values ( categoryRefs . current ) . forEach ( ( div ) => {
46+
47+ const currentRefs = categoryRefs . current
48+ Object . values ( currentRefs ) . forEach ( ( div ) => {
4649 if ( div ) observer . observe ( div )
4750 } )
51+
4852 return ( ) => observer . disconnect ( )
49- } , [ catalogData ] )
53+ } , [ catalogData ?. contents ] )
5054
5155 const scrollToCategory = ( id : string ) => {
5256 setActiveCategory ( id )
53- categoryRefs . current [ id ] ?. scrollIntoView ( {
54- behavior : 'smooth' ,
55- block : 'start' ,
56- } )
57+ const element = categoryRefs . current [ id ]
58+ if ( element ) {
59+ element . scrollIntoView ( {
60+ behavior : 'smooth' ,
61+ block : 'start' ,
62+ } )
63+ }
5764 Analytics . event ( 'explorer_click_category' )
5865 }
5966
6067 return (
6168 < div className = "flex flex-row w-full h-screen overflow-hidden" >
62- < aside className = "flex-col items-center hidden w-24 gap-3 py-2 md:flex border-base-300 bg-content bg-glass lg:mt-3 rounded-t-2xl rounded-b-2xl h-[calc(100vh-10rem)] " >
63- < div className = "flex flex-col items-center w-full gap-3 px-2 overflow-x-hidden overflow-y-auto scrollbar-none" >
69+ < aside className = "flex-col items-center hidden w-20 gap-3 py-4 md:flex bg-white/[0.02] backdrop-blur-sm border border-white/[0.08] rounded-[2.5rem] lg:mt-4 h-fit max- h-[calc(100vh-160px)] sticky top-4 " >
70+ < div className = "flex flex-col items-center w-full gap-2 px-2 py -2 overflow-x-hidden overflow-y-auto scrollbar-none" >
6471 { catalogData ?. contents ?. map ( ( cat : CategoryItem ) => (
6572 < button
6673 key = { cat . id }
6774 onClick = { ( ) => scrollToCategory ( cat . id ) }
68- className = { `relative group flex flex-col items-center justify-center w-full py-3 px-2 rounded-2xl transition-all duration-300 cursor-pointer ${
75+ className = { `relative group flex flex-col items-center justify-center w-14 min-h-14 max-h-14 rounded-[1.5rem] transition-all duration-500 cursor-pointer border ${
6976 activeCategory === cat . id
70- ? 'bg-primary/80 text-white shadow-sm shadow-primary/20 '
71- : 'bg-base-200 /60 hover:bg-base-300 text-base-content/70 hover:scale-102 '
77+ ? 'bg-primary text-white shadow-md shadow-primary/40 scale-110 border-primary/50 '
78+ : 'bg-white/[0.03] border-white/5 text- base-content /60 hover:bg-primary/10 hover: text-primary hover:scale-105 hover:border-primary/30 '
7279 } `}
7380 >
74- { activeCategory === cat . id && (
75- < div className = "absolute w-1 h-10 rounded-r-full -left-2 bg-primary" />
76- ) }
77-
81+ < div
82+ className = { `absolute w-1 h-8 rounded-r-full -left-2 bg-primary transition-all duration-500 ${ activeCategory === cat . id ? 'opacity-100 scale-y-100' : 'opacity-0 scale-y-0' } ` }
83+ />
7884 { cat . icon ? (
7985 < img
8086 src = { cat . icon }
81- className = { `w-8 h-8 mb-2 object-contain transition-transform ${
87+ className = { `w-7 h-7 object-contain transition-transform ${
8288 activeCategory === cat . id
8389 ? 'scale-110'
8490 : 'opacity-70 group-hover:opacity-100'
@@ -87,7 +93,7 @@ export function ExplorerContent() {
8793 />
8894 ) : (
8995 < div
90- className = { `w-8 h-8 mb-2 rounded-xl flex items-center justify-center text-lg font-bold transition-all ${
96+ className = { `w-7 h-7 rounded-xl flex items-center justify-center text-sm font-bold transition-all ${
9197 activeCategory === cat . id
9298 ? 'bg-white/20'
9399 : 'bg-base-content/10 group-hover:bg-base-content/20'
@@ -96,17 +102,6 @@ export function ExplorerContent() {
96102 { cat . category . substring ( 0 , 1 ) }
97103 </ div >
98104 ) }
99-
100- < span
101- className = { `text-[9px] font-bold text-center leading-tight transition-all line-clamp-2 ${
102- activeCategory === cat . id
103- ? 'opacity-100'
104- : 'opacity-60 group-hover:opacity-90'
105- } `}
106- >
107- { cat . category }
108- </ span >
109-
110105 < div className = "absolute z-50 px-3 py-2 ml-4 text-xs font-semibold transition-opacity rounded-lg shadow-xl opacity-0 pointer-events-none left-full bg-neutral text-neutral-content group-hover:opacity-100 whitespace-nowrap" >
111106 { cat . category }
112107 < div className = "absolute -translate-y-1/2 border-4 border-transparent right-full top-1/2 border-r-neutral" />
@@ -116,16 +111,16 @@ export function ExplorerContent() {
116111 </ div >
117112 </ aside >
118113
119- < div className = "flex flex-col flex-1 w-full h-full gap-3 px-2 py-3 overflow-hidden md:px-6 " >
114+ < div className = "flex flex-col w-full h-full gap-3 px-2 py-3 overflow-hidden md:px-24 " >
120115 < div className = "md:hidden sticky top-0 z-50 flex items-center w-full gap-2 p-1.5 overflow-x-auto bg-base-100/80 backdrop-blur-xl rounded-2xl border border-white/10 shadow-lg no-scrollbar flex-nowrap" >
121116 { catalogData ?. contents ?. map ( ( cat : CategoryItem ) => (
122117 < button
123118 key = { cat . id }
124119 onClick = { ( ) => scrollToCategory ( cat . id ) }
125120 className = { `flex items-center gap-2 px-4 py-2 text-[10px] font-bold whitespace-nowrap rounded-xl transition-all shrink-0 ${
126121 activeCategory === cat . id
127- ? 'bg-primary text-white shadow-md'
128- : 'bg-base-200/50'
122+ ? 'bg-primary text-white shadow-md scale-105 '
123+ : 'bg-base-200/50 hover:bg-primary/10 hover:text-primary '
129124 } `}
130125 >
131126 { cat . icon && (
@@ -136,13 +131,13 @@ export function ExplorerContent() {
136131 ) ) }
137132 </ div >
138133
139- < div className = "grid w-full h-full grid-cols-1 gap-6 overflow-hidden lg:grid-cols-12 " >
140- < div className = "flex flex-col h-full gap-4 overflow-hidden lg:col-span-8 " >
134+ < div className = "grid w-full h-full grid-cols-1 gap-6 overflow-hidden lg:grid-cols-1 " >
135+ < div className = "flex flex-col h-full gap-4 overflow-hidden lg:col-span-1 " >
141136 < div
142137 ref = { scrollContainerRef }
143138 className = "flex-1 pb-10 pr-1 overflow-y-auto scrollbar-none scroll-smooth"
144139 >
145- < div className = "grid grid-cols-1 gap-4 pb-10 md:grid-cols-2" >
140+ < div className = "grid max-w-5xl grid-cols-1 gap-4 pb-[50vh] mx-auto md:grid-cols-2" >
146141 { catalogData ?. contents ?. map (
147142 ( category : CategoryItem , index : number ) => (
148143 < div
@@ -151,10 +146,21 @@ export function ExplorerContent() {
151146 ref = { ( el ) => {
152147 categoryRefs . current [ category . id ] = el
153148 } }
154- className = { `relative overflow-hidden border scroll-mt-2 bg-content bg-glass border-base-300 rounded-3xl transition-all duration-300 ${
155- index % 3 === 0
156- ? 'md:col-span-2'
157- : 'md:col-span-1'
149+ className = { `relative overflow-hidden border scroll-mt-4 bg-content bg-glass border-base-300 rounded-3xl transition-all duration-300 ${
150+ index === 0
151+ ? 'md:col-span-2' // آیتم اول همیشه تمام عرض
152+ : (
153+ index ===
154+ catalogData . contents
155+ . length -
156+ 1 &&
157+ catalogData . contents
158+ . length %
159+ 2 ===
160+ 0
161+ )
162+ ? 'md:col-span-2' // اگر تعداد کل زوج بود (مثل ۶ تا)، آخری تمام عرض شود تا جای خالی پر شود
163+ : 'md:col-span-1'
158164 } `}
159165 >
160166 { category . banner && (
@@ -172,7 +178,6 @@ export function ExplorerContent() {
172178 />
173179 </ div >
174180 ) }
175-
176181 < div className = "p-5" >
177182 < div className = "flex items-center gap-4 mb-6" >
178183 < div className = "flex items-center gap-2.5" >
@@ -191,13 +196,8 @@ export function ExplorerContent() {
191196 </ div >
192197 < div className = "flex-1 h-px bg-linear-to-r from-base-content/10 to-transparent" />
193198 </ div >
194-
195199 < div
196- className = { `grid gap-y-6 gap-x-2 ${
197- index % 3 === 0
198- ? 'grid-cols-4 sm:grid-cols-6 lg:grid-cols-8'
199- : 'grid-cols-3 sm:grid-cols-4'
200- } `}
200+ className = { `grid gap-y-6 gap-x-2 grid-cols-3 sm:grid-cols-5` }
201201 >
202202 { category . links ?. map ( ( link , idx ) => (
203203 < a
@@ -207,10 +207,10 @@ export function ExplorerContent() {
207207 rel = "noopener noreferrer"
208208 className = "flex flex-col items-center gap-3 group/item active:scale-95"
209209 >
210- < div className = "relative flex items-center justify-center w-12 h-12 transition-all duration-300 bg-base-200/40 rounded-2xl group-hover/item:bg-primary/10 " >
210+ < div className = "relative flex items-center justify-center w-12 h-12 transition-all duration-500 bg-base-200/40 rounded-2xl group-hover/item:bg-primary/20 group-hover/item:shadow-lg group-hover/item:shadow-primary/20 group-hover/item:-translate-y-1.5 border border-transparent group-hover/item:border-primary/20 " >
211211 { link . badge && (
212212 < span
213- className = "absolute -top-1 -right-1 z-20 px-1.5 py-0.5 rounded-lg text-[8px] font-black border border-white/10"
213+ className = "absolute -top-1 -right-1 z-20 px-1.5 py-0.5 rounded-lg text-[8px] font-black border border-white/10 shadow-sm "
214214 style = { {
215215 backgroundColor :
216216 link . badgeColor ||
@@ -228,11 +228,11 @@ export function ExplorerContent() {
228228 link . url
229229 )
230230 }
231- className = "object-contain w-6 h-6 transition-transform rounded group-hover/item:scale-110"
231+ className = "object-contain w-6 h-6 transition-all duration-500 rounded group-hover/item:scale-110 group-hover/item:brightness -110"
232232 alt = { link . name }
233233 />
234234 </ div >
235- < span className = "text-[10px] font-medium tracking-tighter text-center truncate w-full opacity-50 group-hover/item:opacity-100 transition-opacity " >
235+ < span className = "text-[10px] font-semibold tracking-tighter text-center truncate w-full opacity-40 group-hover/item:opacity-100 group-hover/item:text-primary transition-all duration-300 " >
236236 { link . name }
237237 </ span >
238238 </ a >
@@ -245,33 +245,6 @@ export function ExplorerContent() {
245245 </ div >
246246 </ div >
247247 </ div >
248- < div className = "hidden h-full pb-4 space-y-4 overflow-y-auto lg:block lg:col-span-4 scrollbar-none" >
249- < div className = "sticky top-0 flex flex-col gap-4" >
250- < a
251- href = "https://feedback.widgetify.ir"
252- target = "_blank"
253- rel = "noopener noreferrer"
254- className = "relative flex flex-col items-center justify-center p-5 overflow-hidden text-center transition-all duration-500 border border-dashed group bg-content bg-glass border-base-300 rounded-3xl hover:border-primary/50 hover:bg-primary/5 min-h-20"
255- >
256- < div className = "p-3 mb-3 transition-all duration-500 rounded-2xl bg-base-200/50 text-base-content/40 group-hover:scale-110 group-hover:rotate-12 group-hover:text-warning group-hover:bg-warning/10" >
257- < HiOutlineLightBulb
258- size = { 28 }
259- className = "transition-transform duration-500"
260- />
261- </ div >
262-
263- < h3 className = "font-bold tracking-tight transition-colors duration-300 text-muted group-hover:text-primary" >
264- چیزی جا انداختیم؟
265- </ h3 >
266-
267- < p className = "mt-1 text-[10px] font-medium opacity-40 transition-opacity duration-300 group-hover:opacity-100" >
268- بهمون بگو تا اضافهاش کنیم
269- </ p >
270-
271- < div className = "absolute bottom-0 left-1/2 -translate-x-1/2 w-0 h-0.5 bg-primary/30 transition-all duration-500 group-hover:w-1/3" />
272- </ a >
273- </ div >
274- </ div >
275248 </ div >
276249 </ div >
277250 </ div >
0 commit comments