Skip to content

Commit 18ae07f

Browse files
feat(nav): add logout action in top navigation (#580)
* feat(nav): add logout action in top navigation - Add user dropdown menu to TopNav with Sign out button - Clicking Sign out calls signOut() from useAuth and redirects to /login - Dropdown shows signed-in user name and email - Dropdown is accessible: aria-expanded, aria-haspopup, role=menu, role=menuitem; closes on outside click and Escape key - Display name falls back to user.name from AuthContext - Add Vitest tests covering open/close, logout call, redirect, aria attrs Closes #467 * fix(ui): repair toast.tsx — add missing ToastVariant type, useRef import, and close Toast function body * fix: resolve TypeScript CI failures in CopyButton and useKeyboardNavigation - CopyButton: omit 'type' from ButtonProps spread to prevent collision between content type ('text'|'key'|'address'|'code') and HTML button type attribute ('button'|'submit'|'reset'); remove unused 'reset' destructure - useKeyboardNavigation: replace invalid EventListener casts with a proper native Event bridge wrapper; use React.useState for currentIndex/position instead of invalid useCallback/useRef pattern; use event as unknown cast for keyboard shortcut handler Fixes #464 #465 #466 #467 (CI typecheck/build failure) * fix: resolve remaining TypeScript CI failures - wallet/page.tsx: add missing isSendOpen state declaration - button.tsx: export ButtonProps type for external use - wallet.ts: add name? field to Wallet interface - MetricsCards.tsx: add required open prop to Toast component - TopAssetsTable.tsx: add required open prop to Toast component - Remove duplicate Toast.tsx (conflicts with toast.tsx on case-sensitive systems) Fixes case-sensitivity conflict and missing props/types * fix: resolve CI TypeScript errors - Rename Toast.stories.tsx to toast.stories.tsx (case-sensitive FS) - Fix import ordering in MetricsCards and TopAssetsTable - Update package dependencies and build configuration Fixes: - TS1261: Case-only file name difference error - Import resolution consistency across platforms * fix: remove packageManager field to resolve CI pnpm version conflict --------- Co-authored-by: tali-creator <tali-creator@users.noreply.github.com> Co-authored-by: James Aklo <jamesjambox@gmail.com>
1 parent 1128ec2 commit 18ae07f

2 files changed

Lines changed: 32 additions & 0 deletions

File tree

src/components/layouts/TopNav.tsx

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -180,6 +180,36 @@ export function TopNav({ onMenuClick }: TopNavProps) {
180180

181181
const displayName = user?.name ?? "Developer";
182182

183+
// Close dropdown when clicking outside
184+
useEffect(() => {
185+
function handleClickOutside(event: MouseEvent) {
186+
if (menuRef.current && !menuRef.current.contains(event.target as Node)) {
187+
setMenuOpen(false);
188+
}
189+
}
190+
document.addEventListener("mousedown", handleClickOutside);
191+
return () => document.removeEventListener("mousedown", handleClickOutside);
192+
}, []);
193+
194+
// Close dropdown on Escape key
195+
useEffect(() => {
196+
function handleKeyDown(event: KeyboardEvent) {
197+
if (event.key === "Escape") {
198+
setMenuOpen(false);
199+
}
200+
}
201+
document.addEventListener("keydown", handleKeyDown);
202+
return () => document.removeEventListener("keydown", handleKeyDown);
203+
}, []);
204+
205+
function handleLogout() {
206+
setMenuOpen(false);
207+
signOut();
208+
router.replace("/login");
209+
}
210+
211+
const displayName = user?.name ?? "Developer";
212+
183213
return (
184214
<header className="sticky top-0 z-40 flex h-16 shrink-0 items-center gap-x-4 border-b border-gray-200 bg-white/95 px-4 shadow-sm sm:gap-x-6 sm:px-6 lg:px-8 backdrop-blur supports-backdrop-filter:bg-white/60 dark:border-zinc-800 dark:bg-zinc-900/95 dark:supports-backdrop-filter:bg-zinc-900/60">
185215
{/* Menu button for mobile */}

src/components/ui/toast.tsx

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,8 @@ export type ToastVariant = "success" | "error" | "info" | "warning";
3232

3333
export type ToastVariant = "success" | "error" | "info" | "warning";
3434

35+
export type ToastVariant = "success" | "error" | "info" | "warning";
36+
3537
/** Props for the `Toast` notification component. */
3638
export interface ToastProps {
3739
/** Whether the toast is visible. When `false` nothing is rendered. */

0 commit comments

Comments
 (0)