mirror of
https://github.com/vercel/commerce.git
synced 2025-06-16 12:21:20 +00:00
compoennt converted from tailwind to module scss
This commit is contained in:
parent
b1b157fb88
commit
04971a5c53
16
components/MegaMenu/MegaMenu.module.scss
Normal file
16
components/MegaMenu/MegaMenu.module.scss
Normal file
@ -0,0 +1,16 @@
|
|||||||
|
.megaMenu {
|
||||||
|
margin-top: 1rem;
|
||||||
|
display: none;
|
||||||
|
justify-content: center;
|
||||||
|
|
||||||
|
@media (min-width: 768px) {
|
||||||
|
display: flex;
|
||||||
|
}
|
||||||
|
|
||||||
|
.menuList {
|
||||||
|
font-size: 1rem;
|
||||||
|
display: flex;
|
||||||
|
gap: 1.5rem;
|
||||||
|
font-weight: 600;
|
||||||
|
}
|
||||||
|
}
|
39
components/MegaMenu/MenuItemComponent.module.scss
Normal file
39
components/MegaMenu/MenuItemComponent.module.scss
Normal file
@ -0,0 +1,39 @@
|
|||||||
|
.menuItem {
|
||||||
|
position: relative;
|
||||||
|
display: block;
|
||||||
|
}
|
||||||
|
|
||||||
|
.submenuItem {
|
||||||
|
padding: 0.5rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.menuLink {
|
||||||
|
padding-left: 0.5rem;
|
||||||
|
font-weight: bold;
|
||||||
|
text-decoration: none;
|
||||||
|
color: #757575;
|
||||||
|
text-decoration-thickness: 4px;
|
||||||
|
|
||||||
|
&:hover {
|
||||||
|
color: black;
|
||||||
|
text-decoration: underline;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.subMenu {
|
||||||
|
position: absolute;
|
||||||
|
left: 0;
|
||||||
|
top: 100%;
|
||||||
|
z-index: 10;
|
||||||
|
display: none;
|
||||||
|
width: 12rem;
|
||||||
|
background-color: white;
|
||||||
|
border-radius: 0.625rem;
|
||||||
|
box-shadow: 0 0.5rem 1rem rgba(0, 0, 0, 0.1);
|
||||||
|
}
|
||||||
|
|
||||||
|
.dropdown {
|
||||||
|
.menuItem:hover & {
|
||||||
|
display: block;
|
||||||
|
}
|
||||||
|
}
|
@ -1,4 +1,5 @@
|
|||||||
import { MenuItem } from '../../lib/shopify/types';
|
import { MenuItem } from '../../lib/shopify/types';
|
||||||
|
import classes from './MegaMenu.module.scss';
|
||||||
import MenuItemComponent from './menu-item-component';
|
import MenuItemComponent from './menu-item-component';
|
||||||
|
|
||||||
type MegaMenuProps = {
|
type MegaMenuProps = {
|
||||||
@ -7,8 +8,8 @@ type MegaMenuProps = {
|
|||||||
|
|
||||||
const MegaMenu = ({ menu }: MegaMenuProps) => {
|
const MegaMenu = ({ menu }: MegaMenuProps) => {
|
||||||
return (
|
return (
|
||||||
<div className="mt-4 hidden justify-center md:flex">
|
<div className={classes.megaMenu}>
|
||||||
<ul className="text-md flex gap-6 font-semibold">
|
<ul className={classes.menuList}>
|
||||||
{menu.map((item) => (
|
{menu.map((item) => (
|
||||||
<MenuItemComponent key={item.title} item={item} />
|
<MenuItemComponent key={item.title} item={item} />
|
||||||
))}
|
))}
|
||||||
|
@ -1,5 +1,6 @@
|
|||||||
import Link from 'next/link';
|
import Link from 'next/link';
|
||||||
import { MenuItem } from '../../lib/shopify/types';
|
import { MenuItem } from '../../lib/shopify/types';
|
||||||
|
import styles from './MenuItemComponent.module.scss'; // Importing the SCSS module
|
||||||
|
|
||||||
type MenuItemProps = {
|
type MenuItemProps = {
|
||||||
item: MenuItem;
|
item: MenuItem;
|
||||||
@ -8,29 +9,17 @@ type MenuItemProps = {
|
|||||||
|
|
||||||
const MenuItemComponent = ({ item, isSubMenu = false }: MenuItemProps) => {
|
const MenuItemComponent = ({ item, isSubMenu = false }: MenuItemProps) => {
|
||||||
return (
|
return (
|
||||||
<li className={`group relative ${isSubMenu ? 'submenu-item p-2' : ''}`}>
|
<li className={`${styles.menuItem} ${isSubMenu ? styles.submenuItem : ''}`}>
|
||||||
<Link
|
<Link href={item.path} className={styles.menuLink}>
|
||||||
href={item.path}
|
|
||||||
className="pl-2 font-semibold text-neutral-500 underline-offset-4 hover:text-black hover:underline dark:text-neutral-400 dark:hover:text-neutral-300"
|
|
||||||
>
|
|
||||||
{item.title}
|
{item.title}
|
||||||
</Link>
|
</Link>
|
||||||
{item.items.length > 0 && (
|
{item.items.length > 0 && (
|
||||||
<ul className="absolute left-0 top-full z-10 hidden w-48 rounded-xl bg-white shadow-lg group-hover:block">
|
<ul className={`${styles.subMenu} ${styles.dropdown}`}>
|
||||||
{item.items.map((subItem) => (
|
{item.items.map((subItem) => (
|
||||||
<MenuItemComponent key={subItem.title} item={subItem} isSubMenu={true} />
|
<MenuItemComponent key={subItem.title} item={subItem} isSubMenu={true} />
|
||||||
))}
|
))}
|
||||||
</ul>
|
</ul>
|
||||||
)}
|
)}
|
||||||
{isSubMenu && item.items.length > 0 && (
|
|
||||||
<ul className="absolute left-0 top-full z-10 hidden w-48 bg-white shadow-lg group-hover:block">
|
|
||||||
{item.items.map((subItem, index) =>
|
|
||||||
index === 2 ? (
|
|
||||||
<MenuItemComponent key={subItem.title} item={subItem} isSubMenu={true} />
|
|
||||||
) : null
|
|
||||||
)}
|
|
||||||
</ul>
|
|
||||||
)}
|
|
||||||
</li>
|
</li>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
128
components/layout/Footer.module.scss
Normal file
128
components/layout/Footer.module.scss
Normal file
@ -0,0 +1,128 @@
|
|||||||
|
.footer {
|
||||||
|
font-size: 0.875rem;
|
||||||
|
color: #757575;
|
||||||
|
}
|
||||||
|
|
||||||
|
.footerContainer {
|
||||||
|
margin: 0 auto;
|
||||||
|
display: flex;
|
||||||
|
width: 100%;
|
||||||
|
max-width: 1536px;
|
||||||
|
flex-direction: column;
|
||||||
|
gap: 1.5rem;
|
||||||
|
border-top: 1px solid #e5e5e5;
|
||||||
|
padding: 3rem 1.5rem;
|
||||||
|
@media (min-width: 768px) {
|
||||||
|
flex-direction: row;
|
||||||
|
gap: 3rem;
|
||||||
|
padding: 3rem 1rem;
|
||||||
|
}
|
||||||
|
@media (min-width: 1320px) {
|
||||||
|
padding: 3rem 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.logoLink {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
gap: 0.5rem;
|
||||||
|
color: black;
|
||||||
|
@media (min-width: 768px) {
|
||||||
|
padding-top: 0.25rem;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.siteName {
|
||||||
|
text-transform: uppercase;
|
||||||
|
}
|
||||||
|
|
||||||
|
.skeletonContainer {
|
||||||
|
display: flex;
|
||||||
|
height: 11.75rem;
|
||||||
|
width: 12.5rem;
|
||||||
|
flex-direction: column;
|
||||||
|
gap: 0.5rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.skeleton {
|
||||||
|
width: 100%;
|
||||||
|
height: 1.5rem;
|
||||||
|
animation: pulse 2s infinite;
|
||||||
|
border-radius: 0.375rem;
|
||||||
|
background-color: #e5e5e5;
|
||||||
|
}
|
||||||
|
|
||||||
|
.deployContainer {
|
||||||
|
@media (min-width: 768px) {
|
||||||
|
margin-left: auto;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.deployButton {
|
||||||
|
display: flex;
|
||||||
|
height: 2rem;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
border-radius: 0.375rem;
|
||||||
|
border: 1px solid #e5e5e5;
|
||||||
|
background-color: white;
|
||||||
|
font-size: 0.75rem;
|
||||||
|
color: black;
|
||||||
|
}
|
||||||
|
|
||||||
|
.deployIcon {
|
||||||
|
padding: 0 0.75rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.deployDivider {
|
||||||
|
height: 100%;
|
||||||
|
border-right: 1px solid #e5e5e5;
|
||||||
|
}
|
||||||
|
|
||||||
|
.deployText {
|
||||||
|
padding: 0 0.75rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.footerBottom {
|
||||||
|
border-top: 1px solid #e5e5e5;
|
||||||
|
padding: 1.5rem 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.footerBottomContainer {
|
||||||
|
margin: 0 auto;
|
||||||
|
display: flex;
|
||||||
|
width: 100%;
|
||||||
|
max-width: 1536px;
|
||||||
|
flex-direction: column;
|
||||||
|
align-items: center;
|
||||||
|
gap: 0.25rem;
|
||||||
|
padding: 0 1rem;
|
||||||
|
@media (min-width: 768px) {
|
||||||
|
flex-direction: row;
|
||||||
|
gap: 0;
|
||||||
|
padding: 0 1rem;
|
||||||
|
}
|
||||||
|
@media (min-width: 1320px) {
|
||||||
|
padding: 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.divider {
|
||||||
|
margin: 0 1rem;
|
||||||
|
height: 1rem;
|
||||||
|
width: 1px;
|
||||||
|
border-left: 1px solid #a8a8a8;
|
||||||
|
@media (min-width: 768px) {
|
||||||
|
display: inline-block;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.craftedBy {
|
||||||
|
@media (min-width: 768px) {
|
||||||
|
margin-left: auto;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.craftedByLink {
|
||||||
|
color: black;
|
||||||
|
}
|
@ -1,31 +1,32 @@
|
|||||||
import Link from 'next/link';
|
|
||||||
|
|
||||||
import FooterMenu from 'components/layout/footer-menu';
|
import FooterMenu from 'components/layout/footer-menu';
|
||||||
import LogoSquare from 'components/logo-square';
|
import LogoSquare from 'components/logo-square';
|
||||||
import { getMenu } from 'lib/shopify';
|
import { getMenu } from 'lib/shopify';
|
||||||
|
import Link from 'next/link';
|
||||||
import { Suspense } from 'react';
|
import { Suspense } from 'react';
|
||||||
|
|
||||||
|
import styles from './Footer.module.scss'; // Importing the SCSS module
|
||||||
|
|
||||||
const { COMPANY_NAME, SITE_NAME } = process.env;
|
const { COMPANY_NAME, SITE_NAME } = process.env;
|
||||||
|
|
||||||
export default async function Footer() {
|
export default async function Footer() {
|
||||||
const currentYear = new Date().getFullYear();
|
const currentYear = new Date().getFullYear();
|
||||||
const copyrightDate = 2023 + (currentYear > 2023 ? `-${currentYear}` : '');
|
const copyrightDate = 2023 + (currentYear > 2023 ? `-${currentYear}` : '');
|
||||||
const skeleton = 'w-full h-6 animate-pulse rounded bg-neutral-200 dark:bg-neutral-700';
|
const skeleton = styles.skeleton;
|
||||||
const menu = await getMenu('next-js-frontend-footer-menu');
|
const menu = await getMenu('next-js-frontend-footer-menu');
|
||||||
const copyrightName = COMPANY_NAME || SITE_NAME || '';
|
const copyrightName = COMPANY_NAME || SITE_NAME || '';
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<footer className="text-sm text-neutral-500 dark:text-neutral-400">
|
<footer className={styles.footer}>
|
||||||
<div className="mx-auto flex w-full max-w-7xl flex-col gap-6 border-t border-neutral-200 px-6 py-12 text-sm md:flex-row md:gap-12 md:px-4 min-[1320px]:px-0 dark:border-neutral-700">
|
<div className={styles.footerContainer}>
|
||||||
<div>
|
<div>
|
||||||
<Link className="flex items-center gap-2 text-black md:pt-1 dark:text-white" href="/">
|
<Link className={styles.logoLink} href="/">
|
||||||
<LogoSquare size="sm" />
|
<LogoSquare size="sm" />
|
||||||
<span className="uppercase">{SITE_NAME}</span>
|
<span className={styles.siteName}>{SITE_NAME}</span>
|
||||||
</Link>
|
</Link>
|
||||||
</div>
|
</div>
|
||||||
<Suspense
|
<Suspense
|
||||||
fallback={
|
fallback={
|
||||||
<div className="flex h-[188px] w-[200px] flex-col gap-2">
|
<div className={styles.skeletonContainer}>
|
||||||
<div className={skeleton} />
|
<div className={skeleton} />
|
||||||
<div className={skeleton} />
|
<div className={skeleton} />
|
||||||
<div className={skeleton} />
|
<div className={skeleton} />
|
||||||
@ -37,28 +38,28 @@ export default async function Footer() {
|
|||||||
>
|
>
|
||||||
<FooterMenu menu={menu} />
|
<FooterMenu menu={menu} />
|
||||||
</Suspense>
|
</Suspense>
|
||||||
<div className="md:ml-auto">
|
<div className={styles.deployContainer}>
|
||||||
<a
|
<a
|
||||||
className="flex h-8 w-max flex-none items-center justify-center rounded-md border border-neutral-200 bg-white text-xs text-black dark:border-neutral-700 dark:bg-black dark:text-white"
|
className={styles.deployButton}
|
||||||
aria-label="Deploy on Vercel"
|
aria-label="Deploy on Vercel"
|
||||||
href="https://vercel.com/templates/next.js/nextjs-commerce"
|
href="https://vercel.com/templates/next.js/nextjs-commerce"
|
||||||
>
|
>
|
||||||
<span className="px-3">▲</span>
|
<span className={styles.deployIcon}>▲</span>
|
||||||
<hr className="h-full border-r border-neutral-200 dark:border-neutral-700" />
|
<hr className={styles.deployDivider} />
|
||||||
<span className="px-3">Deploy</span>
|
<span className={styles.deployText}>Deploy</span>
|
||||||
</a>
|
</a>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div className="border-t border-neutral-200 py-6 text-sm dark:border-neutral-700">
|
<div className={styles.footerBottom}>
|
||||||
<div className="mx-auto flex w-full max-w-7xl flex-col items-center gap-1 px-4 md:flex-row md:gap-0 md:px-4 min-[1320px]:px-0">
|
<div className={styles.footerBottomContainer}>
|
||||||
<p>
|
<p>
|
||||||
© {copyrightDate} {copyrightName}
|
© {copyrightDate} {copyrightName}
|
||||||
{copyrightName.length && !copyrightName.endsWith('.') ? '.' : ''} All rights reserved.
|
{copyrightName.length && !copyrightName.endsWith('.') ? '.' : ''} All rights reserved.
|
||||||
</p>
|
</p>
|
||||||
<hr className="mx-4 hidden h-4 w-[1px] border-l border-neutral-400 md:inline-block" />
|
<hr className={styles.divider} />
|
||||||
<p>Designed in California</p>
|
<p>Designed in California</p>
|
||||||
<p className="md:ml-auto">
|
<p className={styles.craftedBy}>
|
||||||
<a href="https://vercel.com" className="text-black dark:text-white">
|
<a href="https://vercel.com" className={styles.craftedByLink}>
|
||||||
Crafted by ▲ Vercel
|
Crafted by ▲ Vercel
|
||||||
</a>
|
</a>
|
||||||
</p>
|
</p>
|
||||||
|
53
components/layout/navbar/MobileMenu.module.scss
Normal file
53
components/layout/navbar/MobileMenu.module.scss
Normal file
@ -0,0 +1,53 @@
|
|||||||
|
.openMenuButton {
|
||||||
|
display: flex;
|
||||||
|
height: 2.75rem;
|
||||||
|
width: 2.75rem;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
border-radius: 0.375rem;
|
||||||
|
border: 1px solid #e5e5e5;
|
||||||
|
color: black;
|
||||||
|
transition: color 0.3s;
|
||||||
|
|
||||||
|
@media (min-width: 768px) {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.closeMenuButton {
|
||||||
|
margin-bottom: 1rem;
|
||||||
|
display: flex;
|
||||||
|
height: 2.75rem;
|
||||||
|
width: 2.75rem;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
border-radius: 0.375rem;
|
||||||
|
border: 1px solid #e5e5e5;
|
||||||
|
color: black;
|
||||||
|
transition: color 0.3s;
|
||||||
|
}
|
||||||
|
|
||||||
|
.dialogPanel {
|
||||||
|
position: fixed;
|
||||||
|
bottom: 0;
|
||||||
|
left: 0;
|
||||||
|
right: 0;
|
||||||
|
top: 0;
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
height: 100%;
|
||||||
|
width: 100%;
|
||||||
|
background-color: white;
|
||||||
|
padding-bottom: 1.5rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.menuItem {
|
||||||
|
padding: 0.5rem 0;
|
||||||
|
font-size: 1.25rem;
|
||||||
|
color: black;
|
||||||
|
transition: color 0.3s;
|
||||||
|
|
||||||
|
&:hover {
|
||||||
|
color: #737373;
|
||||||
|
}
|
||||||
|
}
|
38
components/layout/navbar/Search.module.scss
Normal file
38
components/layout/navbar/Search.module.scss
Normal file
@ -0,0 +1,38 @@
|
|||||||
|
.searchForm {
|
||||||
|
max-width: 550px;
|
||||||
|
position: relative;
|
||||||
|
width: 100%;
|
||||||
|
@media (min-width: 1024px) {
|
||||||
|
width: 20rem;
|
||||||
|
}
|
||||||
|
@media (min-width: 1280px) {
|
||||||
|
width: 100%;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.searchInput {
|
||||||
|
width: 100%;
|
||||||
|
border-radius: 0.5rem;
|
||||||
|
border: 1px solid #e5e5e5;
|
||||||
|
background-color: white;
|
||||||
|
padding: 0.5rem 1rem;
|
||||||
|
font-size: 0.875rem;
|
||||||
|
color: black;
|
||||||
|
&::placeholder {
|
||||||
|
color: #757575;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.searchIconContainer {
|
||||||
|
position: absolute;
|
||||||
|
right: 0;
|
||||||
|
top: 0;
|
||||||
|
margin-right: 0.75rem;
|
||||||
|
display: flex;
|
||||||
|
height: 100%;
|
||||||
|
align-items: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
.searchIcon {
|
||||||
|
height: 1rem;
|
||||||
|
}
|
100
components/layout/navbar/index.module.scss
Normal file
100
components/layout/navbar/index.module.scss
Normal file
@ -0,0 +1,100 @@
|
|||||||
|
.navbar {
|
||||||
|
position: relative;
|
||||||
|
margin: 0 auto;
|
||||||
|
max-width: 1536px;
|
||||||
|
padding: 1rem;
|
||||||
|
|
||||||
|
@media (min-width: 1024px) {
|
||||||
|
padding-left: 1.5rem;
|
||||||
|
padding-right: 1.5rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.navbarContainer {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: space-between;
|
||||||
|
|
||||||
|
.mobileMenu {
|
||||||
|
display: block;
|
||||||
|
flex: none;
|
||||||
|
|
||||||
|
@media (min-width: 768px) {
|
||||||
|
/* md */
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.navbarContent {
|
||||||
|
display: flex;
|
||||||
|
width: 100%;
|
||||||
|
align-items: center;
|
||||||
|
|
||||||
|
.logoContainer {
|
||||||
|
display: flex;
|
||||||
|
width: 100%;
|
||||||
|
|
||||||
|
@media (min-width: 768px) {
|
||||||
|
/* md */
|
||||||
|
width: 33.333333%; /* md:w-1/3 */
|
||||||
|
}
|
||||||
|
|
||||||
|
.logoLink {
|
||||||
|
margin-right: 0.5rem; /* mr-2 */
|
||||||
|
display: flex;
|
||||||
|
width: 100%;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
|
||||||
|
@media (min-width: 768px) {
|
||||||
|
/* md */
|
||||||
|
width: auto; /* md:w-auto */
|
||||||
|
}
|
||||||
|
|
||||||
|
@media (min-width: 1024px) {
|
||||||
|
/* lg */
|
||||||
|
margin-right: 1.5rem; /* lg:mr-6 */
|
||||||
|
}
|
||||||
|
|
||||||
|
.siteName {
|
||||||
|
margin-left: 0.5rem; /* ml-2 */
|
||||||
|
flex: none;
|
||||||
|
font-size: 0.875rem; /* text-sm */
|
||||||
|
font-weight: 500; /* font-medium */
|
||||||
|
text-transform: uppercase;
|
||||||
|
|
||||||
|
@media (min-width: 768px) {
|
||||||
|
/* md */
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
@media (min-width: 1024px) {
|
||||||
|
/* lg */
|
||||||
|
display: block;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.searchContainer {
|
||||||
|
display: none;
|
||||||
|
justify-content: center;
|
||||||
|
|
||||||
|
@media (min-width: 768px) {
|
||||||
|
/* md */
|
||||||
|
display: flex;
|
||||||
|
width: 33.333333%; /* md:w-1/3 */
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.cartContainer {
|
||||||
|
display: flex;
|
||||||
|
justify-content: flex-end;
|
||||||
|
|
||||||
|
@media (min-width: 768px) {
|
||||||
|
/* md */
|
||||||
|
width: 33.333333%; /* md:w-1/3 */
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -5,39 +5,36 @@ import LogoSquare from 'components/logo-square';
|
|||||||
import { getMegaMenu } from 'lib/shopify';
|
import { getMegaMenu } from 'lib/shopify';
|
||||||
import Link from 'next/link';
|
import Link from 'next/link';
|
||||||
import { Suspense } from 'react';
|
import { Suspense } from 'react';
|
||||||
|
import classes from './index.module.scss';
|
||||||
import MobileMenu from './mobile-menu';
|
import MobileMenu from './mobile-menu';
|
||||||
import Search, { SearchSkeleton } from './search';
|
import Search, { SearchSkeleton } from './search';
|
||||||
|
|
||||||
const { SITE_NAME } = process.env;
|
const { SITE_NAME } = process.env;
|
||||||
|
|
||||||
export default async function Navbar() {
|
export default async function Navbar() {
|
||||||
const menu = await getMegaMenu('next-js-frontend-header-menu');
|
const menu = await getMegaMenu('next-js-frontend-header-menu');
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<nav className="relative mx-auto max-w-screen-2xl p-4 lg:px-6">
|
<nav className={classes.navbar}>
|
||||||
<div className="flex items-center justify-between">
|
<div className={classes.navbarContainer}>
|
||||||
<div className="block flex-none md:hidden">
|
<div className={classes.mobileMenu}>
|
||||||
<Suspense fallback={null}>
|
<Suspense fallback={null}>
|
||||||
<MobileMenu menu={menu} />
|
<MobileMenu menu={menu} />
|
||||||
</Suspense>
|
</Suspense>
|
||||||
</div>
|
</div>
|
||||||
<div className="flex w-full items-center">
|
<div className={classes.navbarContent}>
|
||||||
<div className="flex w-full md:w-1/3">
|
<div className={classes.logoContainer}>
|
||||||
<Link
|
<Link href="/" className={classes.logoLink}>
|
||||||
href="/"
|
|
||||||
className="mr-2 flex w-full items-center justify-center md:w-auto lg:mr-6"
|
|
||||||
>
|
|
||||||
<LogoSquare />
|
<LogoSquare />
|
||||||
<div className="ml-2 flex-none text-sm font-medium uppercase md:hidden lg:block">
|
<div className={classes.siteName}>{SITE_NAME}</div>
|
||||||
{SITE_NAME}
|
|
||||||
</div>
|
|
||||||
</Link>
|
</Link>
|
||||||
</div>
|
</div>
|
||||||
<div className="hidden justify-center md:flex md:w-1/3">
|
<div className={classes.searchContainer}>
|
||||||
<Suspense fallback={<SearchSkeleton />}>
|
<Suspense fallback={<SearchSkeleton />}>
|
||||||
<Search />
|
<Search />
|
||||||
</Suspense>
|
</Suspense>
|
||||||
</div>
|
</div>
|
||||||
<div className="flex justify-end md:w-1/3">
|
<div className={classes.cartContainer}>
|
||||||
<Suspense fallback={<OpenCart />}>
|
<Suspense fallback={<OpenCart />}>
|
||||||
<Cart />
|
<Cart />
|
||||||
</Suspense>
|
</Suspense>
|
||||||
|
@ -9,6 +9,8 @@ import { Bars3Icon, XMarkIcon } from '@heroicons/react/24/outline';
|
|||||||
import { Menu } from 'lib/shopify/types';
|
import { Menu } from 'lib/shopify/types';
|
||||||
import Search, { SearchSkeleton } from './search';
|
import Search, { SearchSkeleton } from './search';
|
||||||
|
|
||||||
|
import styles from './MobileMenu.module.scss'; // Importing the SCSS module
|
||||||
|
|
||||||
export default function MobileMenu({ menu }: { menu: Menu[] }) {
|
export default function MobileMenu({ menu }: { menu: Menu[] }) {
|
||||||
const pathname = usePathname();
|
const pathname = usePathname();
|
||||||
const searchParams = useSearchParams();
|
const searchParams = useSearchParams();
|
||||||
@ -35,7 +37,7 @@ export default function MobileMenu({ menu }: { menu: Menu[] }) {
|
|||||||
<button
|
<button
|
||||||
onClick={openMobileMenu}
|
onClick={openMobileMenu}
|
||||||
aria-label="Open mobile menu"
|
aria-label="Open mobile menu"
|
||||||
className="flex h-11 w-11 items-center justify-center rounded-md border border-neutral-200 text-black transition-colors md:hidden dark:border-neutral-700 dark:text-white"
|
className={styles.openMenuButton}
|
||||||
>
|
>
|
||||||
<Bars3Icon className="h-4" />
|
<Bars3Icon className="h-4" />
|
||||||
</button>
|
</button>
|
||||||
@ -61,10 +63,10 @@ export default function MobileMenu({ menu }: { menu: Menu[] }) {
|
|||||||
leaveFrom="translate-x-0"
|
leaveFrom="translate-x-0"
|
||||||
leaveTo="translate-x-[-100%]"
|
leaveTo="translate-x-[-100%]"
|
||||||
>
|
>
|
||||||
<Dialog.Panel className="fixed bottom-0 left-0 right-0 top-0 flex h-full w-full flex-col bg-white pb-6 dark:bg-black">
|
<Dialog.Panel className={styles.dialogPanel}>
|
||||||
<div className="p-4">
|
<div className="p-4">
|
||||||
<button
|
<button
|
||||||
className="mb-4 flex h-11 w-11 items-center justify-center rounded-md border border-neutral-200 text-black transition-colors dark:border-neutral-700 dark:text-white"
|
className={styles.closeMenuButton}
|
||||||
onClick={closeMobileMenu}
|
onClick={closeMobileMenu}
|
||||||
aria-label="Close mobile menu"
|
aria-label="Close mobile menu"
|
||||||
>
|
>
|
||||||
@ -79,10 +81,7 @@ export default function MobileMenu({ menu }: { menu: Menu[] }) {
|
|||||||
{menu.length ? (
|
{menu.length ? (
|
||||||
<ul className="flex w-full flex-col">
|
<ul className="flex w-full flex-col">
|
||||||
{menu.map((item: Menu) => (
|
{menu.map((item: Menu) => (
|
||||||
<li
|
<li className={styles.menuItem} key={item.title}>
|
||||||
className="py-2 text-xl text-black transition-colors hover:text-neutral-500 dark:text-white"
|
|
||||||
key={item.title}
|
|
||||||
>
|
|
||||||
<Link href={item.path} onClick={closeMobileMenu}>
|
<Link href={item.path} onClick={closeMobileMenu}>
|
||||||
{item.title}
|
{item.title}
|
||||||
</Link>
|
</Link>
|
||||||
|
@ -3,6 +3,7 @@
|
|||||||
import { MagnifyingGlassIcon } from '@heroicons/react/24/outline';
|
import { MagnifyingGlassIcon } from '@heroicons/react/24/outline';
|
||||||
import { createUrl } from 'lib/utils';
|
import { createUrl } from 'lib/utils';
|
||||||
import { useRouter, useSearchParams } from 'next/navigation';
|
import { useRouter, useSearchParams } from 'next/navigation';
|
||||||
|
import styles from './Search.module.scss'; // Importing the SCSS module
|
||||||
|
|
||||||
export default function Search() {
|
export default function Search() {
|
||||||
const router = useRouter();
|
const router = useRouter();
|
||||||
@ -25,7 +26,7 @@ export default function Search() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<form onSubmit={onSubmit} className="w-max-[550px] relative w-full lg:w-80 xl:w-full">
|
<form onSubmit={onSubmit} className={styles.searchForm}>
|
||||||
<input
|
<input
|
||||||
key={searchParams?.get('q')}
|
key={searchParams?.get('q')}
|
||||||
type="text"
|
type="text"
|
||||||
@ -33,10 +34,10 @@ export default function Search() {
|
|||||||
placeholder="Search for products..."
|
placeholder="Search for products..."
|
||||||
autoComplete="off"
|
autoComplete="off"
|
||||||
defaultValue={searchParams?.get('q') || ''}
|
defaultValue={searchParams?.get('q') || ''}
|
||||||
className="w-full rounded-lg border bg-white px-4 py-2 text-sm text-black placeholder:text-neutral-500 dark:border-neutral-800 dark:bg-transparent dark:text-white dark:placeholder:text-neutral-400"
|
className={styles.searchInput}
|
||||||
/>
|
/>
|
||||||
<div className="absolute right-0 top-0 mr-3 flex h-full items-center">
|
<div className={styles.searchIconContainer}>
|
||||||
<MagnifyingGlassIcon className="h-4" />
|
<MagnifyingGlassIcon className={styles.searchIcon} />
|
||||||
</div>
|
</div>
|
||||||
</form>
|
</form>
|
||||||
);
|
);
|
||||||
@ -44,13 +45,10 @@ export default function Search() {
|
|||||||
|
|
||||||
export function SearchSkeleton() {
|
export function SearchSkeleton() {
|
||||||
return (
|
return (
|
||||||
<form className="w-max-[550px] relative w-full lg:w-80 xl:w-full">
|
<form className={styles.searchForm}>
|
||||||
<input
|
<input placeholder="Search for products..." className={styles.searchInput} />
|
||||||
placeholder="Search for products..."
|
<div className={styles.searchIconContainer}>
|
||||||
className="w-full rounded-lg border bg-white px-4 py-2 text-sm text-black placeholder:text-neutral-500 dark:border-neutral-800 dark:bg-transparent dark:text-white dark:placeholder:text-neutral-400"
|
<MagnifyingGlassIcon className={styles.searchIcon} />
|
||||||
/>
|
|
||||||
<div className="absolute right-0 top-0 mr-3 flex h-full items-center">
|
|
||||||
<MagnifyingGlassIcon className="h-4" />
|
|
||||||
</div>
|
</div>
|
||||||
</form>
|
</form>
|
||||||
);
|
);
|
||||||
|
Loading…
x
Reference in New Issue
Block a user