tangled
alpha
login
or
join now
whey.party
/
red-dwarf
82
fork
atom
an independent Bluesky client using Constellation, PDS Queries, and other services
reddwarf.app
frontend
spa
bluesky
reddwarf
microcosm
client
app
82
fork
atom
overview
issues
25
pulls
pipelines
(unused) experimental sticky
whey.party
3 weeks ago
4d052c4d
272453f8
+52
-21
1 changed file
expand all
collapse all
unified
split
src
components
ReusableTabRoute.tsx
+52
-21
src/components/ReusableTabRoute.tsx
···
1
1
import * as TabsPrimitive from "@radix-ui/react-tabs";
2
2
import { useAtom } from "jotai";
3
3
-
import { useEffect, useLayoutEffect } from "react";
3
3
+
import { useEffect, useLayoutEffect, useRef, useState } from "react";
4
4
5
5
import { isAtTopAtom, reusableTabRouteScrollAtom } from "~/utils/atoms";
6
6
···
70
70
// eslint-disable-next-line react-hooks/exhaustive-deps
71
71
}, []);
72
72
73
73
+
//const { sentinelRef, isStuck } = useSticky(52);
74
74
+
//bg-gray-100 dark:bg-gray-900
75
75
+
73
76
return (
74
74
-
<TabsPrimitive.Root
75
75
-
value={activeTab}
76
76
-
onValueChange={handleValueChange}
77
77
-
className={`w-full`}
78
78
-
>
79
79
-
<TabsPrimitive.List
80
80
-
className={`flex sticky top-[52px] bg-[var(--header-bg-light)] dark:bg-[var(--header-bg-dark)] z-[9] border-0 sm:border-b ${!isAtTop && "shadow-sm"} sm:shadow-none sm:dark:bg-gray-950 sm:bg-white border-gray-200 dark:border-gray-700`}
77
77
+
<>
78
78
+
<TabsPrimitive.Root
79
79
+
value={activeTab}
80
80
+
onValueChange={handleValueChange}
81
81
+
className={`w-full`}
81
82
>
82
82
-
{Object.entries(tabs).map(([key]) => (
83
83
-
<TabsPrimitive.Trigger key={key} value={key} className="m3tab">
84
84
-
{key}
85
85
-
</TabsPrimitive.Trigger>
83
83
+
{/* <div ref={sentinelRef} className="h-[0.000000001px]" /> */}
84
84
+
<TabsPrimitive.List
85
85
+
className={`flex sticky top-[52px] bg-[var(--header-bg-light)] dark:bg-[var(--header-bg-dark)] sm:dark:bg-gray-950 sm:bg-white z-[9] border-0 sm:border-b ${!isAtTop && "shadow-sm"} sm:shadow-none border-gray-200 dark:border-gray-700`}
86
86
+
>
87
87
+
{Object.entries(tabs).map(([key]) => (
88
88
+
<TabsPrimitive.Trigger key={key} value={key} className="m3tab">
89
89
+
{key}
90
90
+
</TabsPrimitive.Trigger>
91
91
+
))}
92
92
+
</TabsPrimitive.List>
93
93
+
94
94
+
{Object.entries(tabs).map(([key, node]) => (
95
95
+
<TabsPrimitive.Content key={key} value={key} className="flex-1 min-h-[80dvh]">
96
96
+
{activeTab === key && node}
97
97
+
</TabsPrimitive.Content>
86
98
))}
87
87
-
</TabsPrimitive.List>
88
88
-
89
89
-
{Object.entries(tabs).map(([key, node]) => (
90
90
-
<TabsPrimitive.Content key={key} value={key} className="flex-1 min-h-[80dvh]">
91
91
-
{activeTab === key && node}
92
92
-
</TabsPrimitive.Content>
93
93
-
))}
94
94
-
</TabsPrimitive.Root>
99
99
+
</TabsPrimitive.Root>
100
100
+
</>
101
101
+
95
102
);
96
103
}
97
104
···
121
128
window.scrollTo(0, savedY);
122
129
}, [activeTab, notifState.scrollPositions]);
123
130
124
124
-
*/
131
131
+
*/
132
132
+
133
133
+
134
134
+
135
135
+
export function useSticky(top: number = 0) {
136
136
+
const sentinelRef = useRef<HTMLDivElement | null>(null);
137
137
+
const [isStuck, setIsStuck] = useState(false);
138
138
+
139
139
+
useEffect(() => {
140
140
+
if (!sentinelRef.current) return;
141
141
+
142
142
+
const observer = new IntersectionObserver(
143
143
+
([entry]) => setIsStuck(!entry.isIntersecting),
144
144
+
{
145
145
+
rootMargin: `-${top}px 0px 0px 0px`,
146
146
+
threshold: 0,
147
147
+
}
148
148
+
);
149
149
+
150
150
+
observer.observe(sentinelRef.current);
151
151
+
return () => observer.disconnect();
152
152
+
}, [top]);
153
153
+
154
154
+
return { sentinelRef, isStuck };
155
155
+
}