diff --git a/app/modules/cart.tsx b/app/modules/cart.tsx index 0aabe2e7..fc9c1b16 100644 --- a/app/modules/cart.tsx +++ b/app/modules/cart.tsx @@ -281,7 +281,7 @@ function CartLineItem({ line, layout }: { line: CartLine; layout: Layouts }) {
{merchandise?.product?.handle ? ( - + {merchandise?.product?.title || ""} diff --git a/app/modules/footer.tsx b/app/modules/footer.tsx index 6cdeeec1..aced7097 100644 --- a/app/modules/footer.tsx +++ b/app/modules/footer.tsx @@ -198,7 +198,7 @@ function FooterMenu({
{items.map((item, ind) => ( - {item.title} + {item.title} ))}
diff --git a/app/modules/header/cart-count.tsx b/app/modules/header/cart-count.tsx index adfe9a3f..34a715d6 100644 --- a/app/modules/header/cart-count.tsx +++ b/app/modules/header/cart-count.tsx @@ -67,10 +67,10 @@ function Badge({ "flex items-center justify-center min-w-4 rounded-full p-0.5", "absolute top-0 -right-1", "transition-colors duration-300", - "group-hover/header:bg-[var(--color-header-text)] group-hover/header:text-[var(--color-header-bg)]", + "group-hover/header:bg-[var(--color-header-text)] group-hover/header:text-[--color-header-bg]", isTransparent - ? "text-[var(--color-header-text)] bg-[var(--color-transparent-header-text)]" - : "bg-[var(--color-header-text)] text-[var(--color-header-bg)]", + ? "text-[--color-header-text] bg-[--color-transparent-header-text]" + : "bg-[--color-header-text] text-[--color-header-bg]", )} > {count} diff --git a/app/modules/header/desktop-header.tsx b/app/modules/header/desktop-header.tsx index 815cd2e3..2fbe4715 100644 --- a/app/modules/header/desktop-header.tsx +++ b/app/modules/header/desktop-header.tsx @@ -74,12 +74,12 @@ export function DesktopHeader({ >
- {menu && } +
- {items.map((item) => { - let { id, items = [] } = item; - let level = getMaxDepth(item); - let isAllImageItems = - items.length && - items.every( - (childItem) => - childItem?.resource?.image && childItem.items.length === 0, - ); - let MenuComponent: React.FC = isAllImageItems - ? ImagesMenu - : level > 2 - ? MegaMenu - : level === 2 - ? DropdownMenu - : FirstLevelMenu; + let { openMenuBy } = useThemeSettings(); + let [value, setValue] = useState(null); + if (menu?.items?.length) { + let items = menu.items as unknown as SingleMenuItem[]; + return ( + setValue(null)} + > + + + ); + } + return null; +} - return ; - })} - +function DropdownSubMenu({ items }: { items: SingleMenuItem[] }) { + return ( +
    + {items.map(({ id, to, title }) => ( + + {title} + + ))} +
); } -function MegaMenu({ title, items, to }: SingleMenuItem) { - let renderList = (item: SingleMenuItem, idx: number) => ( -
- - {item.title} - -
    - {item.items.map((subItem) => ( -
  • +function MegaMenu({ items }: { items: SingleMenuItem[] }) { + return ( +
    + {items.map(({ id, title, to, items: children, resource }, idx) => + resource?.image && children.length === 0 ? ( + + - {subItem.title} + {title} -
  • - ))} -
-
- ); - - let renderImageItem = (item: SingleMenuItem, idx: number) => ( -
- - - -
- {item.title} -
-
- ); - return ( - -
-
-
- {items.map((item, id) => - item.resource && item.items.length === 0 - ? renderImageItem(item, id) - : renderList(item, id), - )} -
-
-
-
- - ); -} - -function DropdownMenu(props: SingleMenuItem) { - let { title, items, to } = props; - return ( - -
-
-
    - {items.map((childItem) => ( -
  • + + ) : ( + + + {title} + +
    + {children.map((cItem) => ( - {childItem.title} + {cItem.title} -
  • - ))} -
-
-
-
- ); -} - -function ImagesMenu({ title, items, to }: SingleMenuItem) { - return ( - -
-
-
- {items.map((item, id) => ( - -
- -
- {item.title} -
-
- - ))} -
-
-
-
+ ))} +
+ + ), + )} +
); } -function FirstLevelMenu(props: { +function SlideIn(props: { className?: string; - title: string; - to: string; - children?: React.ReactNode; + children: React.ReactNode; + style: React.CSSProperties; }) { - let { children, className, title, to } = props; - let hasChild = React.Children.count(children) > 0; + let { className, children, style } = props; return ( -
-
- - - {title} - - {hasChild && ( - - )} - -
+
{children}
); diff --git a/app/modules/header/mobile-header.tsx b/app/modules/header/mobile-header.tsx index e0e0173c..fe00986c 100644 --- a/app/modules/header/mobile-header.tsx +++ b/app/modules/header/mobile-header.tsx @@ -38,8 +38,8 @@ export function MobileHeader({ "h-nav z-40 top-[var(--topbar-height,var(--initial-topbar-height))] w-full leading-none", "flex lg:hidden justify-between items-center gap-4", "px-3 md:px-10", - "text-[var(--color-header-text)] bg-[var(--color-header-bg)]", - "hover:text-[var(--color-header-text)] hover:bg-[var(--color-header-bg)]", + "text-[var(--color-header-text)] bg-[--color-header-bg]", + "hover:text-[var(--color-header-text)] hover:bg-[--color-header-bg]", scrolled && "shadow-header", enableTransparentHeader && isHome ? [ diff --git a/app/modules/header/scrolling-announcement.tsx b/app/modules/header/scrolling-announcement.tsx index ded3c690..283de5ca 100644 --- a/app/modules/header/scrolling-announcement.tsx +++ b/app/modules/header/scrolling-announcement.tsx @@ -39,7 +39,7 @@ export function ScrollingAnnouncement() { return (
- View all products + View all products */}
diff --git a/app/modules/predictive-search/result-item.tsx b/app/modules/predictive-search/result-item.tsx index 98157788..b7d1e4c0 100644 --- a/app/modules/predictive-search/result-item.tsx +++ b/app/modules/predictive-search/result-item.tsx @@ -48,7 +48,7 @@ export function SearchResultItem({ )} {styledTitle ? (
) : ( @@ -57,7 +57,7 @@ export function SearchResultItem({ __typename === "Product" ? "line-clamp-1" : "line-clamp-2", )} > - {title} + {title}
)} {price && ( diff --git a/app/styles/app.css b/app/styles/app.css index 8b7f1a7c..68e4b82a 100644 --- a/app/styles/app.css +++ b/app/styles/app.css @@ -170,7 +170,7 @@ view-transition-name: product-image; } -.underline-animation { +.reveal-underline { background-image: linear-gradient( to right, var(--underline-color, rgb(15, 15, 15)), @@ -183,7 +183,7 @@ transition: background 200ms ease-in-out; background-position: left calc(1em + 4px); } -.underline-animation:hover { +.reveal-underline:hover { background-size: 100% 1px; } .dropdown-transition { diff --git a/app/weaverse/schema.server.ts b/app/weaverse/schema.server.ts index 9b374675..349648d4 100644 --- a/app/weaverse/schema.server.ts +++ b/app/weaverse/schema.server.ts @@ -245,6 +245,22 @@ export let themeSchema: HydrogenThemeSchema = { }, defaultValue: 150, }, + { + type: "heading", + label: "Menu", + }, + { + type: "select", + name: "openMenuBy", + label: "Open menu by", + configs: { + options: [ + { value: "hover", label: "Mouse hover" }, + { value: "click", label: "Mouse click" }, + ], + }, + defaultValue: "click", + }, ], }, { diff --git a/package-lock.json b/package-lock.json index 85a40907..0223fe1b 100644 --- a/package-lock.json +++ b/package-lock.json @@ -14,6 +14,7 @@ "@phosphor-icons/react": "2.1.7", "@radix-ui/react-checkbox": "1.1.2", "@radix-ui/react-dialog": "1.1.2", + "@radix-ui/react-menubar": "^1.1.2", "@radix-ui/react-tooltip": "1.1.4", "@remix-run/react": "2.14.0", "@remix-run/server-runtime": "2.14.0", @@ -4422,6 +4423,32 @@ } } }, + "node_modules/@radix-ui/react-collection": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@radix-ui/react-collection/-/react-collection-1.1.0.tgz", + "integrity": "sha512-GZsZslMJEyo1VKm5L1ZJY8tGDxZNPAoUeQUIbKeJfoi7Q4kmig5AsgLMYYuyYbfjd8fBmFORAIwYAkXMnXZgZw==", + "license": "MIT", + "dependencies": { + "@radix-ui/react-compose-refs": "1.1.0", + "@radix-ui/react-context": "1.1.0", + "@radix-ui/react-primitive": "2.0.0", + "@radix-ui/react-slot": "1.1.0" + }, + "peerDependencies": { + "@types/react": "*", + "@types/react-dom": "*", + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", + "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + }, + "@types/react-dom": { + "optional": true + } + } + }, "node_modules/@radix-ui/react-compose-refs": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/@radix-ui/react-compose-refs/-/react-compose-refs-1.1.0.tgz", @@ -4499,6 +4526,21 @@ } } }, + "node_modules/@radix-ui/react-direction": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@radix-ui/react-direction/-/react-direction-1.1.0.tgz", + "integrity": "sha512-BUuBvgThEiAXh2DWu93XsT+a3aWrGqolGlqqw5VU1kG7p/ZH2cuDlM1sRLNnY3QcBS69UIz2mcKhMxDsdewhjg==", + "license": "MIT", + "peerDependencies": { + "@types/react": "*", + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + } + } + }, "node_modules/@radix-ui/react-dismissable-layer": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/@radix-ui/react-dismissable-layer/-/react-dismissable-layer-1.1.1.tgz", @@ -4580,6 +4622,108 @@ } } }, + "node_modules/@radix-ui/react-menu": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/@radix-ui/react-menu/-/react-menu-2.1.2.tgz", + "integrity": "sha512-lZ0R4qR2Al6fZ4yCCZzu/ReTFrylHFxIqy7OezIpWF4bL0o9biKo0pFIvkaew3TyZ9Fy5gYVrR5zCGZBVbO1zg==", + "license": "MIT", + "dependencies": { + "@radix-ui/primitive": "1.1.0", + "@radix-ui/react-collection": "1.1.0", + "@radix-ui/react-compose-refs": "1.1.0", + "@radix-ui/react-context": "1.1.1", + "@radix-ui/react-direction": "1.1.0", + "@radix-ui/react-dismissable-layer": "1.1.1", + "@radix-ui/react-focus-guards": "1.1.1", + "@radix-ui/react-focus-scope": "1.1.0", + "@radix-ui/react-id": "1.1.0", + "@radix-ui/react-popper": "1.2.0", + "@radix-ui/react-portal": "1.1.2", + "@radix-ui/react-presence": "1.1.1", + "@radix-ui/react-primitive": "2.0.0", + "@radix-ui/react-roving-focus": "1.1.0", + "@radix-ui/react-slot": "1.1.0", + "@radix-ui/react-use-callback-ref": "1.1.0", + "aria-hidden": "^1.1.1", + "react-remove-scroll": "2.6.0" + }, + "peerDependencies": { + "@types/react": "*", + "@types/react-dom": "*", + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", + "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + }, + "@types/react-dom": { + "optional": true + } + } + }, + "node_modules/@radix-ui/react-menu/node_modules/@radix-ui/react-context": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/@radix-ui/react-context/-/react-context-1.1.1.tgz", + "integrity": "sha512-UASk9zi+crv9WteK/NU4PLvOoL3OuE6BWVKNF6hPRBtYBDXQ2u5iu3O59zUlJiTVvkyuycnqrztsHVJwcK9K+Q==", + "license": "MIT", + "peerDependencies": { + "@types/react": "*", + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + } + } + }, + "node_modules/@radix-ui/react-menubar": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/@radix-ui/react-menubar/-/react-menubar-1.1.2.tgz", + "integrity": "sha512-cKmj5Gte7LVyuz+8gXinxZAZECQU+N7aq5pw7kUPpx3xjnDXDbsdzHtCCD2W72bwzy74AvrqdYnKYS42ueskUQ==", + "license": "MIT", + "dependencies": { + "@radix-ui/primitive": "1.1.0", + "@radix-ui/react-collection": "1.1.0", + "@radix-ui/react-compose-refs": "1.1.0", + "@radix-ui/react-context": "1.1.1", + "@radix-ui/react-direction": "1.1.0", + "@radix-ui/react-id": "1.1.0", + "@radix-ui/react-menu": "2.1.2", + "@radix-ui/react-primitive": "2.0.0", + "@radix-ui/react-roving-focus": "1.1.0", + "@radix-ui/react-use-controllable-state": "1.1.0" + }, + "peerDependencies": { + "@types/react": "*", + "@types/react-dom": "*", + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", + "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + }, + "@types/react-dom": { + "optional": true + } + } + }, + "node_modules/@radix-ui/react-menubar/node_modules/@radix-ui/react-context": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/@radix-ui/react-context/-/react-context-1.1.1.tgz", + "integrity": "sha512-UASk9zi+crv9WteK/NU4PLvOoL3OuE6BWVKNF6hPRBtYBDXQ2u5iu3O59zUlJiTVvkyuycnqrztsHVJwcK9K+Q==", + "license": "MIT", + "peerDependencies": { + "@types/react": "*", + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + } + } + }, "node_modules/@radix-ui/react-popper": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/@radix-ui/react-popper/-/react-popper-1.2.0.tgz", @@ -4680,6 +4824,37 @@ } } }, + "node_modules/@radix-ui/react-roving-focus": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@radix-ui/react-roving-focus/-/react-roving-focus-1.1.0.tgz", + "integrity": "sha512-EA6AMGeq9AEeQDeSH0aZgG198qkfHSbvWTf1HvoDmOB5bBG/qTxjYMWUKMnYiV6J/iP/J8MEFSuB2zRU2n7ODA==", + "license": "MIT", + "dependencies": { + "@radix-ui/primitive": "1.1.0", + "@radix-ui/react-collection": "1.1.0", + "@radix-ui/react-compose-refs": "1.1.0", + "@radix-ui/react-context": "1.1.0", + "@radix-ui/react-direction": "1.1.0", + "@radix-ui/react-id": "1.1.0", + "@radix-ui/react-primitive": "2.0.0", + "@radix-ui/react-use-callback-ref": "1.1.0", + "@radix-ui/react-use-controllable-state": "1.1.0" + }, + "peerDependencies": { + "@types/react": "*", + "@types/react-dom": "*", + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", + "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + }, + "@types/react-dom": { + "optional": true + } + } + }, "node_modules/@radix-ui/react-slot": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/@radix-ui/react-slot/-/react-slot-1.1.0.tgz", diff --git a/package.json b/package.json index e2798d6e..6fdc5f3f 100644 --- a/package.json +++ b/package.json @@ -27,6 +27,7 @@ "@phosphor-icons/react": "2.1.7", "@radix-ui/react-checkbox": "1.1.2", "@radix-ui/react-dialog": "1.1.2", + "@radix-ui/react-menubar": "^1.1.2", "@radix-ui/react-tooltip": "1.1.4", "@remix-run/react": "2.14.0", "@remix-run/server-runtime": "2.14.0", diff --git a/tailwind.config.js b/tailwind.config.js index 25c160fd..f962d2eb 100644 --- a/tailwind.config.js +++ b/tailwind.config.js @@ -13,24 +13,15 @@ export default { extend: { keyframes: { "fade-in": { - from: { opacity: "0" }, + from: { opacity: "0.5" }, to: { opacity: "1" }, }, - "slide-down-and-fade": { - from: { opacity: "0", transform: "translateY(-6px)" }, - to: { opacity: "1", transform: "translateY(0)" }, - }, "slide-left-and-fade": { - from: { opacity: "0", transform: "translateX(6px)" }, - to: { opacity: "1", transform: "translateX(0)" }, - }, - "slide-up-and-fade": { - from: { opacity: "0", transform: "translateY(6px)" }, - to: { opacity: "1", transform: "translateY(0)" }, - }, - "slide-right-and-fade": { - from: { opacity: "0", transform: "translateX(-6px)" }, - to: { opacity: "1", transform: "translateX(0)" }, + from: { + opacity: 0, + transform: "translateX(var(--left-distance, 6px))", + }, + to: { opacity: 1, transform: "translateX(0)" }, }, marquee: { from: { transform: "translateZ(0)" }, @@ -57,15 +48,9 @@ export default { spin: "spin .5s linear infinite", marquee: "marquee var(--marquee-duration, 15s) linear infinite", underline: "underline 400ms linear", - "fade-in": "fade-in 500ms ease-in forwards", - "slide-down-and-fade": - "slide-down-and-fade 400ms cubic-bezier(0.16, 1, 0.3, 1) forwards", + "fade-in": "fade-in var(--fade-in-duration, .5s) ease-in forwards", "slide-left-and-fade": - "slide-left-and-fade 400ms cubic-bezier(0.16, 1, 0.3, 1) forwards", - "slide-up-and-fade": - "slide-up-and-fade 400ms cubic-bezier(0.16, 1, 0.3, 1) forwards", - "slide-right-and-fade": - "slide-right-and-fade 400ms cubic-bezier(0.16, 1, 0.3, 1) forwards", + "slide-left-and-fade var(--slide-left-and-fade-duration, .5s) cubic-bezier(0.14, 0.8, 0.6, 1) forwards", }, borderWidth: { 6: "6px",