Add sidebar navigation with responsive bottom bar
Three pages: AutoTrader, AutoBuyer, AutoRequester. Fixed left sidebar on desktop (md+), bottom tab bar on mobile. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Opus 4.6
parent
b990ba0606
commit
881c210366
@@ -0,0 +1,12 @@
|
|||||||
|
export default function AutoBuyer() {
|
||||||
|
return (
|
||||||
|
<div className="min-h-screen bg-slate-50 p-8">
|
||||||
|
<div className="max-w-7xl mx-auto">
|
||||||
|
<h1 className="text-2xl font-bold text-slate-900 mb-6">AutoBuyer</h1>
|
||||||
|
<div className="bg-white border border-slate-200 rounded-xl shadow-sm p-8 text-center text-slate-400">
|
||||||
|
Coming soon
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
||||||
@@ -0,0 +1,12 @@
|
|||||||
|
export default function AutoRequester() {
|
||||||
|
return (
|
||||||
|
<div className="min-h-screen bg-slate-50 p-8">
|
||||||
|
<div className="max-w-7xl mx-auto">
|
||||||
|
<h1 className="text-2xl font-bold text-slate-900 mb-6">AutoRequester</h1>
|
||||||
|
<div className="bg-white border border-slate-200 rounded-xl shadow-sm p-8 text-center text-slate-400">
|
||||||
|
Coming soon
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
||||||
@@ -0,0 +1,100 @@
|
|||||||
|
'use client';
|
||||||
|
|
||||||
|
import Link from 'next/link';
|
||||||
|
import { usePathname } from 'next/navigation';
|
||||||
|
|
||||||
|
const NAV_ITEMS = [
|
||||||
|
{
|
||||||
|
label: 'AutoTrader',
|
||||||
|
href: '/',
|
||||||
|
icon: (
|
||||||
|
<svg width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round">
|
||||||
|
<polyline points="22 12 18 12 15 21 9 3 6 12 2 12" />
|
||||||
|
</svg>
|
||||||
|
),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: 'AutoBuyer',
|
||||||
|
href: '/autobuyer',
|
||||||
|
icon: (
|
||||||
|
<svg width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round">
|
||||||
|
<circle cx="9" cy="21" r="1" />
|
||||||
|
<circle cx="20" cy="21" r="1" />
|
||||||
|
<path d="M1 1h4l2.68 13.39a2 2 0 0 0 2 1.61h9.72a2 2 0 0 0 2-1.61L23 6H6" />
|
||||||
|
</svg>
|
||||||
|
),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: 'AutoRequester',
|
||||||
|
href: '/autorequester',
|
||||||
|
icon: (
|
||||||
|
<svg width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round">
|
||||||
|
<path d="M14 2H6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V8z" />
|
||||||
|
<polyline points="14 2 14 8 20 8" />
|
||||||
|
<line x1="12" y1="18" x2="12" y2="12" />
|
||||||
|
<line x1="9" y1="15" x2="15" y2="15" />
|
||||||
|
</svg>
|
||||||
|
),
|
||||||
|
},
|
||||||
|
];
|
||||||
|
|
||||||
|
export default function Sidebar() {
|
||||||
|
const pathname = usePathname();
|
||||||
|
|
||||||
|
return (
|
||||||
|
<>
|
||||||
|
{/* Desktop sidebar */}
|
||||||
|
<aside className="fixed top-0 left-0 h-screen w-56 bg-slate-900 text-white hidden md:flex flex-col z-50">
|
||||||
|
<div className="px-5 py-5 border-b border-slate-700">
|
||||||
|
<span className="text-lg font-bold tracking-tight">AutoTrader</span>
|
||||||
|
</div>
|
||||||
|
<nav className="flex-1 px-3 py-4 flex flex-col gap-1">
|
||||||
|
{NAV_ITEMS.map((item) => {
|
||||||
|
const active = item.href === '/'
|
||||||
|
? pathname === '/'
|
||||||
|
: pathname.startsWith(item.href);
|
||||||
|
|
||||||
|
return (
|
||||||
|
<Link
|
||||||
|
key={item.href}
|
||||||
|
href={item.href}
|
||||||
|
className={`flex items-center gap-3 px-3 py-2.5 rounded-lg text-sm font-medium transition-colors ${
|
||||||
|
active
|
||||||
|
? 'bg-slate-700 text-white'
|
||||||
|
: 'text-slate-400 hover:text-white hover:bg-slate-800'
|
||||||
|
}`}
|
||||||
|
>
|
||||||
|
{item.icon}
|
||||||
|
{item.label}
|
||||||
|
</Link>
|
||||||
|
);
|
||||||
|
})}
|
||||||
|
</nav>
|
||||||
|
</aside>
|
||||||
|
|
||||||
|
{/* Mobile bottom bar */}
|
||||||
|
<nav className="fixed bottom-0 left-0 right-0 bg-slate-900 text-white flex md:hidden items-center justify-around z-50 border-t border-slate-700 px-2 py-1 safe-bottom">
|
||||||
|
{NAV_ITEMS.map((item) => {
|
||||||
|
const active = item.href === '/'
|
||||||
|
? pathname === '/'
|
||||||
|
: pathname.startsWith(item.href);
|
||||||
|
|
||||||
|
return (
|
||||||
|
<Link
|
||||||
|
key={item.href}
|
||||||
|
href={item.href}
|
||||||
|
className={`flex flex-col items-center gap-1 px-3 py-2 rounded-lg text-[11px] font-medium transition-colors ${
|
||||||
|
active
|
||||||
|
? 'text-white'
|
||||||
|
: 'text-slate-400'
|
||||||
|
}`}
|
||||||
|
>
|
||||||
|
{item.icon}
|
||||||
|
{item.label}
|
||||||
|
</Link>
|
||||||
|
);
|
||||||
|
})}
|
||||||
|
</nav>
|
||||||
|
</>
|
||||||
|
);
|
||||||
|
}
|
||||||
+5
-1
@@ -1,5 +1,6 @@
|
|||||||
import type { Metadata } from "next";
|
import type { Metadata } from "next";
|
||||||
import "./globals.css";
|
import "./globals.css";
|
||||||
|
import Sidebar from "./components/Sidebar";
|
||||||
|
|
||||||
export const metadata: Metadata = {
|
export const metadata: Metadata = {
|
||||||
title: "AutoTrader",
|
title: "AutoTrader",
|
||||||
@@ -13,7 +14,10 @@ export default function RootLayout({
|
|||||||
}>) {
|
}>) {
|
||||||
return (
|
return (
|
||||||
<html lang="en">
|
<html lang="en">
|
||||||
<body className="antialiased">{children}</body>
|
<body className="antialiased">
|
||||||
|
<Sidebar />
|
||||||
|
<div className="md:ml-56 pb-16 md:pb-0">{children}</div>
|
||||||
|
</body>
|
||||||
</html>
|
</html>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user