refactor: remove singular component and replace with wrapper component

This commit is contained in:
Nam Doan
2025-12-10 14:09:46 +07:00
parent baaa0e9c62
commit fe881d5aed
6 changed files with 133 additions and 93 deletions
@@ -24,21 +24,21 @@ export default async function VtFooter({
return (
<footer className={props?.className ?? ""}>
<div className={clx("flex gap-x-4 h-full", props?.leftClassName)}>
{props.left && (
<DynamicLayoutRenderer nodes={props.left} context={context} />
)}
</div>
<div className={clx("flex gap-x-4 h-full", props?.centerClassName)}>
{props.center && (
<DynamicLayoutRenderer nodes={props.center} context={context} />
)}
</div>
<div className={clx("flex gap-x-4 h-full", props?.rightClassName)}>
{props.right && (
<DynamicLayoutRenderer nodes={props.right} context={context} />
)}
</div>
{props?.left && (
<div className={clx("flex gap-x-4 h-full", props?.leftClassName)}>
<DynamicLayoutRenderer nodes={props?.left} context={context} />
</div>
)}
{props?.center && (
<div className={clx("flex gap-x-4 h-full", props?.centerClassName)}>
<DynamicLayoutRenderer nodes={props?.center} context={context} />
</div>
)}
{props?.right && (
<div className={clx("flex gap-x-4 h-full", props?.rightClassName)}>
<DynamicLayoutRenderer nodes={props?.right} context={context} />
</div>
)}
</footer>
)
}
@@ -0,0 +1,31 @@
import * as MedusaIcons from "@medusajs/icons"
import { clx } from "@medusajs/ui"
import { LayoutComponentDefinition, LayoutContext } from "@vibentec/component-map"
export default function VtFooterBottom({
nodes,
context,
}: {
nodes: LayoutComponentDefinition
context: LayoutContext
}) {
const props = (nodes.config) ?? {}
const renderIcon = (name: string, idx: number) => {
const IconComp = (MedusaIcons as Record<string, any>)[name]
if (!IconComp) return null
return (
<IconComp key={`${name}-${idx}`} className="shadow-none" />
)
}
return (
<div className={clx("flex w-full items-center justify-between", props.className)}>
<span className={clx("text-[14px] font-[400] pt-2", props.textClassName)}>{props.text}</span>
<div className={clx("flex items-center gap-2", props.iconsClassName)}>
{(props.icons ?? []).map(renderIcon)}
</div>
</div>
)
}
@@ -0,0 +1,62 @@
import { clx } from "@medusajs/ui"
import { ChevronRightMini } from "@medusajs/icons"
import { LayoutComponentDefinition, LayoutContext } from "@vibentec/component-map"
import LocalizedClientLink from "@modules/common/components/localized-client-link"
interface VtFooterHeroConfig {
logoSrc: string
logoAlt?: string
title: string
description: string
cta?: { label: string; href: string }
className?: string
logoClassName?: string
titleClassName?: string
descriptionClassName?: string
ctaClassName?: string
}
export default function VtFooterHero({
nodes,
context,
}: {
nodes: LayoutComponentDefinition
context: LayoutContext
}) {
const props = (nodes.config as VtFooterHeroConfig) ?? {}
return (
<div className={clx("flex flex-col items-start", props.className)}>
{props.logoSrc && (
<img
src={props.logoSrc}
alt={props.logoAlt ?? "logo"}
className={clx("object-contain", props.logoClassName)}
/>
)}
{props.title && (
<h2 className={clx("mt-4 w-[320px] text-[24px] font-semibold text-[#11314E]", props.titleClassName)}>
{props.title}
</h2>
)}
{props.description && (
<p className={clx("mt-2 text-ui-fg-subtle txt-small", props.descriptionClassName)}>
{props.description}
</p>
)}
{props.cta && (
<LocalizedClientLink
href={props.cta.href}
className={clx(
"bg-black text-white items-center flex gap-2 px-4 mt-[24px] py-2 rounded-md w-fit text-[14px]",
props.ctaClassName
)}
>
<span>{props.cta.label}</span>
<ChevronRightMini className="order-1" />
</LocalizedClientLink>
)}
</div>
)
}
@@ -3,15 +3,13 @@ import {
LayoutComponentDefinition,
LayoutContext,
} from "@vibentec/component-map"
import Image from "next/image"
export interface VtImageConfig {
src: string
alt: string
className?: string,
objectFit?: string,
}
export default function VtImage({
export default function VtLogo({
nodes,
context,
}: {
@@ -21,7 +19,7 @@ export default function VtImage({
const props = (nodes.config as VtImageConfig) ?? {}
return (
<div className={clx("relative", props.className)}>
<img src={props.src} alt={props.alt} className={clx("w-full h-full object-cover", props.objectFit)} />
<img src={props.src} alt={props.alt} className={clx("w-full h-full", props.objectFit)} />
</div>
)
}
+6 -9
View File
@@ -12,17 +12,16 @@ import Banner from "@modules/layout/templates/vt-banner"
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/templates/vt-dropdown"
import VtButton from "@modules/layout/templates/vt-button"
import VtSearchInput from "@modules/layout/templates/vt-search-input"
import VtSection from "@modules/layout/templates/vt-section"
import VtText from "@modules/layout/templates/vt-text"
import VtInput from "@modules/layout/templates/vt-input"
import VtCurrencySelect from "@modules/layout/templates/vt-currency-select"
import VtMenuItem from "@modules/layout/templates/vt-menu-item"
import VtCountryCodeSelect from "@modules/layout/templates/vt-country-select/server"
import VtSocialLinks from "@modules/layout/templates/vt-social-link"
import VtFooterHero from "@modules/layout/templates/vt-footer/vt-footer-hero"
import VtFooterBottom from "@modules/layout/templates/vt-footer/vt-footer-bottom"
import VtLogo from "@modules/layout/templates/vt-logo"
type ComponentConfig = Record<string, any>;
@@ -63,18 +62,14 @@ export const componentMap: Record<string, ComponentRenderer> = {
VtSideMenu: nodesContextRenderer(VtSideMenu),
Banner: nodesContextRenderer(Banner),
HomeButton: nodesContextRenderer(HomeButton),
Logo: nodesContextRenderer(VtLogo),
AccountButton: nodesContextRenderer(AccountButton),
Button: nodesContextRenderer(VtButton),
Section: nodesContextRenderer(VtSection),
SearchInput: nodesContextRenderer(VtSearchInput),
VtCartButton: nodesContextRenderer(VtCartButton),
VtCurrencySelect: nodesContextRenderer(VtCurrencySelect),
VtCountryCodeSelect: nodesContextRenderer(VtCountryCodeSelect),
VtSocialLinks: nodesContextRenderer(VtSocialLinks),
Link: nodesContextRenderer(VtLink),
Input: nodesContextRenderer(VtInput),
Image: nodesContextRenderer(VtImage),
Text: nodesContextRenderer(VtText),
Dropdown: nodesContextRenderer(VtDropdown),
VtMenuItem: nodesContextRenderer(VtMenuItem),
CartMismatchBanner: configOnly(CartMismatchBanner),
@@ -82,6 +77,8 @@ export const componentMap: Record<string, ComponentRenderer> = {
PropsChildren: {
render: (_props, ctx) => ctx.contentChildren, // PageLayout's props.children
},
VtFooterHero: nodesContextRenderer(VtFooterHero),
VtFooterBottom: nodesContextRenderer(VtFooterBottom),
Footer: nodesContextRenderer(VtFooter)
}