Merge pull request #1 from Nezumi-2711/feat/implement-layout

Feature/ Implement the layout of the application
This commit is contained in:
2025-04-30 17:06:42 +07:00
committed by GitHub
13 changed files with 257 additions and 12 deletions
+7
View File
@@ -0,0 +1,7 @@
const AboutPage = () => {
return (
<div>AboutPage</div>
)
}
export default AboutPage
+7
View File
@@ -0,0 +1,7 @@
const ContactPage = () => {
return (
<div>Contact Page</div>
)
}
export default ContactPage
+7
View File
@@ -0,0 +1,7 @@
const FeaturesPage = () => {
return (
<div>FeaturesPage</div>
)
}
export default FeaturesPage
+11
View File
@@ -0,0 +1,11 @@
const Footer = () => {
return (
<footer className="flex border-t justify-between font-medium p-6">
<div className="flex items-center gap-2">
<p>funroad, Inc.</p>
</div>
</footer>
)
}
export default Footer
+22
View File
@@ -0,0 +1,22 @@
import { ReactNode } from 'react';
import Navbar from './navbar';
import Footer from './footer';
interface LayoutProps {
children: ReactNode;
}
const Layout = ({ children }: LayoutProps) => {
return (
<div className="flex flex-col min-h-screen">
<Navbar />
<div className="flex-1 bg-[#F4F4F0]">{children}</div>
<Footer />
</div>
);
};
export default Layout;
+65
View File
@@ -0,0 +1,65 @@
import { ScrollArea } from '@/components/ui/scroll-area';
import {
Sheet,
SheetContent,
SheetHeader,
SheetTitle,
} from '@/components/ui/sheet';
import Link from 'next/link';
import { ReactNode } from 'react';
interface NavbarItem {
href: string;
children: ReactNode;
}
interface Props {
items: NavbarItem[];
open: boolean;
onOpenChange: (open: boolean) => void;
}
const NavbarSidebar = ({ items, open, onOpenChange }: Props) => {
return (
<Sheet open={open} onOpenChange={onOpenChange}>
<SheetContent side="left" className="p-0 transition-none">
<SheetHeader className="p-4 border-b">
<SheetTitle>Menu</SheetTitle>
</SheetHeader>
<ScrollArea className="flex flex-col overflow-y-auto h-full pb-2">
{items.map((item) => (
<Link
key={item.href}
href={item.href}
className="w-full text-left p-4 hover:bg-black hover:text-white flex items-center text-base font-medium"
onClick={() => onOpenChange(false)}
>
{item.children}
</Link>
))}
<div className="border-t">
<Link
href="/sign-in"
className="w-full text-left p-4 hover:bg-black hover:text-white flex items-center text-base font-medium"
onClick={() => onOpenChange(false)}
>
Log in
</Link>
<Link
href="/sign-up"
className="w-full text-left p-4 hover:bg-black hover:text-white flex items-center text-base font-medium"
onClick={() => onOpenChange(false)}
>
Start Selling
</Link>
</div>
</ScrollArea>
</SheetContent>
</Sheet>
);
};
export default NavbarSidebar;
+120
View File
@@ -0,0 +1,120 @@
'use client';
import { ReactNode, useState } from 'react';
import Link from 'next/link';
import { Poppins } from 'next/font/google';
import { MenuIcon } from 'lucide-react';
import { usePathname } from 'next/navigation';
import { cn } from '@/lib/utils';
import { Button } from '@/components/ui/button';
import NavbarSidebar from './navbar-sidebar';
const poppins = Poppins({
subsets: ['latin'],
weight: ['700'],
});
interface NavbarItemProps {
href: string;
children: ReactNode;
isActive?: boolean;
}
const navbarItems = [
{
href: '/',
children: 'Home',
},
{
href: '/about',
children: 'About',
},
{
href: '/features',
children: 'Features',
},
{
href: '/pricing',
children: 'Pricing',
},
{
href: '/contact',
children: 'Contact',
},
];
const NavbarItem = ({ href, children, isActive }: NavbarItemProps) => {
return (
<Button
asChild
variant="outline"
className={cn(
'bg-transparent hover:bg-transparent rounded-full hover:border-primary border-transparent px-3.5 text-lg',
isActive && 'bg-black text-white hover:bg-black hover:text-white'
)}
>
<Link href={href}>{children}</Link>
</Button>
);
};
const Navbar = () => {
const pathname = usePathname();
const [isSidebarOpen, setIsSidebarOpen] = useState(false);
return (
<nav className="h-20 flex border-b justify-between font-medium bg-white">
<Link href="/" className="pl-6 flex items-center">
<span className={cn('text-5xl font-semibold', poppins.className)}>
funroad
</span>
</Link>
<NavbarSidebar
items={navbarItems}
open={isSidebarOpen}
onOpenChange={setIsSidebarOpen}
/>
<div className="items-center gap-4 hidden lg:flex">
{navbarItems.map((item) => (
<NavbarItem
key={item.href}
href={item.href}
isActive={pathname === item.href}
>
{item.children}
</NavbarItem>
))}
</div>
<div className="hidden lg:flex">
<Button
asChild
variant="secondary"
className="border-l border-t-0 border-b-0 border-r-0 px-12 h-full rounded-none bg-white hover:bg-pink-400 transition-colors text-lg"
>
<Link href="/sign-in">Log in</Link>
</Button>
<Button
asChild
variant="secondary"
className="border-l border-t-0 border-b-0 border-r-0 px-12 h-full rounded-none bg-black text-white hover:bg-pink-400 hover:text-black transition-colors text-lg"
>
<Link href="/sign-up">Start Selling</Link>
</Button>
</div>
<div className='flex lg:hidden items-center justify-center'>
<Button variant="ghost" className="size-12 border-transparent bg-white" onClick={() => setIsSidebarOpen(true)}>
<MenuIcon />
</Button>
</div>
</nav>
);
};
export default Navbar;
+7
View File
@@ -0,0 +1,7 @@
export default function Home() {
return (
<div>
Home page
</div>
);
}
+7
View File
@@ -0,0 +1,7 @@
const PricingPage = () => {
return (
<div>PricingPage</div>
)
}
export default PricingPage
-9
View File
@@ -1,9 +0,0 @@
import { Button } from "@/components/ui/button";
export default function Home() {
return (
<div>
<Button variant="elevated">Hello World</Button>
</div>
);
}
+1
View File
@@ -15,6 +15,7 @@ function Checkbox({
data-slot="checkbox"
className={cn(
"peer border-input dark:bg-input/30 data-[state=checked]:bg-primary data-[state=checked]:text-primary-foreground dark:data-[state=checked]:bg-primary data-[state=checked]:border-primary focus-visible:border-ring focus-visible:ring-ring/50 aria-invalid:ring-destructive/20 dark:aria-invalid:ring-destructive/40 aria-invalid:border-destructive size-4 shrink-0 rounded-[4px] border shadow-xs transition-shadow outline-none focus-visible:ring-[3px] disabled:cursor-not-allowed disabled:opacity-50",
"bg-white",
className
)}
{...props}
+1 -1
View File
@@ -15,7 +15,7 @@ function Progress({
data-slot="progress"
className={cn(
"relative h-3 w-full overflow-hidden rounded-full",
"border bg-transparent",
"border bg-white",
className
)}
{...props}
+2 -2
View File
@@ -7,8 +7,8 @@ function Textarea({ className, ...props }: React.ComponentProps<"textarea">) {
<textarea
data-slot="textarea"
className={cn(
"border-input placeholder:text-muted-foreground focus-visible:border-ring focus-visible:ring-ring/50 aria-invalid:ring-destructive/20 dark:aria-invalid:ring-destructive/40 aria-invalid:border-destructive dark:bg-input/30 flex field-sizing-content min-h-16 w-full rounded-md border bg-transparent px-3 py-2 text-base transition-[color,box-shadow] outline-none focus-visible:ring-[3px] disabled:cursor-not-allowed disabled:opacity-50",
"md:text-base",
"border-input placeholder:text-muted-foreground focus-visible:border-ring focus-visible:ring-ring/50 aria-invalid:ring-destructive/20 dark:aria-invalid:ring-destructive/40 aria-invalid:border-destructive dark:bg-input/30 flex field-sizing-content min-h-16 w-full rounded-md border px-3 py-2 text-base transition-[color,box-shadow] outline-none focus-visible:ring-[3px] disabled:cursor-not-allowed disabled:opacity-50",
"md:text-base bg-white",
className
)}
{...props}