Skip to content

Commit

Permalink
Update nav menu for desktop and mobile
Browse files Browse the repository at this point in the history
  • Loading branch information
ruchernchong committed Sep 16, 2024
1 parent 067792a commit 5934b0d
Show file tree
Hide file tree
Showing 3 changed files with 155 additions and 121 deletions.
264 changes: 143 additions & 121 deletions app/components/NavMenu.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,17 +3,9 @@
import * as React from "react";
import { useState } from "react";
import Link from "next/link";
import {
Battery,
Droplet,
Fuel,
type LucideIcon,
Menu,
Search,
TrendingUp,
Zap,
} from "lucide-react";
import { ArrowRight, type LucideIcon, Menu, Search } from "lucide-react";
import { BrandLogo } from "@/components/BrandLogo";
import Typography from "@/components/Typography";
import { UnreleasedFeature } from "@/components/UnreleasedFeature";
import {
Accordion,
Expand All @@ -34,104 +26,106 @@ import {
} from "@/components/ui/navigation-menu";
import { ScrollArea } from "@/components/ui/scroll-area";
import { Sheet, SheetContent, SheetTrigger } from "@/components/ui/sheet";
import { Tabs, TabsContent, TabsList, TabsTrigger } from "@/components/ui/tabs";
import { FUEL_TYPE_LINKS, VEHICLE_TYPE_LINKS } from "@/config";
import { cn } from "@/lib/utils";

export const NavMenu = () => {
return (
<NavigationMenu>
<NavigationMenuList>
export const NavMenu = () => (
<NavigationMenu>
<NavigationMenuList>
<NavigationMenuItem>
<Link href="/cars" legacyBehavior passHref>
<NavigationMenuLink className={navigationMenuTriggerStyle()}>
Monthly
</NavigationMenuLink>
</Link>
</NavigationMenuItem>
<NavigationMenuItem>
<NavigationMenuTrigger>Fuel Types</NavigationMenuTrigger>
<NavigationMenuContent>
<ul className="grid gap-3 p-6 md:w-[400px] lg:w-[500px] lg:grid-cols-[.75fr_1fr]">
{/*<li className="row-span-4">*/}
{/* <NavigationMenuLink asChild>*/}
{/* <Link*/}
{/* className="flex h-full w-full select-none flex-col justify-end rounded-md bg-gradient-to-b from-muted/50 to-muted p-6 no-underline outline-none focus:shadow-md"*/}
{/* href="/cars"*/}
{/* >*/}
{/* <TrendingUp className="h-6 w-6 stroke-primary" />*/}
{/* <div className="mb-2 mt-4 text-lg font-medium">Monthly</div>*/}
{/* <p className="text-sm leading-tight text-muted-foreground">*/}
{/* Car registration data for the latest month and previous*/}
{/* months, broken down by fuel type and vehicle type.*/}
{/* </p>*/}
{/* </Link>*/}
{/* </NavigationMenuLink>*/}
{/*</li>*/}
{FUEL_TYPE_LINKS.map(({ label, description, href, icon }) => (
<ListItem key={label} href={href} title={label} icon={icon}>
{description}
</ListItem>
))}
</ul>
</NavigationMenuContent>
</NavigationMenuItem>
<NavigationMenuItem>
<NavigationMenuTrigger>Vehicle Types</NavigationMenuTrigger>
<NavigationMenuContent>
<ul className="grid gap-3 p-6 md:w-[400px] lg:w-[500px] lg:grid-cols-[.75fr_1fr]">
{VEHICLE_TYPE_LINKS.map(({ label, description, href, icon }) => (
<ListItem key={label} href={href} title={label} icon={icon}>
{description}
</ListItem>
))}
</ul>
</NavigationMenuContent>
</NavigationMenuItem>
<UnreleasedFeature>
<NavigationMenuItem>
<NavigationMenuTrigger>Cars</NavigationMenuTrigger>
<NavigationMenuTrigger>COE</NavigationMenuTrigger>
<NavigationMenuContent>
<ul className="grid gap-3 p-6 md:w-[400px] lg:w-[500px] lg:grid-cols-[.75fr_1fr]">
<li className="row-span-4">
<NavigationMenuLink asChild>
<Link
className="flex h-full w-full select-none flex-col justify-end rounded-md bg-gradient-to-b from-muted/50 to-muted p-6 no-underline outline-none focus:shadow-md"
href="/cars"
>
<TrendingUp className="h-6 w-6 stroke-primary" />
<div className="mb-2 mt-4 text-lg font-medium">Monthly</div>
<p className="text-sm leading-tight text-muted-foreground">
Car registration data for the latest month and previous
months, broken down by fuel type and vehicle type.
</p>
</Link>
</NavigationMenuLink>
</li>
<ListItem href="/cars/petrol" title="Petrol" icon={Fuel}>
Petrol Cars
<ListItem href="/coe/prices" title="Latest COE">
Latest
</ListItem>
<ListItem href="/cars/hybrid" title="Hybrid" icon={Zap}>
Hybrid Cars
</ListItem>
<ListItem href="/cars/electric" title="Electric" icon={Battery}>
Electric Cars
</ListItem>
<ListItem href="/cars/diesel" title="Diesel" icon={Droplet}>
Diesel Cars
<ListItem href="/coe/prices" title="Historical COE Trends">
Historical
</ListItem>
</ul>
</NavigationMenuContent>
</NavigationMenuItem>
<UnreleasedFeature>
<NavigationMenuItem>
<NavigationMenuTrigger>COE</NavigationMenuTrigger>
<NavigationMenuContent>
<ul className="grid gap-3 p-6 md:w-[400px] lg:w-[500px] lg:grid-cols-[.75fr_1fr]">
<ListItem href="/coe/prices" title="Latest COE">
Latest
</ListItem>
<ListItem href="/coe/prices" title="Historical COE Trends">
Historical
</ListItem>
</ul>
</NavigationMenuContent>
</NavigationMenuItem>
</UnreleasedFeature>
</NavigationMenuList>
</NavigationMenu>
);
};
</UnreleasedFeature>
</NavigationMenuList>
</NavigationMenu>
);

export const DesktopNavMenu = () => {
return (
<div className="container hidden items-center justify-between p-4 lg:flex">
<nav className="flex items-center gap-x-4">
<Link href="/" className="flex items-center gap-x-2">
<BrandLogo />
</Link>
<NavMenu />
</nav>
<UnreleasedFeature>
<div className="flex items-center gap-x-4">
<div className="relative">
<Input
type="search"
placeholder="Search..."
className="border border-gray-300 pl-10 focus:border-transparent focus:outline-none focus:ring-2 focus:ring-blue-500"
/>
<div className="pointer-events-none absolute inset-y-0 left-0 flex items-center pl-3">
<Search className="h-4 w-4 text-gray-400" />
</div>
export const DesktopNavMenu = () => (
<div className="container hidden items-center justify-between p-4 lg:flex">
<nav className="flex items-center gap-x-4">
<Link href="/" className="flex items-center gap-x-2">
<BrandLogo />
</Link>
<NavMenu />
</nav>
<UnreleasedFeature>
<div className="flex items-center gap-x-4">
<div className="relative">
<Input
type="search"
placeholder="Search..."
className="border border-gray-300 pl-10 focus:border-transparent focus:outline-none focus:ring-2 focus:ring-blue-500"
/>
<div className="pointer-events-none absolute inset-y-0 left-0 flex items-center pl-3">
<Search className="h-4 w-4 text-gray-400" />
</div>
</div>
</UnreleasedFeature>
</div>
);
};
</div>
</UnreleasedFeature>
</div>
);

export const MobileNavMenu = () => {
const [isOpen, setIsOpen] = useState(false);

const links = [
{ title: "Overview", link: "/cars" },
{ title: "Petrol Cars", link: "/cars/petrol" },
{ title: "Hybrid Cars", link: "/cars/hybrid" },
{ title: "Electric Cars", link: "/cars/electric" },
{ title: "Diesel Cars", link: "/cars/diesel" },
];

return (
<div className="flex items-center justify-between px-4 py-3 lg:hidden">
<Link href="/" className="flex items-center gap-x-2">
Expand All @@ -143,7 +137,7 @@ export const MobileNavMenu = () => {
<Menu className="h-6 w-6" />
</Button>
</SheetTrigger>
<SheetContent side="left" className="w-[300px] sm:w-[400px]">
<SheetContent side="left" className="w-full">
<div className="mb-6 flex items-center justify-between">
<Link
href="/"
Expand All @@ -163,35 +157,63 @@ export const MobileNavMenu = () => {
/>
</div>
</UnreleasedFeature>
<ScrollArea>
<Accordion type="single" collapsible>
<AccordionItem value="cars">
<AccordionTrigger>Cars</AccordionTrigger>
<AccordionContent>
<nav className="flex flex-col space-y-4">
{links.map(({ title, link }) => (
<Link
key={title}
href={link}
className="text-blue-600 hover:underline"
onClick={() => setIsOpen(false)}
>
{title}
</Link>
))}
</nav>
</AccordionContent>
</AccordionItem>
</Accordion>
<nav className="mt-4 flex flex-col space-y-4">
<Link
href="/coe/prices"
className="text-gray-700 hover:text-blue-600"
>
COE
</Link>
</nav>
</ScrollArea>
<Tabs defaultValue="cars">
<TabsList>
<TabsTrigger value="cars">Cars</TabsTrigger>
<UnreleasedFeature>
<TabsTrigger value="coe">COE</TabsTrigger>
</UnreleasedFeature>
</TabsList>
<TabsContent value="cars">
<ScrollArea>
<Link href="/cars" onClick={() => setIsOpen(false)}>
<Typography.H4 className="flex items-center gap-1">
Monthly <ArrowRight className="h-6 w-6" />
</Typography.H4>
</Link>
<Accordion type="multiple">
<AccordionItem value="fuelType">
<AccordionTrigger>Fuel Type</AccordionTrigger>
<AccordionContent>
<div className="flex flex-col space-y-4">
{FUEL_TYPE_LINKS.map(
({ label, description, href, icon: Icon }) => (
<Link
key={label}
href={href}
onClick={() => setIsOpen(false)}
>
<div className="flex items-center gap-2">
{Icon && <Icon className="h-4 w-4" />}
<div>{label}</div>
</div>
<Typography.Muted>{description}</Typography.Muted>
</Link>
),
)}
</div>
</AccordionContent>
</AccordionItem>
<AccordionItem value="vehicleType">
<AccordionTrigger>Vehicle Type</AccordionTrigger>
<AccordionContent>
<div className="flex flex-col space-y-4">
{VEHICLE_TYPE_LINKS.map(({ label, href }) => (
<Link
key={label}
href={href}
onClick={() => setIsOpen(false)}
>
{label}
</Link>
))}
</div>
</AccordionContent>
</AccordionItem>
</Accordion>
</ScrollArea>
</TabsContent>
</Tabs>
</SheetContent>
</Sheet>
</div>
Expand Down
9 changes: 9 additions & 0 deletions config/index.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import { Battery, Droplet, Fuel, Zap } from "lucide-react";
import type { AppEnv, LinkItem } from "@/types";

const DOMAIN_NAME = "sgcarstrends.com";
Expand Down Expand Up @@ -48,19 +49,27 @@ export const FEATURE_FLAG_UNRELEASED =
export const FUEL_TYPE_LINKS: LinkItem[] = [
{
label: "Petrol",
description: "Internal Combustion Engine (ICE) vehicles",
href: "/cars/petrol",
icon: Fuel,
},
{
label: "Hybrid",
description: "Includes Petrol, Diesel and Plug-In types",
href: "/cars/hybrid",
icon: Zap,
},
{
label: "Electric",
description: "Battery Electric Vehicles (BEV)",
href: "/cars/electric",
icon: Battery,
},
{
label: "Diesel",
description: "Compression-ignition engine vehicles",
href: "/cars/diesel",
icon: Droplet,
},
].sort((a, b) => a.label.localeCompare(b.label));

Expand Down
3 changes: 3 additions & 0 deletions types/index.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import { FUEL_TYPE } from "@/config";
import type { LucideIcon } from "lucide-react";

export type VEHICLE_TYPE =
| "Coupe/ Convertible"
Expand Down Expand Up @@ -83,4 +84,6 @@ export enum AppEnv {
export interface LinkItem {
label: string;
href: string;
description?: string;
icon?: LucideIcon;
}

0 comments on commit 5934b0d

Please sign in to comment.