fix: animations for menu

This commit is contained in:
Benno Tielen 2024-11-25 11:19:01 +01:00
parent ab83bf0990
commit b868c0a7a4
3 changed files with 74 additions and 22 deletions

View file

@ -6,7 +6,7 @@ type MegaMenuProps = {
bibleText: string, bibleText: string,
bibleBook: string, bibleBook: string,
groups: ItemGroupProps[], groups: ItemGroupProps[],
onClick?: () => void onItemClick?: () => void
} }
type ItemProps = { type ItemProps = {
@ -14,16 +14,18 @@ type ItemProps = {
description: string description: string
icon?: string icon?: string
href: string href: string
onClick?: () => void
} }
type ItemGroupProps = { type ItemGroupProps = {
title: string, title: string,
items: ItemProps[] items: ItemProps[]
onItemClick?: () => void
} }
const Item = ({href, title, description, icon}: ItemProps) => { const Item = ({href, title, description, icon, onClick}: ItemProps) => {
return ( return (
<Link href={href} className={styles.item}> <Link href={href} className={styles.item} onClick={onClick}>
{icon && {icon &&
<div className={styles.itemIcon}> <div className={styles.itemIcon}>
</div> </div>
@ -40,20 +42,26 @@ const Item = ({href, title, description, icon}: ItemProps) => {
) )
} }
const ItemGroup = ({title, items}: ItemGroupProps) => { const ItemGroup = ({title, items, onItemClick}: ItemGroupProps) => {
return ( return (
<div className={styles.itemGroup}> <div className={styles.itemGroup}>
<div className={styles.groupTitle}>{title}</div> <div className={styles.groupTitle}>{title}</div>
<div className={styles.itemGroupContent}> <div className={styles.itemGroupContent}>
{items.map(item => <Item key={item.title} title={item.title} href={item.href} description={item.description} />)} {items.map(item => <Item
key={item.title}
title={item.title}
href={item.href}
description={item.description}
onClick={onItemClick}
/>)}
</div> </div>
</div> </div>
) )
} }
export const MegaMenu = ({ bibleText, bibleBook, groups, onClick }: MegaMenuProps) => { export const MegaMenu = ({ bibleText, bibleBook, groups, onItemClick }: MegaMenuProps) => {
return ( return (
<div className={styles.menu} onClick={onClick}> <div className={styles.menu}>
<div className={styles.bibleText}> <div className={styles.bibleText}>
<div className={faustina.className}> <div className={faustina.className}>
{bibleText} {bibleText}
@ -63,7 +71,13 @@ export const MegaMenu = ({ bibleText, bibleBook, groups, onClick }: MegaMenuProp
</div> </div>
</div> </div>
{groups.map(group => <ItemGroup key={group.title} title={group.title} items={group.items} />)} {groups.map(group =>
<ItemGroup
key={group.title}
title={group.title}
items={group.items}
onItemClick={onItemClick}
/>)}
</div> </div>
) )
} }

View file

@ -6,38 +6,62 @@ import Image from 'next/image'
import classNames from 'classnames' import classNames from 'classnames'
import {Menu as MenuType, MenuItem as MenuItemType} from "./menu.types" import {Menu as MenuType, MenuItem as MenuItemType} from "./menu.types"
import { Logo } from '@/components/Logo/Logo' import { Logo } from '@/components/Logo/Logo'
import { useState } from 'react' import { useCallback, useState } from 'react'
import { MegaMenu } from '@/components/MegaMenu/MegaMenu' import { MegaMenu } from '@/components/MegaMenu/MegaMenu'
const MenuItem = ({text, href, display = "normal", megaMenu}: MenuItemType) => { type MenuItemProps = MenuItemType & {
onItemClick?: () => void
}
const MenuItem = ({text, href, display = "normal", megaMenu, onItemClick}: MenuItemProps) => {
const className = classNames({ const className = classNames({
[styles.menuLink]: display === "normal", [styles.menuLink]: display === "normal",
[styles.button]: display === "button" [styles.button]: display === "button"
}); });
const [displayMegaMenu, setDisplayMegaMenu] = useState(false) const [isActive, setIsActive] = useState<boolean>(false);
const itemClicked = useCallback(() => {
setIsActive(false);
if (onItemClick) {
onItemClick();
}
}, [setIsActive, onItemClick]);
return ( return (
<> <span
<a className={className} href={href} onClick={() => setDisplayMegaMenu(!displayMegaMenu)}> className={styles.menuItem}
onMouseEnter={() => setIsActive(true)}
onMouseLeave={() => setIsActive(false)}
>
<a className={className} href={href}>
{text} {text}
</a> </a>
{megaMenu && displayMegaMenu && {megaMenu &&
<div className={styles.megaMenu}> <div
<MegaMenu bibleText={megaMenu.text.quote} bibleBook={megaMenu.text.source} groups={megaMenu.groups} /> className={classNames({
[styles.megaMenu]: true,
[styles.megaMenuActive]: isActive
})}
>
<MegaMenu
bibleText={megaMenu.text.quote}
bibleBook={megaMenu.text.source}
groups={megaMenu.groups}
onItemClick={itemClicked}
/>
</div> </div>
} }
</> </span>
) )
} }
type MenuItemsProps = { type MenuItemsProps = {
items: MenuItemType[] items: MenuItemType[]
onItemClick?: () => void
} }
const MenuItems = ({items}: MenuItemsProps) => { const MenuItems = ({items, onItemClick}: MenuItemsProps) => {
return ( return (
<> <>
{items.map(item => {items.map(item =>
@ -47,6 +71,7 @@ const MenuItems = ({items}: MenuItemsProps) => {
href={item.href} href={item.href}
display={item.display} display={item.display}
megaMenu={item.megaMenu} megaMenu={item.megaMenu}
onItemClick={onItemClick}
/> />
)} )}
</> </>
@ -77,11 +102,17 @@ export const Menu = ({menu}: MenuProps) => {
</div> </div>
<div className={classNames(styles.itemsLeft, {[styles.hide]: !displayMenuMobile})}> <div className={classNames(styles.itemsLeft, {[styles.hide]: !displayMenuMobile})}>
<MenuItems items={menu.leftItems} /> <MenuItems
items={menu.leftItems}
onItemClick={() => setDisplayMenuMobile(false)}
/>
</div> </div>
<div className={classNames(styles.itemsRight, {[styles.hide]: !displayMenuMobile})}> <div className={classNames(styles.itemsRight, {[styles.hide]: !displayMenuMobile})}>
<MenuItems items={menu.rightItems} /> <MenuItems
items={menu.rightItems}
onItemClick={() => setDisplayMenuMobile(false)}
/>
</div> </div>
</nav> </nav>

View file

@ -64,10 +64,17 @@
.megaMenu { .megaMenu {
position: fixed; position: fixed;
top: 76px; top: 62px;
left: 0; left: 0;
width: 100%; width: 100%;
z-index: 8; z-index: 8;
max-height: 0;
overflow: hidden;
transition: max-height 0.3s ease-in-out;
}
.megaMenuActive {
max-height: 1000px;
} }
@media screen and (max-width: 800px) { @media screen and (max-width: 800px) {