2026-01-07 09:31:02 +00:00
|
|
|
import React, { useState } from 'react';
|
2026-01-13 18:47:57 +00:00
|
|
|
import {
|
|
|
|
|
Menu,
|
|
|
|
|
Palette,
|
|
|
|
|
Zap,
|
|
|
|
|
ChevronDown,
|
|
|
|
|
LogOut,
|
|
|
|
|
Settings,
|
|
|
|
|
User,
|
|
|
|
|
ShoppingCart,
|
2026-01-25 11:33:46 +00:00
|
|
|
Search,
|
2026-01-13 18:47:57 +00:00
|
|
|
} from 'lucide-react';
|
2026-01-25 11:33:46 +00:00
|
|
|
import { Button } from '@/components/ui/button';
|
|
|
|
|
import { Input } from '@/components/ui/input';
|
feat(ui): tooltip adoption + search highlighting & skeleton loading
Tooltip adoption (18 conversions across 11 files):
- Player controls: shuffle, repeat, mute, expand, close, lyrics, auto-scroll
- Navbar: theme toggle
- File browser: download, add tag, AI auto-tag, watermark, process with AI
- Notifications: mark as read
- Share links: open link, revoke link
- Chat: scroll to bottom
Search polish:
- New highlightMatch utility — wraps matching text in <mark> with primary color
- Applied to track titles, artist names, playlist names in SearchPageResults
- Applied to suggestion dropdown titles and subtitles
- Replaced spinner loading state with content-aware SearchPageSkeleton
- Skeleton matches actual results layout (tab bar, track cards, artist circles)
Co-authored-by: Cursor <cursoragent@cursor.com>
2026-02-09 22:14:00 +00:00
|
|
|
import { Tooltip } from '@/components/ui/tooltip';
|
2026-02-03 08:42:59 +00:00
|
|
|
import { useCartStore } from '../../stores/cartStore';
|
2026-02-03 23:44:40 +00:00
|
|
|
import { useTheme } from '../theme/ThemeProvider';
|
2026-01-07 09:31:02 +00:00
|
|
|
import { Notification } from '../../types';
|
|
|
|
|
import { NotificationBell } from '../notifications/NotificationBell';
|
|
|
|
|
|
|
|
|
|
interface NavbarProps {
|
|
|
|
|
onNavigate: (viewId: string) => void;
|
|
|
|
|
onLogout: () => void;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
const mockNotifications: Notification[] = [
|
2026-01-13 18:47:57 +00:00
|
|
|
{
|
|
|
|
|
id: '1',
|
|
|
|
|
type: 'info',
|
|
|
|
|
title: 'System Update',
|
|
|
|
|
message: 'System Update v2.0 Live',
|
|
|
|
|
timestamp: '2m',
|
|
|
|
|
read: false,
|
|
|
|
|
},
|
|
|
|
|
{
|
|
|
|
|
id: '2',
|
|
|
|
|
type: 'like',
|
|
|
|
|
title: 'New Like',
|
|
|
|
|
message: 'Neon_Dev liked your track',
|
|
|
|
|
timestamp: '15m',
|
|
|
|
|
read: false,
|
|
|
|
|
actionUrl: '/track/1',
|
|
|
|
|
},
|
|
|
|
|
{
|
|
|
|
|
id: '3',
|
|
|
|
|
type: 'follow',
|
|
|
|
|
title: 'New Follower',
|
|
|
|
|
message: 'Skrillex started following you',
|
|
|
|
|
timestamp: '1h',
|
|
|
|
|
read: true,
|
|
|
|
|
actionUrl: '/u/skrillex',
|
|
|
|
|
},
|
2026-01-07 09:31:02 +00:00
|
|
|
];
|
|
|
|
|
|
|
|
|
|
export const Navbar: React.FC<NavbarProps> = ({ onNavigate, onLogout }) => {
|
2026-02-03 23:44:40 +00:00
|
|
|
const { theme, setTheme } = useTheme();
|
|
|
|
|
|
|
|
|
|
const toggleTheme = () => {
|
|
|
|
|
setTheme(theme === 'dark' ? 'light' : 'dark');
|
|
|
|
|
};
|
2026-02-03 08:42:59 +00:00
|
|
|
// Selector ensures we re-render only when the calculated count changes
|
|
|
|
|
const itemCount = useCartStore((state) => state.getItemCount());
|
2026-01-07 09:31:02 +00:00
|
|
|
const [showUserMenu, setShowUserMenu] = useState(false);
|
2026-01-13 18:47:57 +00:00
|
|
|
const [notifications, setNotifications] =
|
|
|
|
|
useState<Notification[]>(mockNotifications);
|
2026-01-07 09:31:02 +00:00
|
|
|
|
|
|
|
|
const handleMarkAllRead = () => {
|
2026-01-13 18:47:57 +00:00
|
|
|
setNotifications((prev) => prev.map((n) => ({ ...n, read: true })));
|
2026-01-07 09:31:02 +00:00
|
|
|
};
|
|
|
|
|
|
|
|
|
|
const handleRead = (id: string) => {
|
2026-01-13 18:47:57 +00:00
|
|
|
setNotifications((prev) =>
|
|
|
|
|
prev.map((n) => (n.id === id ? { ...n, read: true } : n)),
|
|
|
|
|
);
|
2026-01-07 09:31:02 +00:00
|
|
|
};
|
|
|
|
|
|
|
|
|
|
return (
|
|
|
|
|
<>
|
|
|
|
|
{/* Backdrop for closing menus - Lower z-index than Navbar (z-40) but higher than content */}
|
|
|
|
|
{showUserMenu && (
|
2026-01-07 10:15:48 +00:00
|
|
|
<div
|
|
|
|
|
className="fixed inset-0 z-[35] bg-transparent cursor-default"
|
2026-01-07 09:31:02 +00:00
|
|
|
onClick={() => setShowUserMenu(false)}
|
|
|
|
|
/>
|
|
|
|
|
)}
|
|
|
|
|
|
2026-01-13 18:47:57 +00:00
|
|
|
<nav
|
|
|
|
|
role="navigation"
|
|
|
|
|
aria-label="Main Navigation"
|
2026-02-07 14:25:44 +00:00
|
|
|
className="fixed top-0 left-0 right-0 h-16 bg-background/80 backdrop-blur-md border-b border-border/40 z-40 flex items-center justify-between px-6 lg:px-8"
|
2026-01-13 18:47:57 +00:00
|
|
|
>
|
2026-01-07 09:31:02 +00:00
|
|
|
{/* Brand & Mobile Menu */}
|
|
|
|
|
<div className="flex items-center gap-4">
|
|
|
|
|
<Button variant="ghost" size="sm" className="lg:hidden p-1">
|
2026-01-07 10:15:48 +00:00
|
|
|
<Menu className="w-5 h-5" />
|
2026-01-07 09:31:02 +00:00
|
|
|
</Button>
|
2026-01-13 18:47:57 +00:00
|
|
|
<div
|
aesthetic-improvements: align spacing to 8px grid (Action 11.2.1.3)
- Created automated script (scripts/align-8px-grid.py) to align all spacing to 8px grid
- Replaced non-8px-aligned spacing: gap-3/p-3/m-3 (12px) → gap-4/p-4/m-4 (16px), gap-5/p-5/m-5 (20px) → gap-6/p-6/m-6 (24px), gap-10/p-10/m-10 (40px) → gap-12/p-12/m-12 (48px), gap-20/p-20/m-20 (80px) → gap-24/p-24/m-24 (96px)
- Preserved: 4px values (gap-1, p-1, m-1) as they may be intentional fine-tuning, responsive breakpoints (sm:, md:, lg:), test files, documentation
- Modified files across all components to ensure consistent 8px grid alignment
- Action 11.2.1.3: Align all elements to 8px grid - COMPLETE
2026-01-16 10:50:46 +00:00
|
|
|
className="flex items-center gap-4 cursor-pointer"
|
2026-01-13 18:47:57 +00:00
|
|
|
onClick={() => onNavigate('dashboard')}
|
|
|
|
|
>
|
2026-02-07 14:25:44 +00:00
|
|
|
<div className="w-8 h-8 rounded-full bg-primary flex items-center justify-center shadow-lg shadow-border/20">
|
|
|
|
|
<span className="font-display font-bold text-primary-foreground text-lg">
|
2026-01-13 18:47:57 +00:00
|
|
|
V
|
|
|
|
|
</span>
|
2026-01-07 09:31:02 +00:00
|
|
|
</div>
|
|
|
|
|
<div className="hidden sm:flex flex-col justify-center">
|
2026-02-07 14:25:44 +00:00
|
|
|
<span className="font-display font-bold text-base tracking-wide text-foreground leading-none">
|
2026-01-07 09:31:02 +00:00
|
|
|
VEZA
|
|
|
|
|
</span>
|
ui(tokens): migrate text-[10px] to text-xs across 23 components
Replace all arbitrary text-[10px] / text-[9px] with the standard Tailwind
text-xs token. Also migrates nearby arbitrary width values where applicable
(max-w-[200px] → max-w-48, max-w-[120px] → max-w-32, h-[1px] → h-px).
Only documented exceptions remain: avatar xs (text-[10px] for w-6 h-6
initials) and badge JSDoc reference.
Affected areas: admin views, marketplace, player, settings, chat, upload,
education, commerce, library, PWA, search, navbar, user card.
Co-authored-by: Cursor <cursoragent@cursor.com>
2026-02-08 21:47:19 +00:00
|
|
|
<span className="text-xs text-muted-foreground font-medium tracking-widest uppercase leading-none mt-1">
|
2026-01-07 09:31:02 +00:00
|
|
|
Spectre Astral
|
|
|
|
|
</span>
|
|
|
|
|
</div>
|
|
|
|
|
</div>
|
|
|
|
|
</div>
|
|
|
|
|
|
|
|
|
|
{/* Center Search (Hidden on Mobile) */}
|
|
|
|
|
<div className="hidden md:flex flex-1 max-w-md mx-8 relative">
|
2026-02-03 08:42:59 +00:00
|
|
|
<Input
|
|
|
|
|
placeholder="Search platform..."
|
2026-01-25 11:33:46 +00:00
|
|
|
icon={<Search className="w-4 h-4" />}
|
|
|
|
|
/>
|
2026-01-07 09:31:02 +00:00
|
|
|
<div className="absolute right-0 top-1/2 -translate-y-1/2 pr-3 flex gap-2">
|
ui(tokens): migrate text-[10px] to text-xs across 23 components
Replace all arbitrary text-[10px] / text-[9px] with the standard Tailwind
text-xs token. Also migrates nearby arbitrary width values where applicable
(max-w-[200px] → max-w-48, max-w-[120px] → max-w-32, h-[1px] → h-px).
Only documented exceptions remain: avatar xs (text-[10px] for w-6 h-6
initials) and badge JSDoc reference.
Affected areas: admin views, marketplace, player, settings, chat, upload,
education, commerce, library, PWA, search, navbar, user card.
Co-authored-by: Cursor <cursoragent@cursor.com>
2026-02-08 21:47:19 +00:00
|
|
|
<span className="px-1.5 py-0.5 bg-muted rounded text-xs text-muted-foreground font-mono border border-white/5">
|
2026-01-13 18:47:57 +00:00
|
|
|
CMD+K
|
|
|
|
|
</span>
|
2026-01-07 09:31:02 +00:00
|
|
|
</div>
|
|
|
|
|
</div>
|
|
|
|
|
|
|
|
|
|
{/* Right Actions */}
|
aesthetic-improvements: align spacing to 8px grid (Action 11.2.1.3)
- Created automated script (scripts/align-8px-grid.py) to align all spacing to 8px grid
- Replaced non-8px-aligned spacing: gap-3/p-3/m-3 (12px) → gap-4/p-4/m-4 (16px), gap-5/p-5/m-5 (20px) → gap-6/p-6/m-6 (24px), gap-10/p-10/m-10 (40px) → gap-12/p-12/m-12 (48px), gap-20/p-20/m-20 (80px) → gap-24/p-24/m-24 (96px)
- Preserved: 4px values (gap-1, p-1, m-1) as they may be intentional fine-tuning, responsive breakpoints (sm:, md:, lg:), test files, documentation
- Modified files across all components to ensure consistent 8px grid alignment
- Action 11.2.1.3: Align all elements to 8px grid - COMPLETE
2026-01-16 10:50:46 +00:00
|
|
|
<div className="flex items-center gap-4 md:gap-6">
|
2026-01-07 09:31:02 +00:00
|
|
|
{/* Pro Badge */}
|
2026-02-07 14:25:44 +00:00
|
|
|
<div className="hidden xl:flex items-center gap-4 border-r border-border/50 pr-6">
|
2026-01-07 10:15:48 +00:00
|
|
|
<div className="text-right">
|
2026-02-07 14:25:44 +00:00
|
|
|
<div className="text-xs text-foreground font-medium">
|
2026-01-13 18:47:57 +00:00
|
|
|
Pro Plan
|
|
|
|
|
</div>
|
ui(tokens): migrate text-[10px] to text-xs across 23 components
Replace all arbitrary text-[10px] / text-[9px] with the standard Tailwind
text-xs token. Also migrates nearby arbitrary width values where applicable
(max-w-[200px] → max-w-48, max-w-[120px] → max-w-32, h-[1px] → h-px).
Only documented exceptions remain: avatar xs (text-[10px] for w-6 h-6
initials) and badge JSDoc reference.
Affected areas: admin views, marketplace, player, settings, chat, upload,
education, commerce, library, PWA, search, navbar, user card.
Co-authored-by: Cursor <cursoragent@cursor.com>
2026-02-08 21:47:19 +00:00
|
|
|
<div className="text-xs text-muted-foreground">
|
2026-01-13 18:47:57 +00:00
|
|
|
Valid until Dec 31
|
|
|
|
|
</div>
|
2026-01-07 10:15:48 +00:00
|
|
|
</div>
|
2026-02-07 14:25:44 +00:00
|
|
|
<div className="w-8 h-8 rounded-full bg-muted flex items-center justify-center">
|
|
|
|
|
<Zap className="w-4 h-4 text-warning fill-current" />
|
2026-01-07 10:15:48 +00:00
|
|
|
</div>
|
2026-01-07 09:31:02 +00:00
|
|
|
</div>
|
|
|
|
|
|
feat(ui): tooltip adoption + search highlighting & skeleton loading
Tooltip adoption (18 conversions across 11 files):
- Player controls: shuffle, repeat, mute, expand, close, lyrics, auto-scroll
- Navbar: theme toggle
- File browser: download, add tag, AI auto-tag, watermark, process with AI
- Notifications: mark as read
- Share links: open link, revoke link
- Chat: scroll to bottom
Search polish:
- New highlightMatch utility — wraps matching text in <mark> with primary color
- Applied to track titles, artist names, playlist names in SearchPageResults
- Applied to suggestion dropdown titles and subtitles
- Replaced spinner loading state with content-aware SearchPageSkeleton
- Skeleton matches actual results layout (tab bar, track cards, artist circles)
Co-authored-by: Cursor <cursoragent@cursor.com>
2026-02-09 22:14:00 +00:00
|
|
|
<Tooltip content={`Theme: ${theme}`}>
|
|
|
|
|
<Button
|
|
|
|
|
variant="ghost"
|
|
|
|
|
size="sm"
|
|
|
|
|
onClick={toggleTheme}
|
|
|
|
|
className="hidden sm:flex"
|
|
|
|
|
>
|
|
|
|
|
<Palette className="w-5 h-5" />
|
|
|
|
|
</Button>
|
|
|
|
|
</Tooltip>
|
2026-01-07 09:31:02 +00:00
|
|
|
|
|
|
|
|
{/* Cart Trigger */}
|
2026-01-07 10:15:48 +00:00
|
|
|
<Button
|
|
|
|
|
variant="ghost"
|
|
|
|
|
size="sm"
|
2026-01-16 09:14:17 +00:00
|
|
|
className="relative hidden sm:flex"
|
2026-01-07 09:31:02 +00:00
|
|
|
onClick={() => onNavigate('cart')}
|
|
|
|
|
>
|
|
|
|
|
<ShoppingCart className="w-5 h-5" />
|
2026-01-13 18:47:57 +00:00
|
|
|
{itemCount > 0 && (
|
ui(tokens): migrate kodo-cyan to primary (51 files, 88 instances)
Replace legacy text-kodo-cyan/border-kodo-cyan/bg-kodo-cyan with semantic
text-primary/border-primary/bg-primary across 51 components.
The brand primary color now uses the design system token, enabling proper
theme adaptation. Covers UI primitives, search, dashboard, chat, playlists,
settings, social, marketplace, and auth components.
Co-authored-by: Cursor <cursoragent@cursor.com>
2026-02-08 23:19:12 +00:00
|
|
|
<span className="absolute top-1.5 right-1.5 w-2 h-2 bg-primary rounded-full border border-kodo-void"></span>
|
2026-01-13 18:47:57 +00:00
|
|
|
)}
|
2026-01-07 09:31:02 +00:00
|
|
|
</Button>
|
|
|
|
|
|
|
|
|
|
{/* Notification Center */}
|
2026-01-07 10:15:48 +00:00
|
|
|
<NotificationBell
|
|
|
|
|
notifications={notifications}
|
|
|
|
|
onMarkAllRead={handleMarkAllRead}
|
|
|
|
|
onRead={handleRead}
|
|
|
|
|
onViewAll={() => onNavigate('notifications')}
|
2026-01-07 09:31:02 +00:00
|
|
|
/>
|
2026-01-07 10:15:48 +00:00
|
|
|
|
2026-01-07 09:31:02 +00:00
|
|
|
{/* User Menu */}
|
|
|
|
|
<div className="relative z-50">
|
2026-01-07 10:15:48 +00:00
|
|
|
<div
|
|
|
|
|
className="flex items-center gap-2 cursor-pointer group select-none"
|
|
|
|
|
onClick={() => setShowUserMenu(!showUserMenu)}
|
|
|
|
|
>
|
2026-02-07 14:25:44 +00:00
|
|
|
<div className="w-9 h-9 rounded-full bg-border p-px hover:ring-2 hover:ring-border transition-all">
|
2026-01-07 10:15:48 +00:00
|
|
|
<div className="w-full h-full rounded-full overflow-hidden">
|
2026-01-13 18:47:57 +00:00
|
|
|
<img
|
|
|
|
|
src="https://picsum.photos/100/100"
|
|
|
|
|
alt="Avatar"
|
|
|
|
|
className="w-full h-full object-cover"
|
|
|
|
|
/>
|
2026-01-07 10:15:48 +00:00
|
|
|
</div>
|
2026-01-07 09:31:02 +00:00
|
|
|
</div>
|
2026-01-13 18:47:57 +00:00
|
|
|
<ChevronDown
|
feat(web): UI premium Discord/Spotify-like — tokens, shadows, focus, layout
Plan UI premium 6–8 semaines (design system, shell, Storybook, a11y):
- Design system: DESIGN_TOKENS.md, APP_SHELL.md, FULL_LAYOUT_PAGE.md. Single source
for layout/shell (index.css), shadows (design-system.css), durations/easing.
- Tokens: shadow-cover-depth, shadow-gold-glow, shadow-fab-glow; layout max-height
(max-h-layout-drawer, max-h-layout-panel, max-h-layout-list). All duration-200/300/500
replaced by --duration-fast/normal/slow. Arbitrary shadows replaced by token classes.
- Shell & player: Sidebar, Header, GlobalPlayer, MiniPlayer, PlayerQueue, PlayerControls,
AudioPlayer use tokens; focus-visible on Sidebar, PlayerQueue, DropdownMenuTrigger/Item,
TabsTrigger. Typography: text-[10px]/[9px] → text-xs where applicable.
- ESLint: no-restricted-syntax (warn) for w-/h-/rounded-/shadow-/text-/spacing arbitrary.
- Scripts: report-arbitrary-values.mjs, capture/compare/generate visual; visual-complete.spec.ts.
- Stories full layout: Dashboard, Playlists, Library, Settings, Profile in DashboardLayout.stories.
- .cursorrules + README: DESIGN_TOKENS, APP_SHELL, visual commands, no arbitrary without justification.
- apps/web/.gitignore: e2e test artifacts (test-results-visual, playwright-report-visual).
Co-authored-by: Cursor <cursoragent@cursor.com>
2026-02-08 16:15:58 +00:00
|
|
|
className={`w-4 h-4 text-white group-hover:text-primary transition-transform duration-[var(--duration-fast)] ${showUserMenu ? 'rotate-180' : ''}`}
|
2026-01-13 18:47:57 +00:00
|
|
|
/>
|
2026-01-07 10:15:48 +00:00
|
|
|
</div>
|
2026-01-07 09:31:02 +00:00
|
|
|
|
2026-01-07 10:15:48 +00:00
|
|
|
{showUserMenu && (
|
2026-02-07 14:25:44 +00:00
|
|
|
<div className="absolute top-full right-0 mt-4 w-56 bg-card border border-border rounded-xl shadow-2xl overflow-hidden animate-fadeIn origin-top-right ring-1 ring-white/5 flex flex-col">
|
|
|
|
|
<div className="px-4 py-4 border-b border-border/30 mb-1 bg-muted/50">
|
2026-01-07 10:15:48 +00:00
|
|
|
<p className="text-sm font-bold text-white">Cyber_Producer</p>
|
2026-02-07 14:25:44 +00:00
|
|
|
<p className="text-xs text-muted-foreground">Pro Plan</p>
|
2026-01-07 10:15:48 +00:00
|
|
|
</div>
|
2026-01-18 21:27:53 +00:00
|
|
|
<Button
|
|
|
|
|
variant="ghost"
|
2026-01-13 18:47:57 +00:00
|
|
|
onClick={() => {
|
|
|
|
|
onNavigate('profile');
|
|
|
|
|
setShowUserMenu(false);
|
|
|
|
|
}}
|
2026-02-07 14:25:44 +00:00
|
|
|
className="w-full justify-start px-4 py-2.5 text-sm text-foreground hover:bg-muted hover:text-foreground gap-4"
|
2026-01-07 10:15:48 +00:00
|
|
|
>
|
|
|
|
|
<User className="w-4 h-4" /> My Profile
|
2026-01-18 21:27:53 +00:00
|
|
|
</Button>
|
|
|
|
|
<Button
|
|
|
|
|
variant="ghost"
|
2026-01-13 18:47:57 +00:00
|
|
|
onClick={() => {
|
|
|
|
|
onNavigate('studio/go-live');
|
|
|
|
|
setShowUserMenu(false);
|
|
|
|
|
}}
|
2026-02-07 14:25:44 +00:00
|
|
|
className="w-full justify-start px-4 py-2.5 text-sm text-foreground hover:bg-muted hover:text-foreground gap-4"
|
2026-01-07 10:15:48 +00:00
|
|
|
>
|
2026-02-07 14:25:44 +00:00
|
|
|
<Zap className="w-4 h-4 text-destructive" /> Go Live
|
2026-01-18 21:27:53 +00:00
|
|
|
</Button>
|
|
|
|
|
<Button
|
|
|
|
|
variant="ghost"
|
2026-01-13 18:47:57 +00:00
|
|
|
onClick={() => {
|
|
|
|
|
onNavigate('purchases');
|
|
|
|
|
setShowUserMenu(false);
|
|
|
|
|
}}
|
2026-02-07 14:25:44 +00:00
|
|
|
className="w-full justify-start px-4 py-2.5 text-sm text-foreground hover:bg-muted hover:text-foreground gap-4"
|
2026-01-07 10:15:48 +00:00
|
|
|
>
|
|
|
|
|
<ShoppingCart className="w-4 h-4" /> Purchases
|
2026-01-18 21:27:53 +00:00
|
|
|
</Button>
|
|
|
|
|
<Button
|
|
|
|
|
variant="ghost"
|
2026-01-13 18:47:57 +00:00
|
|
|
onClick={() => {
|
|
|
|
|
onNavigate('settings');
|
|
|
|
|
setShowUserMenu(false);
|
|
|
|
|
}}
|
2026-02-07 14:25:44 +00:00
|
|
|
className="w-full justify-start px-4 py-2.5 text-sm text-foreground hover:bg-muted hover:text-foreground gap-4"
|
2026-01-07 10:15:48 +00:00
|
|
|
>
|
|
|
|
|
<Settings className="w-4 h-4" /> Settings
|
2026-01-18 21:27:53 +00:00
|
|
|
</Button>
|
2026-02-07 14:25:44 +00:00
|
|
|
<div className="h-px bg-border/30 my-1 mx-2"></div>
|
2026-01-18 21:27:53 +00:00
|
|
|
<Button
|
|
|
|
|
variant="ghost"
|
2026-01-13 18:47:57 +00:00
|
|
|
onClick={() => {
|
|
|
|
|
onLogout();
|
|
|
|
|
setShowUserMenu(false);
|
|
|
|
|
}}
|
2026-02-07 14:25:44 +00:00
|
|
|
className="w-full justify-start px-4 py-2.5 text-sm text-destructive hover:bg-destructive/10 rounded-lg gap-4"
|
2026-01-07 10:15:48 +00:00
|
|
|
>
|
|
|
|
|
<LogOut className="w-4 h-4" /> Sign Out
|
2026-01-18 21:27:53 +00:00
|
|
|
</Button>
|
2026-01-07 10:15:48 +00:00
|
|
|
</div>
|
|
|
|
|
)}
|
2026-01-07 09:31:02 +00:00
|
|
|
</div>
|
|
|
|
|
</div>
|
|
|
|
|
</nav>
|
|
|
|
|
</>
|
|
|
|
|
);
|
|
|
|
|
};
|