tangled
alpha
login
or
join now
byarielm.fyi
/
atlast
16
fork
atom
ATlast — you'll never need to find your favorites on another platform again. Find your favs in the ATmosphere.
atproto
16
fork
atom
overview
issues
1
pulls
pipelines
fixed menu behind dashboard
byarielm.fyi
3 months ago
93ab88b2
7c90d1db
1/1
deploy.yml
success
2s
+79
-51
2 changed files
expand all
collapse all
unified
split
src
components
AppHeader.tsx
SetupWizard.tsx
+76
-48
src/components/AppHeader.tsx
···
1
1
import { useState, useEffect, useRef } from "react";
2
2
+
import { createPortal } from "react-dom";
2
3
import { Heart, Home, LogOut, ChevronDown } from "lucide-react";
3
4
import ThemeControls from "./ThemeControls";
4
5
import FireflyLogo from "../assets/at-firefly-logo.svg?react";
···
33
34
onToggleMotion,
34
35
}: AppHeaderProps) {
35
36
const [showMenu, setShowMenu] = useState(false);
37
37
+
const [menuPosition, setMenuPosition] = useState({ top: 0, right: 0 });
36
38
const menuRef = useRef<HTMLDivElement>(null);
39
39
+
const buttonRef = useRef<HTMLButtonElement>(null);
37
40
38
41
useEffect(() => {
39
42
function handleClickOutside(event: MouseEvent) {
40
40
-
if (menuRef.current && !menuRef.current.contains(event.target as Node)) {
43
43
+
if (
44
44
+
menuRef.current &&
45
45
+
!menuRef.current.contains(event.target as Node) &&
46
46
+
buttonRef.current &&
47
47
+
!buttonRef.current.contains(event.target as Node)
48
48
+
) {
41
49
setShowMenu(false);
42
50
}
43
51
}
···
45
53
return () => document.removeEventListener("mousedown", handleClickOutside);
46
54
}, []);
47
55
56
56
+
useEffect(() => {
57
57
+
if (showMenu && buttonRef.current) {
58
58
+
const rect = buttonRef.current.getBoundingClientRect();
59
59
+
setMenuPosition({
60
60
+
top: rect.bottom + 8,
61
61
+
right: window.innerWidth - rect.right,
62
62
+
});
63
63
+
}
64
64
+
}, [showMenu]);
65
65
+
48
66
return (
49
49
-
<div className="bg-white dark:bg-slate-900 border-b-2 border-cyan-500/30 dark:border-purple-500/30 backdrop-blur-xl relative z-[100]">
67
67
+
<div className="bg-white dark:bg-slate-900 border-b-2 border-cyan-500/30 dark:border-purple-500/30 backdrop-blur-xl relative z-50">
50
68
<div className="max-w-6xl mx-auto px-4 py-1">
51
69
<div className="flex items-center justify-between">
52
70
<button
···
69
87
/>
70
88
)}
71
89
{session && (
72
72
-
<div className="relative z-[9999]" ref={menuRef}>
90
90
+
<>
73
91
<button
92
92
+
ref={buttonRef}
74
93
onClick={() => setShowMenu(!showMenu)}
75
94
className="flex items-center space-x-3 px-3 py-1 rounded-lg hover:bg-purple-50 dark:hover:bg-slate-800 transition-colors focus:outline-none focus:ring-2 focus:ring-orange-500 dark:focus:ring-amber-400"
76
95
>
···
95
114
/>
96
115
</button>
97
116
98
98
-
{showMenu && (
99
99
-
<div className="absolute right-0 mt-2 w-64 bg-white dark:bg-slate-900 rounded-lg shadow-lg border-2 border-cyan-500/30 dark:border-purple-500/30 py-2 z-[9999]">
100
100
-
<div className="px-4 py-3">
101
101
-
<div className="font-semibold text-purple-950 dark:text-cyan-50">
102
102
-
{session?.displayName || session.handle}
103
103
-
</div>
104
104
-
<div className="text-sm text-purple-750 dark:text-cyan-250">
105
105
-
@{session?.handle}
106
106
-
</div>
107
107
-
</div>
108
108
-
<button
109
109
-
onClick={() => {
110
110
-
setShowMenu(false);
111
111
-
onNavigate("home");
112
112
-
}}
113
113
-
className="w-full flex items-center space-x-3 px-4 py-2 hover:bg-purple-50 dark:hover:bg-slate-800 transition-colors text-left"
114
114
-
>
115
115
-
<Home className="w-4 h-4 text-purple-950 dark:text-cyan-50" />
116
116
-
<span className="text-purple-950 dark:text-cyan-50">
117
117
-
Dashboard
118
118
-
</span>
119
119
-
</button>
120
120
-
<button
121
121
-
onClick={() => {
122
122
-
setShowMenu(false);
123
123
-
onNavigate("login");
124
124
-
}}
125
125
-
className="w-full flex items-center space-x-3 px-4 py-2 hover:bg-purple-50 dark:hover:bg-slate-800 transition-colors text-left"
126
126
-
>
127
127
-
<Heart className="w-4 h-4 text-purple-950 dark:text-cyan-50" />
128
128
-
<span className="text-purple-950 dark:text-cyan-50">
129
129
-
Login screen
130
130
-
</span>
131
131
-
</button>
132
132
-
<button
133
133
-
onClick={() => {
134
134
-
setShowMenu(false);
135
135
-
onLogout();
117
117
+
{showMenu &&
118
118
+
createPortal(
119
119
+
<div
120
120
+
ref={menuRef}
121
121
+
className="fixed w-64 bg-white dark:bg-slate-900 rounded-lg shadow-2xl border-2 border-cyan-500/30 dark:border-purple-500/30 py-2 z-[9999]"
122
122
+
style={{
123
123
+
top: `${menuPosition.top}px`,
124
124
+
right: `${menuPosition.right}px`,
136
125
}}
137
137
-
className="w-full flex items-center space-x-3 px-4 py-2 hover:bg-red-50 dark:hover:bg-red-900/20 transition-colors text-left text-red-600 dark:text-red-400"
138
126
>
139
139
-
<LogOut className="w-4 h-4" />
140
140
-
<span>Log out</span>
141
141
-
</button>
142
142
-
</div>
143
143
-
)}
144
144
-
</div>
127
127
+
<div className="px-4 py-3">
128
128
+
<div className="font-semibold text-purple-950 dark:text-cyan-50">
129
129
+
{session?.displayName || session.handle}
130
130
+
</div>
131
131
+
<div className="text-sm text-purple-750 dark:text-cyan-250">
132
132
+
@{session?.handle}
133
133
+
</div>
134
134
+
</div>
135
135
+
<button
136
136
+
onClick={() => {
137
137
+
setShowMenu(false);
138
138
+
onNavigate("home");
139
139
+
}}
140
140
+
className="w-full flex items-center space-x-3 px-4 py-2 hover:bg-purple-50 dark:hover:bg-slate-800 transition-colors text-left"
141
141
+
>
142
142
+
<Home className="w-4 h-4 text-purple-950 dark:text-cyan-50" />
143
143
+
<span className="text-purple-950 dark:text-cyan-50">
144
144
+
Dashboard
145
145
+
</span>
146
146
+
</button>
147
147
+
<button
148
148
+
onClick={() => {
149
149
+
setShowMenu(false);
150
150
+
onNavigate("login");
151
151
+
}}
152
152
+
className="w-full flex items-center space-x-3 px-4 py-2 hover:bg-purple-50 dark:hover:bg-slate-800 transition-colors text-left"
153
153
+
>
154
154
+
<Heart className="w-4 h-4 text-purple-950 dark:text-cyan-50" />
155
155
+
<span className="text-purple-950 dark:text-cyan-50">
156
156
+
Login screen
157
157
+
</span>
158
158
+
</button>
159
159
+
<button
160
160
+
onClick={() => {
161
161
+
setShowMenu(false);
162
162
+
onLogout();
163
163
+
}}
164
164
+
className="w-full flex items-center space-x-3 px-4 py-2 hover:bg-red-50 dark:hover:bg-red-900/20 transition-colors text-left text-red-600 dark:text-red-400"
165
165
+
>
166
166
+
<LogOut className="w-4 h-4" />
167
167
+
<span>Log out</span>
168
168
+
</button>
169
169
+
</div>,
170
170
+
document.body,
171
171
+
)}
172
172
+
</>
145
173
)}
146
174
</div>
147
175
</div>
+3
-3
src/components/SetupWizard.tsx
···
281
281
onChange={(e) =>
282
282
setAutomationFrequency(
283
283
e.target.value as
284
284
-
| "weekly"
285
285
-
| "monthly"
286
286
-
| "quarterly",
284
284
+
| "Weekly"
285
285
+
| "Monthly"
286
286
+
| "Quarterly",
287
287
)
288
288
}
289
289
className="mt-2 px-3 py-2 bg-white dark:bg-slate-800 border border-cyan-500/30 dark:border-purple-500/30 rounded-lg text-sm w-full text-purple-950 dark:text-cyan-50 hover:border-cyan-400 dark:hover:border-purple-400 focus:outline-none focus:ring-2 focus:ring-orange-500 dark:focus:ring-amber-400 transition-colors"