ATlast — you'll never need to find your favorites on another platform again. Find your favs in the ATmosphere.
atproto
17
fork

Configure Feed

Select the types of activity you want to include in your feed.

fixed menu behind dashboard

+79 -51
+76 -48
src/components/AppHeader.tsx
··· 1 1 import { useState, useEffect, useRef } from "react"; 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 + const [menuPosition, setMenuPosition] = useState({ top: 0, right: 0 }); 36 38 const menuRef = useRef<HTMLDivElement>(null); 39 + const buttonRef = useRef<HTMLButtonElement>(null); 37 40 38 41 useEffect(() => { 39 42 function handleClickOutside(event: MouseEvent) { 40 - if (menuRef.current && !menuRef.current.contains(event.target as Node)) { 43 + if ( 44 + menuRef.current && 45 + !menuRef.current.contains(event.target as Node) && 46 + buttonRef.current && 47 + !buttonRef.current.contains(event.target as Node) 48 + ) { 41 49 setShowMenu(false); 42 50 } 43 51 } ··· 45 53 return () => document.removeEventListener("mousedown", handleClickOutside); 46 54 }, []); 47 55 56 + useEffect(() => { 57 + if (showMenu && buttonRef.current) { 58 + const rect = buttonRef.current.getBoundingClientRect(); 59 + setMenuPosition({ 60 + top: rect.bottom + 8, 61 + right: window.innerWidth - rect.right, 62 + }); 63 + } 64 + }, [showMenu]); 65 + 48 66 return ( 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 + <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 - <div className="relative z-[9999]" ref={menuRef}> 90 + <> 73 91 <button 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 - {showMenu && ( 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 - <div className="px-4 py-3"> 101 - <div className="font-semibold text-purple-950 dark:text-cyan-50"> 102 - {session?.displayName || session.handle} 103 - </div> 104 - <div className="text-sm text-purple-750 dark:text-cyan-250"> 105 - @{session?.handle} 106 - </div> 107 - </div> 108 - <button 109 - onClick={() => { 110 - setShowMenu(false); 111 - onNavigate("home"); 112 - }} 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 - > 115 - <Home className="w-4 h-4 text-purple-950 dark:text-cyan-50" /> 116 - <span className="text-purple-950 dark:text-cyan-50"> 117 - Dashboard 118 - </span> 119 - </button> 120 - <button 121 - onClick={() => { 122 - setShowMenu(false); 123 - onNavigate("login"); 124 - }} 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 - > 127 - <Heart className="w-4 h-4 text-purple-950 dark:text-cyan-50" /> 128 - <span className="text-purple-950 dark:text-cyan-50"> 129 - Login screen 130 - </span> 131 - </button> 132 - <button 133 - onClick={() => { 134 - setShowMenu(false); 135 - onLogout(); 117 + {showMenu && 118 + createPortal( 119 + <div 120 + ref={menuRef} 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 + style={{ 123 + top: `${menuPosition.top}px`, 124 + right: `${menuPosition.right}px`, 136 125 }} 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 - <LogOut className="w-4 h-4" /> 140 - <span>Log out</span> 141 - </button> 142 - </div> 143 - )} 144 - </div> 127 + <div className="px-4 py-3"> 128 + <div className="font-semibold text-purple-950 dark:text-cyan-50"> 129 + {session?.displayName || session.handle} 130 + </div> 131 + <div className="text-sm text-purple-750 dark:text-cyan-250"> 132 + @{session?.handle} 133 + </div> 134 + </div> 135 + <button 136 + onClick={() => { 137 + setShowMenu(false); 138 + onNavigate("home"); 139 + }} 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 + > 142 + <Home className="w-4 h-4 text-purple-950 dark:text-cyan-50" /> 143 + <span className="text-purple-950 dark:text-cyan-50"> 144 + Dashboard 145 + </span> 146 + </button> 147 + <button 148 + onClick={() => { 149 + setShowMenu(false); 150 + onNavigate("login"); 151 + }} 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 + > 154 + <Heart className="w-4 h-4 text-purple-950 dark:text-cyan-50" /> 155 + <span className="text-purple-950 dark:text-cyan-50"> 156 + Login screen 157 + </span> 158 + </button> 159 + <button 160 + onClick={() => { 161 + setShowMenu(false); 162 + onLogout(); 163 + }} 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 + > 166 + <LogOut className="w-4 h-4" /> 167 + <span>Log out</span> 168 + </button> 169 + </div>, 170 + document.body, 171 + )} 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 - | "weekly" 285 - | "monthly" 286 - | "quarterly", 284 + | "Weekly" 285 + | "Monthly" 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"