feat: create components and map with data json file of 3bear design
This commit is contained in:
parent
c8853bac1c
commit
b76719fb32
|
|
@ -55,6 +55,138 @@
|
|||
"objectFit": "contain"
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"VtMegaMenu": {
|
||||
"config": {
|
||||
"navLabel": {
|
||||
"text": "Shop",
|
||||
"className": "font-bold text-[1rem] text-[#003F31] flex items-center mr-8 gap-1 hover:text-[#009b93]",
|
||||
"isShowArrow": true
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"Dropdown": {
|
||||
"config": {
|
||||
"trigger": {
|
||||
"text": "Über Uns",
|
||||
"className": "font-bold text-[1rem] text-[#003F31] flex items-center mr-8 gap-1 hover:text-[#009b93]",
|
||||
"isShowArrow": true
|
||||
},
|
||||
"items": [
|
||||
{
|
||||
"text": "Unser Unternehmen",
|
||||
"href": "/"
|
||||
},
|
||||
{
|
||||
"text": "Loren ipsum",
|
||||
"href": "/"
|
||||
},
|
||||
{
|
||||
"text": "Not a Link"
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"Dropdown": {
|
||||
"config": {
|
||||
"trigger": {
|
||||
"text": "Über unsere Produkte",
|
||||
"className": "font-bold text-[1rem] text-[#003F31] flex items-center mr-8 gap-1 hover:text-[#009b93]",
|
||||
"isShowArrow": true
|
||||
},
|
||||
"items": [
|
||||
{
|
||||
"text": "Unser Unternehmen",
|
||||
"href": "/"
|
||||
},
|
||||
{
|
||||
"text": "Loren ipsum",
|
||||
"href": "/"
|
||||
},
|
||||
{
|
||||
"text": "Not a Link"
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"Link": {
|
||||
"config": {
|
||||
"label": "Rezepte",
|
||||
"href": "/",
|
||||
"className": "font-bold text-[1rem] text-[#003F31] flex items-center mr-8 gap-1 hover:text-[#009b93]"
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"Link": {
|
||||
"config": {
|
||||
"label": "Triff Harry Kane",
|
||||
"href": "/",
|
||||
"className": "font-bold text-[1rem] text-[#003F31] flex items-center gap-1 hover:text-[#009b93]"
|
||||
}
|
||||
}
|
||||
}
|
||||
],
|
||||
"right": [
|
||||
{
|
||||
"Dropdown": {
|
||||
"config": {
|
||||
"trigger": {
|
||||
"icon": "https://upload.wikimedia.org/wikipedia/commons/thumb/b/ba/Flag_of_Germany.svg/1200px-Flag_of_Germany.svg.png",
|
||||
"text": "Germany (EUR)",
|
||||
"className": "font-bold text-[1rem] text-[#003F31] flex items-center gap-1 hover:text-[#009b93]",
|
||||
"isShowArrow": true
|
||||
},
|
||||
"items": [
|
||||
{
|
||||
"icon": "https://upload.wikimedia.org/wikipedia/commons/thumb/b/ba/Flag_of_Germany.svg/1200px-Flag_of_Germany.svg.png",
|
||||
"text": "Germany (EUR)",
|
||||
"href": "/"
|
||||
},
|
||||
{
|
||||
"icon": "https://upload.wikimedia.org/wikipedia/commons/2/20/Flag_of_the_Netherlands.svg",
|
||||
"text": "Netherlands (EUR)",
|
||||
"href": "/"
|
||||
},
|
||||
{
|
||||
"icon": "https://upload.wikimedia.org/wikipedia/commons/8/88/Flag_of_Australia_%28converted%29.svg",
|
||||
"text": "Australia (AUD)",
|
||||
"href": "/"
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"IconButton": {
|
||||
"config": {
|
||||
"variant": "search",
|
||||
"className": "shadow-none"
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"IconButton": {
|
||||
"config": {
|
||||
"variant": "user",
|
||||
"className": "shadow-none"
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"VtCartButton": {
|
||||
"config": {
|
||||
"variant": "button",
|
||||
"className": "shadow-none"
|
||||
}
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,13 +1,38 @@
|
|||
import LocalizedClientLink from "@modules/common/components/localized-client-link"
|
||||
import { LayoutComponentDefinition, LayoutContext } from "vibentec/component-map";
|
||||
import { clx } from "@medusajs/ui"
|
||||
import { Suspense } from "react";
|
||||
import CartButton from "@modules/layout/components/cart-button";
|
||||
import {
|
||||
LayoutComponentDefinition,
|
||||
LayoutContext,
|
||||
} from "vibentec/component-map"
|
||||
import { clx, IconButton } from "@medusajs/ui"
|
||||
import { Suspense } from "react"
|
||||
import CartButton from "@modules/layout/components/cart-button"
|
||||
import { ShoppingBag } from "@medusajs/icons"
|
||||
|
||||
export const VtCartButton = ({ nodes, context }: { nodes: LayoutComponentDefinition; context: LayoutContext }) => {
|
||||
const CartIconButtonComponent = ({ className }: { className?: string }) => {
|
||||
return (
|
||||
<IconButton className={className}>
|
||||
<ShoppingBag />
|
||||
</IconButton>
|
||||
)
|
||||
}
|
||||
|
||||
export const VtCartButton = ({
|
||||
nodes,
|
||||
context,
|
||||
}: {
|
||||
nodes: LayoutComponentDefinition
|
||||
context: LayoutContext
|
||||
}) => {
|
||||
const props = nodes.config ?? {}
|
||||
const className = clx("hover:text-ui-fg-base flex gap-2", props.className)
|
||||
|
||||
const variants = {
|
||||
link: <CartButton />,
|
||||
button: <CartIconButtonComponent className={className} />,
|
||||
}
|
||||
if (!props.variant) return null
|
||||
const fallBackComp = variants[props.variant as keyof typeof variants]
|
||||
|
||||
return (
|
||||
<Suspense
|
||||
fallback={
|
||||
|
|
@ -20,7 +45,7 @@ export const VtCartButton = ({ nodes, context }: { nodes: LayoutComponentDefinit
|
|||
</LocalizedClientLink>
|
||||
}
|
||||
>
|
||||
<CartButton />
|
||||
{fallBackComp}
|
||||
</Suspense>
|
||||
)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -0,0 +1,70 @@
|
|||
"use client"
|
||||
import { DropdownMenu } from "@medusajs/ui"
|
||||
import LocalizedClientLink from "@modules/common/components/localized-client-link"
|
||||
import ChevronDown from "@modules/common/icons/chevron-down"
|
||||
import {
|
||||
LayoutComponentDefinition,
|
||||
LayoutContext,
|
||||
} from "@vibentec/component-map"
|
||||
|
||||
export default function VtDropdown({
|
||||
nodes,
|
||||
context,
|
||||
}: {
|
||||
nodes: LayoutComponentDefinition
|
||||
context: LayoutContext
|
||||
}) {
|
||||
const props = nodes.config ?? {}
|
||||
if (!props.trigger.text || props.items.length === 0) {
|
||||
return null
|
||||
}
|
||||
return (
|
||||
<DropdownMenu>
|
||||
<DropdownMenu.Trigger
|
||||
className={props.trigger.className + " flex items-center gap-1"}
|
||||
>
|
||||
{props.trigger.icon && (
|
||||
<img
|
||||
src={props.trigger.icon}
|
||||
alt={props.trigger.text}
|
||||
className="w-5 h-5 rounded-[50%] mr-3"
|
||||
/>
|
||||
)}
|
||||
{props.trigger.text} {props.trigger.isShowArrow && <ChevronDown />}
|
||||
</DropdownMenu.Trigger>
|
||||
<DropdownMenu.Content>
|
||||
{props.items.map(
|
||||
(
|
||||
item: {
|
||||
text: string
|
||||
className?: string
|
||||
href?: string
|
||||
icon?: string
|
||||
},
|
||||
index: number
|
||||
) => (
|
||||
<DropdownMenu.Item
|
||||
key={item.text + index}
|
||||
className={item.className || ""}
|
||||
>
|
||||
{item.icon && (
|
||||
<img
|
||||
src={item.icon}
|
||||
alt={item.text}
|
||||
className="w-5 h-5 rounded-[50%] mr-3"
|
||||
/>
|
||||
)}
|
||||
{item.href ? (
|
||||
<LocalizedClientLink href={item.href}>
|
||||
{item.text}
|
||||
</LocalizedClientLink>
|
||||
) : (
|
||||
item.text
|
||||
)}
|
||||
</DropdownMenu.Item>
|
||||
)
|
||||
)}
|
||||
</DropdownMenu.Content>
|
||||
</DropdownMenu>
|
||||
)
|
||||
}
|
||||
|
|
@ -1,19 +1,34 @@
|
|||
import { LayoutComponentDefinition, LayoutContext } from "vibentec/component-map";
|
||||
import React, { Suspense } from "react";
|
||||
import SkeletonMegaMenu from "@modules/skeletons/components/vt-skeleton-mega-menu";
|
||||
import MegaMenuWrapper from "@modules/layout/components/vt-mega-menu/mega-menu-wrapper";
|
||||
import {
|
||||
LayoutComponentDefinition,
|
||||
LayoutContext,
|
||||
} from "vibentec/component-map"
|
||||
import React, { Suspense } from "react"
|
||||
import SkeletonMegaMenu from "@modules/skeletons/components/vt-skeleton-mega-menu"
|
||||
import MegaMenuWrapper from "@modules/layout/components/vt-mega-menu/mega-menu-wrapper"
|
||||
|
||||
export default function VtMegaMenu({ nodes, context }: { nodes: LayoutComponentDefinition; context: LayoutContext }) {
|
||||
interface MegaMenuProps {
|
||||
navLabel: {
|
||||
text: string
|
||||
className?: string
|
||||
}
|
||||
}
|
||||
export default function VtMegaMenu({
|
||||
nodes,
|
||||
context,
|
||||
}: {
|
||||
nodes: LayoutComponentDefinition
|
||||
context: LayoutContext
|
||||
}) {
|
||||
const { navLabel } = nodes.config as MegaMenuProps ?? {}
|
||||
return (
|
||||
<nav>
|
||||
<ul className="space-x-4 hidden small:flex">
|
||||
<li>
|
||||
<Suspense fallback={<SkeletonMegaMenu />}>
|
||||
<MegaMenuWrapper />
|
||||
<MegaMenuWrapper navLabel={navLabel} />
|
||||
</Suspense>
|
||||
</li>
|
||||
</ul>
|
||||
</nav>
|
||||
)
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -1,10 +1,12 @@
|
|||
import { listCategories } from "@lib/data/categories"
|
||||
import MegaMenu from "./mega-menu"
|
||||
|
||||
export async function MegaMenuWrapper() {
|
||||
|
||||
|
||||
export async function MegaMenuWrapper({ navLabel }: { navLabel: { text: string; className?: string } }) {
|
||||
const categories = await listCategories().catch(() => [])
|
||||
|
||||
return <MegaMenu categories={categories} />
|
||||
return <MegaMenu navLabel={navLabel} categories={categories} />
|
||||
}
|
||||
|
||||
export default MegaMenuWrapper
|
||||
|
|
|
|||
|
|
@ -3,12 +3,16 @@
|
|||
import { HttpTypes } from "@medusajs/types"
|
||||
import { clx } from "@medusajs/ui"
|
||||
import LocalizedClientLink from "@modules/common/components/localized-client-link"
|
||||
import ChevronDown from "@modules/common/icons/chevron-down"
|
||||
import { usePathname } from "next/navigation"
|
||||
import { useEffect, useState } from "react"
|
||||
|
||||
|
||||
const MegaMenu = ({
|
||||
navLabel,
|
||||
categories,
|
||||
}: {
|
||||
navLabel: { text: string; className?: string, isShowArrow?: boolean },
|
||||
categories: HttpTypes.StoreProductCategory[]
|
||||
}) => {
|
||||
const [isHovered, setIsHovered] = useState(false)
|
||||
|
|
@ -81,10 +85,13 @@ const MegaMenu = ({
|
|||
className="z-50"
|
||||
>
|
||||
<LocalizedClientLink
|
||||
className="hover:text-ui-fg-base hover:bg-neutral-100 rounded-full px-3 py-2"
|
||||
className={clx(
|
||||
"hover:text-ui-fg-base hover:bg-neutral-100 rounded-full px-3 py-2",
|
||||
navLabel.className
|
||||
)}
|
||||
href="/store"
|
||||
>
|
||||
Products
|
||||
{navLabel.text} {navLabel.isShowArrow && <ChevronDown />}
|
||||
</LocalizedClientLink>
|
||||
{isHovered && (
|
||||
<div className="absolute top-full left-0 right-0 flex gap-32 py-10 px-20 bg-white border-b border-neutral-200 ">
|
||||
|
|
|
|||
|
|
@ -0,0 +1,28 @@
|
|||
import { IconButton } from "@medusajs/ui"
|
||||
import { MagnifyingGlass, User, ShoppingBag } from "@medusajs/icons"
|
||||
import {
|
||||
LayoutComponentDefinition,
|
||||
LayoutContext,
|
||||
} from "@vibentec/component-map"
|
||||
|
||||
export default function VtIconButton({
|
||||
nodes,
|
||||
context,
|
||||
}: {
|
||||
nodes: LayoutComponentDefinition
|
||||
context: LayoutContext
|
||||
}) {
|
||||
const props = nodes.config || {}
|
||||
const variantsIcon = {
|
||||
search: MagnifyingGlass,
|
||||
user: User,
|
||||
cart: ShoppingBag
|
||||
}
|
||||
if (!props.variant) return null
|
||||
const Icon = variantsIcon[props.variant as keyof typeof variantsIcon]
|
||||
return (
|
||||
<IconButton className={props?.className ?? ""}>
|
||||
<Icon />
|
||||
</IconButton>
|
||||
)
|
||||
}
|
||||
|
|
@ -51,7 +51,8 @@
|
|||
|
||||
@layer components {
|
||||
.content-container {
|
||||
@apply max-w-[1440px] w-full mx-auto px-6;
|
||||
/* @apply max-w-[1440px] w-full mx-auto px-6; */
|
||||
@apply w-full mx-auto px-6;
|
||||
}
|
||||
|
||||
.contrast-btn {
|
||||
|
|
@ -110,3 +111,6 @@
|
|||
@apply text-[32px] leading-[44px] font-semibold;
|
||||
}
|
||||
}
|
||||
[data-radix-popper-content-wrapper]{
|
||||
z-index: 51 !important;
|
||||
}
|
||||
|
|
@ -13,6 +13,8 @@ import VtMegaMenu from "@modules/layout/components/vt-mega-menu"
|
|||
import VtLink from "@modules/layout/components/vt-linkbutton"
|
||||
import VtSideMenu from "@modules/layout/components/vt-sidemenu"
|
||||
import VtImage from "@modules/layout/templates/vt-image"
|
||||
import VtDropdown from "@modules/layout/components/vt-dropdown"
|
||||
import VtIconButton from "@modules/layout/templates/vt-icon-button"
|
||||
|
||||
type ComponentConfig = Record<string, any>;
|
||||
|
||||
|
|
@ -54,9 +56,11 @@ export const componentMap: Record<string, ComponentRenderer> = {
|
|||
Banner: nodesContextRenderer(Banner),
|
||||
HomeButton: nodesContextRenderer(HomeButton),
|
||||
AccountButton: nodesContextRenderer(AccountButton),
|
||||
IconButton: nodesContextRenderer(VtIconButton),
|
||||
VtCartButton: nodesContextRenderer(VtCartButton),
|
||||
Link: nodesContextRenderer(VtLink),
|
||||
Image: nodesContextRenderer(VtImage),
|
||||
Dropdown: nodesContextRenderer(VtDropdown),
|
||||
CartMismatchBanner: configOnly(CartMismatchBanner),
|
||||
FreeShippingPriceNudge: configOnly(FreeShippingPriceNudge),
|
||||
PropsChildren: {
|
||||
|
|
|
|||
Loading…
Reference in New Issue