feat: redesign app UI — top nav, clean dashboard, warm branding
- Replace sidebar with top navigation bar (like Airbnb/Nextdoor) - Redesign dashboard: home cards, coming up tasks, quick action pills - Remove widget-heavy layout (charts, stats, activity feed) - Add landing page with hero, features, how-it-works, CTA sections - Update auth pages with split layout - Clean white theme with neutral grays, brand orange/teal accents - Friendly copy across all empty states and page headers - Add Bricolage Grotesque + Outfit fonts - Default to light mode Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -1,7 +1,10 @@
|
||||
"use client";
|
||||
|
||||
import { useRouter } from 'next/navigation';
|
||||
import Image from 'next/image';
|
||||
import Link from 'next/link';
|
||||
import { usePathname, useRouter } from 'next/navigation';
|
||||
import { LogOut, Settings, User } from 'lucide-react';
|
||||
import { cn } from '@/lib/utils';
|
||||
import { NotificationBell } from '@/components/notifications/notification-bell';
|
||||
import { Avatar, AvatarFallback } from '@/components/ui/avatar';
|
||||
import {
|
||||
@@ -12,10 +15,19 @@ import {
|
||||
DropdownMenuTrigger,
|
||||
} from '@/components/ui/dropdown-menu';
|
||||
import { useDataProvider } from '@/lib/demo/data-provider-context';
|
||||
import { useAuthStore } from '@/stores/auth';
|
||||
import { getNavItems } from './nav-items';
|
||||
|
||||
export function TopBar() {
|
||||
const router = useRouter();
|
||||
const pathname = usePathname();
|
||||
const { basePath } = useDataProvider();
|
||||
const user = useAuthStore((s) => s.user);
|
||||
|
||||
const navItems = getNavItems(basePath).filter((item) => item.label !== 'Settings');
|
||||
const initials = user
|
||||
? `${user.first_name?.[0] ?? ''}${user.last_name?.[0] ?? ''}`.toUpperCase() || 'U'
|
||||
: 'U';
|
||||
|
||||
const handleLogout = async () => {
|
||||
try {
|
||||
@@ -31,42 +43,84 @@ export function TopBar() {
|
||||
};
|
||||
|
||||
return (
|
||||
<header className="sticky top-0 z-20 flex items-center justify-between h-16 px-4 lg:px-6 bg-card border-b border-border">
|
||||
{/* Mobile logo - hidden on desktop since sidebar has it */}
|
||||
<div className="md:hidden">
|
||||
<span className="text-xl font-bold text-foreground">Casera</span>
|
||||
</div>
|
||||
<header className="sticky top-0 z-30 bg-background/80 backdrop-blur-xl border-b border-border/60">
|
||||
<div className="max-w-7xl mx-auto flex items-center justify-between h-16 px-6">
|
||||
{/* Logo */}
|
||||
<Link href={basePath} className="flex items-center gap-2.5 shrink-0 group">
|
||||
<Image
|
||||
src="/logo.png"
|
||||
alt="Casera"
|
||||
width={32}
|
||||
height={32}
|
||||
className="rounded-lg transition-transform group-hover:scale-105"
|
||||
/>
|
||||
<span className="font-heading text-xl font-bold text-foreground tracking-tight">
|
||||
Casera
|
||||
</span>
|
||||
</Link>
|
||||
|
||||
{/* Spacer for desktop (logo is in sidebar) */}
|
||||
<div className="hidden md:block" />
|
||||
{/* Desktop nav links */}
|
||||
<nav className="hidden md:flex items-center gap-1" role="navigation" aria-label="Main navigation">
|
||||
{navItems.map((item) => {
|
||||
const isActive =
|
||||
item.href === basePath
|
||||
? pathname === basePath || pathname === basePath + '/'
|
||||
: pathname.startsWith(item.href);
|
||||
|
||||
{/* Notifications + Profile */}
|
||||
<div className="flex items-center gap-2">
|
||||
<NotificationBell />
|
||||
<DropdownMenu>
|
||||
<DropdownMenuTrigger asChild>
|
||||
<button aria-label="User menu" className="flex items-center gap-2 rounded-full outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2">
|
||||
<Avatar>
|
||||
<AvatarFallback>U</AvatarFallback>
|
||||
</Avatar>
|
||||
</button>
|
||||
</DropdownMenuTrigger>
|
||||
<DropdownMenuContent align="end" className="w-48">
|
||||
<DropdownMenuItem onClick={() => router.push(`${basePath}/settings`)}>
|
||||
<User className="size-4" />
|
||||
Profile
|
||||
</DropdownMenuItem>
|
||||
<DropdownMenuItem onClick={() => router.push(`${basePath}/settings`)}>
|
||||
<Settings className="size-4" />
|
||||
Settings
|
||||
</DropdownMenuItem>
|
||||
<DropdownMenuSeparator />
|
||||
<DropdownMenuItem onClick={handleLogout} variant="destructive">
|
||||
<LogOut className="size-4" />
|
||||
Logout
|
||||
</DropdownMenuItem>
|
||||
</DropdownMenuContent>
|
||||
</DropdownMenu>
|
||||
return (
|
||||
<Link
|
||||
key={item.href}
|
||||
href={item.href}
|
||||
aria-current={isActive ? 'page' : undefined}
|
||||
className={cn(
|
||||
'relative px-3.5 py-1.5 text-sm font-medium rounded-lg transition-colors',
|
||||
isActive
|
||||
? 'text-foreground'
|
||||
: 'text-muted-foreground hover:text-foreground'
|
||||
)}
|
||||
>
|
||||
{item.label}
|
||||
{isActive && (
|
||||
<span className="absolute bottom-0 left-3.5 right-3.5 h-[2px] bg-foreground rounded-full" />
|
||||
)}
|
||||
</Link>
|
||||
);
|
||||
})}
|
||||
</nav>
|
||||
|
||||
{/* Right section */}
|
||||
<div className="flex items-center gap-1.5">
|
||||
<NotificationBell />
|
||||
<DropdownMenu>
|
||||
<DropdownMenuTrigger asChild>
|
||||
<button
|
||||
aria-label="User menu"
|
||||
className="flex items-center gap-2 rounded-full outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2"
|
||||
>
|
||||
<Avatar className="size-8 border border-border/60">
|
||||
<AvatarFallback className="bg-primary/10 text-primary text-xs font-semibold">
|
||||
{initials}
|
||||
</AvatarFallback>
|
||||
</Avatar>
|
||||
</button>
|
||||
</DropdownMenuTrigger>
|
||||
<DropdownMenuContent align="end" className="w-48">
|
||||
<DropdownMenuItem onClick={() => router.push(`${basePath}/settings/profile`)}>
|
||||
<User className="size-4" />
|
||||
Profile
|
||||
</DropdownMenuItem>
|
||||
<DropdownMenuItem onClick={() => router.push(`${basePath}/settings`)}>
|
||||
<Settings className="size-4" />
|
||||
Settings
|
||||
</DropdownMenuItem>
|
||||
<DropdownMenuSeparator />
|
||||
<DropdownMenuItem onClick={handleLogout} variant="destructive">
|
||||
<LogOut className="size-4" />
|
||||
Sign out
|
||||
</DropdownMenuItem>
|
||||
</DropdownMenuContent>
|
||||
</DropdownMenu>
|
||||
</div>
|
||||
</div>
|
||||
</header>
|
||||
);
|
||||
|
||||
Reference in New Issue
Block a user