feat: UI redesign — polished layout, modal, nav, profile
- CSS: refined shadows with border ring, dark bg #0A0A0A, larger card radius (16/22px), modal-backdrop blur, scrollbar styling, new dropzone + profile-grid CSS classes - Navbar: paw emoji logo, labels under icons, accent gradient bar, active-state ring on avatar - Login / Register: auth card with decorative background blobs, form wrapped in card, cleaner spacing - CatModal: two-column layout on desktop (photo left, info right), modal-backdrop blur, comment input with user avatar, like label - ProfilePage: 88px avatar with camera overlay, inline stat bar with icons, grid section divider, Stat helper component - CatCard: points badge in header (amber), caption text secondary color, ring on avatar - FeedSidebar: color-coded rank badges, hover rows, star icon - UploadPage: new dropzone-idle/dropzone-active CSS classes, filename chip on preview, UserAvatar in caption row, HEIC/AVIF in accepted formats hint, 500-char counter Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -2,7 +2,7 @@ import { Link, useLocation } from 'react-router-dom';
|
||||
import { useAuth } from '@/hooks/useAuth';
|
||||
import { useTheme } from '@/hooks/useTheme';
|
||||
import UserAvatar from '@/components/UserAvatar';
|
||||
import { Home, PlusCircle, Shield, Sun, Moon, Monitor } from 'lucide-react';
|
||||
import { Home, PlusSquare, Shield, Sun, Moon, Monitor } from 'lucide-react';
|
||||
|
||||
export default function Navbar() {
|
||||
const { user } = useAuth();
|
||||
@@ -14,33 +14,55 @@ export default function Navbar() {
|
||||
setTheme(next[theme]);
|
||||
};
|
||||
const ThemeIcon = theme === 'dark' ? Moon : theme === 'light' ? Sun : Monitor;
|
||||
const themeLabel = theme === 'dark' ? 'Тёмная' : theme === 'light' ? 'Светлая' : 'Авто';
|
||||
|
||||
if (!user) return null;
|
||||
|
||||
const isProfile = location.pathname.startsWith('/profile');
|
||||
const isFeed = location.pathname === '/feed' || location.pathname === '/';
|
||||
const isUpload = location.pathname === '/upload';
|
||||
|
||||
return (
|
||||
<nav className="sticky top-0 z-50 nav-glass border-b border-[var(--border-light)]" style={{ paddingTop: 3 }}>
|
||||
<div className="nav-editorial-bar" />
|
||||
<div className="mx-auto flex h-14 max-w-[900px] items-center justify-between px-5">
|
||||
<Link to="/feed" className="wordmark flex items-center gap-1">
|
||||
Котограм<span className="wordmark-dot" />
|
||||
<nav className="sticky top-0 z-50 nav-glass border-b border-[var(--border-light)]">
|
||||
<div className="nav-accent-bar" />
|
||||
<div className="mx-auto flex h-[58px] max-w-[900px] items-center justify-between px-5">
|
||||
|
||||
{/* Логотип */}
|
||||
<Link to="/feed" className="wordmark flex items-center gap-2 group select-none">
|
||||
<span className="text-xl">🐾</span>
|
||||
<span className="group-hover:text-[var(--accent)] transition-colors duration-200">
|
||||
Котограм<span className="wordmark-dot" />
|
||||
</span>
|
||||
</Link>
|
||||
|
||||
<div className="flex items-center gap-1">
|
||||
<NavIcon to="/feed" active={location.pathname === '/feed'} icon={Home} label="Лента" />
|
||||
<NavIcon to="/upload" active={location.pathname === '/upload'} icon={PlusCircle} label="Добавить" />
|
||||
{/* Навигация */}
|
||||
<div className="flex items-center gap-0.5">
|
||||
<NavLink to="/feed" active={isFeed} icon={Home} label="Лента" />
|
||||
<NavLink to="/upload" active={isUpload} icon={PlusSquare} label="Добавить" />
|
||||
|
||||
{/* Переключатель темы */}
|
||||
<button
|
||||
onClick={cycleTheme}
|
||||
title={`Тема: ${theme}`}
|
||||
className="flex items-center justify-center h-9 w-9 rounded-xl transition-all text-[var(--fg-tertiary)] hover:text-[var(--fg-secondary)] hover:bg-[var(--border-light)]"
|
||||
title={`Тема: ${themeLabel}`}
|
||||
className="flex flex-col items-center justify-center gap-0.5 h-11 w-11 rounded-xl transition-all text-[var(--fg-tertiary)] hover:text-[var(--fg-secondary)] hover:bg-[var(--border-light)]"
|
||||
>
|
||||
<ThemeIcon className="h-[18px] w-[18px]" strokeWidth={1.5} />
|
||||
<span className="text-[9px] font-semibold uppercase tracking-wide hidden sm:block opacity-60">{themeLabel}</span>
|
||||
</button>
|
||||
|
||||
<Link to="/profile" className="ml-1.5 relative flex items-center">
|
||||
<div className={`flex items-center justify-center h-8 w-8 rounded-full transition-all ${
|
||||
location.pathname.startsWith('/profile') ? 'ring-2 ring-[var(--accent)] ring-offset-2 ring-offset-[var(--bg)]' : ''
|
||||
{/* Аватар */}
|
||||
<Link to="/profile" className="ml-1 relative flex items-center">
|
||||
<div className={`flex items-center justify-center h-9 w-9 rounded-full transition-all duration-200 ${
|
||||
isProfile
|
||||
? 'ring-[2.5px] ring-[var(--accent)] ring-offset-2 ring-offset-[var(--bg)]'
|
||||
: 'opacity-80 hover:opacity-100'
|
||||
}`}>
|
||||
<UserAvatar avatarUrl={user.avatar_url} username={user.username} className="h-8 w-8" fallbackClassName="text-[11px] avatar-colored bg-[var(--accent)]" />
|
||||
<UserAvatar
|
||||
avatarUrl={user.avatar_url}
|
||||
username={user.username}
|
||||
className="h-9 w-9"
|
||||
fallbackClassName="text-[11px] avatar-colored bg-[var(--accent)]"
|
||||
/>
|
||||
</div>
|
||||
{user.is_admin && (
|
||||
<span className="absolute -top-0.5 -right-0.5 h-3.5 w-3.5 rounded-full bg-[var(--accent)] flex items-center justify-center ring-2 ring-[var(--bg)]">
|
||||
@@ -54,18 +76,22 @@ export default function Navbar() {
|
||||
);
|
||||
}
|
||||
|
||||
function NavIcon({ to, active, icon: Icon, label }: { to: string; active: boolean; icon: any; label: string }) {
|
||||
function NavLink({
|
||||
to, active, icon: Icon, label,
|
||||
}: {
|
||||
to: string; active: boolean; icon: any; label: string;
|
||||
}) {
|
||||
return (
|
||||
<Link
|
||||
to={to}
|
||||
title={label}
|
||||
className={`flex items-center justify-center h-9 w-9 rounded-xl transition-all ${
|
||||
className={`flex flex-col items-center justify-center gap-0.5 h-11 w-11 rounded-xl transition-all duration-200 ${
|
||||
active
|
||||
? 'bg-[var(--accent-soft)] text-[var(--accent)]'
|
||||
: 'text-[var(--fg-tertiary)] hover:text-[var(--fg-secondary)] hover:bg-[var(--border-light)]'
|
||||
}`}
|
||||
>
|
||||
<Icon className="h-[18px] w-[18px]" strokeWidth={active ? 2 : 1.5} />
|
||||
<Icon className="h-[18px] w-[18px]" strokeWidth={active ? 2.2 : 1.5} />
|
||||
<span className="text-[9px] font-semibold uppercase tracking-wide hidden sm:block opacity-70">{label}</span>
|
||||
</Link>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user