UI: доработано оформление — тени, анимации, градиенты, iOS-стиль

This commit is contained in:
2026-05-29 11:52:04 +03:00
parent a67b8c3341
commit f8f220469c
13 changed files with 362 additions and 727 deletions

View File

@@ -1,7 +1,6 @@
import { Link, useLocation } from 'react-router-dom';
import { useAuth } from '@/hooks/useAuth';
import { Avatar, AvatarFallback } from '@/components/ui/avatar';
import { House, Plus } from 'lucide-react';
export default function Navbar() {
const { user } = useAuth();
@@ -9,44 +8,19 @@ export default function Navbar() {
if (!user) return null;
const navItems = [
{ to: '/feed', label: 'Лента', icon: House },
{ to: '/upload', label: 'Добавить', icon: Plus },
];
return (
<nav className="sticky top-0 z-50 bg-[var(--surface)]/90 backdrop-blur-xl border-b border-[var(--border)]">
<nav className="sticky top-0 z-50 bg-[var(--surface)]/80 backdrop-blur-xl border-b">
<div className="mx-auto flex h-14 max-w-[660px] items-center justify-between px-4">
<Link
to="/feed"
className="text-[18px] font-bold tracking-tight"
style={{ background: 'linear-gradient(135deg, #007aff, #5856d6)', WebkitBackgroundClip: 'text', WebkitTextFillColor: 'transparent' }}
>
<Link to="/feed" className="text-[19px] font-bold gradient-text tracking-tight">
Catstagram
</Link>
<div className="flex items-center gap-1">
{navItems.map((item) => {
const Icon = item.icon;
const isActive = location.pathname === item.to;
return (
<Link
key={item.to}
to={item.to}
className={`flex items-center gap-1.5 px-3.5 py-2 rounded-full text-[13px] font-medium transition-all ${
isActive
? 'bg-[var(--primary-light)] text-[var(--primary)]'
: 'text-[var(--foreground-secondary)] hover:text-[var(--foreground)] hover:bg-[var(--secondary)]'
}`}
>
<Icon className={`h-4 w-4 ${isActive ? 'stroke-[2.5]' : 'stroke-[1.5]'}`} />
<span className="hidden sm:inline">{item.label}</span>
</Link>
);
})}
<div className="flex items-center gap-0.5">
<NavLink to="/feed" active={location.pathname === '/feed'} emoji="🏠" label="Лента" />
<NavLink to="/upload" active={location.pathname === '/upload'} emoji="" label="Добавить" short />
<Link to="/profile" className="ml-1">
<Avatar className="h-8 w-8 border-2 border-transparent hover:border-[var(--primary)] transition-all">
<Link to="/profile" className="ml-2">
<Avatar className="h-8 w-8 ring-1 ring-[var(--border)] hover:ring-[var(--primary)] transition-all">
<AvatarFallback className="text-[11px] avatar-initials">
{user.username.charAt(0).toUpperCase()}
</AvatarFallback>
@@ -56,4 +30,20 @@ export default function Navbar() {
</div>
</nav>
);
}
function NavLink({ to, active, emoji, label, short }: { to: string; active: boolean; emoji: string; label: string; short?: boolean }) {
return (
<Link
to={to}
className={`flex items-center gap-1.5 px-3 py-1.5 rounded-full text-[13px] font-medium transition-all ${
active
? 'bg-[var(--primary-soft)] text-[var(--primary)]'
: 'text-[var(--fg-secondary)] hover:text-[var(--fg)] hover:bg-[var(--secondary)]'
}`}
>
<span className="text-[15px] leading-none">{emoji}</span>
{(!short || true) && <span className={short ? 'hidden sm:inline' : ''}>{label}</span>}
</Link>
);
}