From f35fd8b09ada80ad83f5ce0556df470b6bf94a64 Mon Sep 17 00:00:00 2001 From: Nam Doan Date: Tue, 25 Nov 2025 16:38:53 +0700 Subject: [PATCH] feat: create navigation menu for 3bear design --- config/nam.3bear.design.json | 202 ++++++++++++++---- .../components/navigation-menu/index.tsx | 125 +++++++++++ src/modules/layout/templates/vt-nav/index.tsx | 2 +- src/vibentec/component-map.tsx | 6 + tailwind.config.js | 40 ++++ 5 files changed, 331 insertions(+), 44 deletions(-) create mode 100644 src/modules/layout/components/navigation-menu/index.tsx diff --git a/config/nam.3bear.design.json b/config/nam.3bear.design.json index 6e4f481..9e6edbe 100644 --- a/config/nam.3bear.design.json +++ b/config/nam.3bear.design.json @@ -24,7 +24,7 @@ "className": "" } ], - "className": "bg-[#009b93] text-white" + "className": "sticky top-0 z-20 bg-[#009b93] text-white" } } }, @@ -55,79 +55,195 @@ }, "children": [ { - "DropdownMenus": { + "NavMenu": { "props": { "label": "Shop", - "className": "hover:text-ui-fg-base flex items-center gap-2", + "className": "", "data-testid": "nav-categories-link", "isShowArrow": true }, - "children": [ + "menuItems": [ { - "DropdownMenuItems": { - "props": { - "label": "All Categories", - "className": "hover:text-ui-fg-base", - "data-testid": "nav-all-categories-link" + "title": { + "text": "Categories", + "className": "text-[#003F31] text-xl font-bold" + }, + "links": [ + { + "label": "Overnight Oats", + "href": "/categories/overnight-oats", + "className": "text-red-500" + }, + { + "label": "Porridge", + "href": "/categories/porridge" + }, + { + "label": "Cereals", + "href": "/categories/cereals" + }, + { + "label": "Granola", + "href": "/categories/granola" + }, + { + "label": "Glasses & Bowls", + "href": "/categories/glasses-bowls" + }, + { + "label": "Oat Bars", + "href": "/categories/oat-bars" + }, + { + "label": "Nut butters", + "href": "/categories/nut-butters" } - } + ] }, { - "DropdownMenuItems": { - "props": { - "label": "New Arrivals", - "className": "hover:text-ui-fg-base flex items-center gap-2", - "data-testid": "nav-new-arrivals-link" + "title": { + "text": "Specials", + "className": "text-[#003F31] text-xl font-bold" + }, + "links": [ + { + "label": "Advent calendar ✨", + "href": "/collections/advent-calendar" + }, + { + "label": "Saver subscription", + "href": "/collections/saver-subscription" + }, + { + "label": "bestseller", + "href": "/collections/bestseller" + }, + { + "label": "New 🔥", + "href": "/collections/new" + }, + { + "label": "Bluey Kidsrange", + "href": "/collections/bluey-kidsrange" + }, + { + "label": "Value sets", + "href": "/collections/value-sets" + }, + { + "label": "Sale", + "href": "/collections/sale" } - } + ] }, { - "DropdownMenuItems": { - "props": { - "label": "Best Sellers", - "className": "hover:text-ui-fg-base flex items-center gap-2", - "data-testid": "nav-best-sellers-link" + "title": { + "text": "All products", + "className": "text-[#003F31] text-xl font-bold" + }, + "links": [ + { + "label": "Shop all", + "href": "/store" } - } + ] } ] } }, { - "DropdownMenus": { + "NavMenu": { "props": { "label": "About us", - "className": "hover:text-ui-fg-base flex items-center gap-2", + "className": "", "data-testid": "nav-categories-link", "isShowArrow": true }, - "children": [ + "menuItems": [ { - "DropdownMenuItems": { - "props": { - "label": "All Categories", - "className": "hover:text-ui-fg-base flex items-center gap-2", - "data-testid": "nav-all-categories-link" + "title": { + "text": "About us", + "className": "text-[#003F31] text-xl font-bold" + }, + "links": [ + { + "label": "Check", + "href": "/categories/overnight-oats", + "className": "text-red-500" + }, + { + "label": "Porridge", + "href": "/categories/porridge" + }, + { + "label": "Cereals", + "href": "/categories/cereals" + }, + { + "label": "Granola", + "href": "/categories/granola" + }, + { + "label": "Glasses & Bowls", + "href": "/categories/glasses-bowls" + }, + { + "label": "Oat Bars", + "href": "/categories/oat-bars" + }, + { + "label": "Nut butters", + "href": "/categories/nut-butters" } - } + ] }, { - "DropdownMenuItems": { - "props": { - "label": "New Arrivals", - "className": "hover:text-ui-fg-base flex items-center gap-2", - "data-testid": "nav-new-arrivals-link" + "title": { + "text": "Specials", + "className": "text-[#003F31] text-xl font-bold" + }, + "links": [ + { + "label": "Advent calendar ✨", + "href": "/collections/advent-calendar" + }, + { + "label": "Saver subscription", + "href": "/collections/saver-subscription" + }, + { + "label": "bestseller", + "href": "/collections/bestseller" + }, + { + "label": "New 🔥", + "href": "/collections/new" + }, + { + "label": "Bluey Kidsrange", + "href": "/collections/bluey-kidsrange" + }, + { + "label": "Value sets", + "href": "/collections/value-sets" + }, + { + "label": "Sale", + "href": "/collections/sale" } - } + ] }, { - "DropdownMenuItems": { - "props": { - "label": "Best Sellers", - "className": "hover:text-ui-fg-base", - "data-testid": "nav-best-sellers-link" + "title": { + "text": "All products", + "className": "text-[#003F31] text-xl font-bold" + }, + "links": [ + { + "label": "Shop all", + "href": "/store" } - } + ] } ] } diff --git a/src/modules/layout/components/navigation-menu/index.tsx b/src/modules/layout/components/navigation-menu/index.tsx new file mode 100644 index 0000000..9578465 --- /dev/null +++ b/src/modules/layout/components/navigation-menu/index.tsx @@ -0,0 +1,125 @@ +"use client" +import * as React from "react" +import LocalizedClientLink from "@modules/common/components/localized-client-link" +import { clx } from "@medusajs/ui" +import { ChevronDownMini } from "@medusajs/icons" + +interface NavigationMenuProps { + props: { + label: string, + className: string, + "data-testid": string, + isShowArrow: boolean + }, + menuItems: MenuSection[] +} +type MenuSection = { + title: { text: string; className?: string } + links: MenuLink[] +} +type MenuLink = { label: string; href: string; className?: string } + +// Structured menu data used to map UI +const menuSections: MenuSection[] = [ + { + title: { text: "Categories", className: "text-red" }, + links: [ + { + label: "Overnight Oats", + href: "/categories/overnight-oats", + className: "text-red", + }, + { label: "Porridge", href: "/categories/porridge" }, + { label: "Cereals", href: "/categories/cereals" }, + { label: "Granola", href: "/categories/granola" }, + { label: "Glasses & Bowls", href: "/categories/glasses-bowls" }, + { label: "Oat Bars", href: "/categories/oat-bars" }, + { label: "Nut butters", href: "/categories/nut-butters" }, + ], + }, + { + title: { text: "Specials" }, + links: [ + { label: "Advent calendar ✨", href: "/collections/advent-calendar" }, + { label: "Saver subscription", href: "/collections/saver-subscription" }, + { label: "bestseller", href: "/collections/bestseller" }, + { label: "New 🔥", href: "/collections/new" }, + { label: "Bluey Kidsrange", href: "/collections/bluey-kidsrange" }, + { label: "Value sets", href: "/collections/value-sets" }, + { label: "Sale", href: "/collections/sale" }, + ], + }, + { + title: { text: "All products" }, + links: [{ label: "Shop all", href: "/store" }], + }, +] + +const MenuLinkItem = ({ href, label, className }: MenuLink) => ( +
  • + +
    {label}
    +
    +
  • +) + +const MenuSectionItem = ({ title, links }: MenuSection) => ( +
    +
    + {title.text} +
    + +
    +) +export default function NavigationMenu({ + props, + menuItems = menuSections, +}: NavigationMenuProps) { + return ( +
    + + {props.label} {props?.isShowArrow ? ( + + + + ) : null} + + +
    +
    +
    + {menuItems.map((section) => ( + + ))} +
    +
    +
    +
    + ) +} diff --git a/src/modules/layout/templates/vt-nav/index.tsx b/src/modules/layout/templates/vt-nav/index.tsx index a60277d..d40ab7e 100644 --- a/src/modules/layout/templates/vt-nav/index.tsx +++ b/src/modules/layout/templates/vt-nav/index.tsx @@ -9,7 +9,7 @@ export default async function VtNav({ nodes, context, className }: DynamicLayout const regions = await listRegions().then((regions: StoreRegion[]) => regions) return ( -
    +