From ab83bf09905404c9b6eee2805271c5d806d32d2a Mon Sep 17 00:00:00 2001 From: Benno Tielen Date: Fri, 22 Nov 2024 18:22:12 +0100 Subject: [PATCH] feature: responsive menu --- src/app/globals.css | 2 +- src/app/layout.tsx | 176 ++++++++++++- src/components/MegaMenu/MegaMenu.tsx | 13 +- src/components/MegaMenu/styles.module.scss | 57 ++++- src/components/Menu/Menu.stories.ts | 178 ++++++++++++- src/components/Menu/Menu.tsx | 274 ++++++--------------- src/components/Menu/menu.types.ts | 33 +++ src/components/Menu/styles.module.scss | 42 +++- 8 files changed, 557 insertions(+), 218 deletions(-) create mode 100644 src/components/Menu/menu.types.ts diff --git a/src/app/globals.css b/src/app/globals.css index 94846a9..db1abba 100644 --- a/src/app/globals.css +++ b/src/app/globals.css @@ -14,4 +14,4 @@ main { .mainContent { font-size: 20px; line-height: 147%; -} +} \ No newline at end of file diff --git a/src/app/layout.tsx b/src/app/layout.tsx index 9b3c770..63847d1 100644 --- a/src/app/layout.tsx +++ b/src/app/layout.tsx @@ -16,7 +16,181 @@ export default function RootLayout({ return ( - +
{children}
diff --git a/src/components/MegaMenu/MegaMenu.tsx b/src/components/MegaMenu/MegaMenu.tsx index 3eba282..822ed69 100644 --- a/src/components/MegaMenu/MegaMenu.tsx +++ b/src/components/MegaMenu/MegaMenu.tsx @@ -12,6 +12,7 @@ type MegaMenuProps = { type ItemProps = { title: string; description: string + icon?: string href: string } @@ -20,11 +21,13 @@ type ItemGroupProps = { items: ItemProps[] } -const Item = ({href, title, description}: ItemProps) => { +const Item = ({href, title, description, icon}: ItemProps) => { return ( -
-
+ {icon && +
+
+ }
{title} @@ -41,7 +44,9 @@ const ItemGroup = ({title, items}: ItemGroupProps) => { return (
{title}
- {items.map(item => )} +
+ {items.map(item => )} +
) } diff --git a/src/components/MegaMenu/styles.module.scss b/src/components/MegaMenu/styles.module.scss index 2b6ce3a..3b5c452 100644 --- a/src/components/MegaMenu/styles.module.scss +++ b/src/components/MegaMenu/styles.module.scss @@ -1,10 +1,8 @@ @import "template.scss"; -$width: 220px; - .menu { background-color: $shade3; - display: inline-flex; + display: flex; gap: 20px; } @@ -36,7 +34,6 @@ $width: 220px; .itemGroup { padding: 40px; - width: $width; } .groupTitle { @@ -68,4 +65,56 @@ $width: 220px; font-size: 16px; font-weight: 300; line-height: 95%; +} + +@media screen and (max-width: 576px) { + .menu { + flex-direction: column; + gap: 30px; + background-color: inherit; + } + + .menu, .itemGroup, .groupTitle, .itemTitle { + font-size: 15px; + } + + .itemGroup { + padding: 0px; + } + + .groupTitle { + margin: 0; + color: #2c2c2c; + } + + .itemGroupContent { + display: flex; + flex-wrap: wrap; + gap: 10px + } + + .itemDescription { + color: #2c2c2c; + } + + .item { + flex: 1 1 40%; + height: 100px; + box-sizing: border-box; + padding: 10px; + background-color: $shade3; + text-align: center; + margin: 0; + border-radius: 5px; + justify-content: center; + } + + .itemDescription { + font-weight: 300; + font-size: 11px; + } + + .bibleText { + display: none; + } } \ No newline at end of file diff --git a/src/components/Menu/Menu.stories.ts b/src/components/Menu/Menu.stories.ts index af3bf4b..18cf288 100644 --- a/src/components/Menu/Menu.stories.ts +++ b/src/components/Menu/Menu.stories.ts @@ -9,5 +9,181 @@ type Story = StoryObj export default meta export const Default: Story = { - args: {}, + args: { + menu: { + leftItems: [ + { + text: 'Home', + href: '/' + }, + { + text: 'Gemeinschaft finden', + megaMenu: { + text: { + quote: '', + source: '' + }, + groups: [ + { + title: "Gemeinden", + items: [ + { + title: "St. Richard", + description: "Mehr informationen", + href: "/gemeinde/st-richard" + }, + { + title: "St. Christophorus", + description: "Mehr informationen", + href: "/gemeinde/st-christophorus" + }, + { + title: "St. Clara", + description: "Mehr informationen", + href: "/gemeinde/st-clara" + }, + ] + }, + { + title: "Gruppen", + items: [ + { + title: "Kathoccino", + description: "Begegnung mit Gott", + href: "https://" + }, + { + title: "Credo & Agape", + description: "Gebet der Meditation", + href: "https://" + }, + { + title: "Mädchengruppe", + description: "Stille Begegnung mit Gott", + href: "https://" + }, + { + title: "Alphakurs", + description: "Dank, Ehre und Freude", + href: "https://" + }, + ] + }, + { + title: "Aktivitaten", + items: [ + { + title: "Kochen", + description: "Begegnung mit Gott", + href: "https://" + }, + { + title: "Lernen", + description: "Gebet der Meditation", + href: "https://" + }, + { + title: "Wandern", + description: "Stille Begegnung mit Gott", + href: "https://" + }, + { + title: "Singen", + description: "Dank, Ehre und Freude", + href: "https://" + }, + ] + } + ] + } + }, + { + text: 'Glauben lauben', + megaMenu: { + text: { + quote: '', + source: '' + }, + groups: [ + { + title: "Sakramenten", + items: [ + { + title: "Taufe", + description: "Neues Leben in Christus", + href: "https://" + }, + { + title: "Eucharistie", + description: "Gemeinschaft durch Brot und Wein", + href: "https://" + }, + { + title: "Firmung", + description: "Stärkung im Heiligen Geist", + href: "https://" + }, + { + title: "Ehe", + description: "Bund in Liebe, Treue", + href: "https://" + }, + { + title: "Beichte", + description: "Sündenbekenntnis, Vergebung und Neuanfang mit Gottes Gnade", + href: "https://" + }, + { + title: "Krankensalbung", + description: "Stärkung und Gottes Beistand", + href: "https://" + } + ] + }, + { + title: "Gebet", + items: [ + { + title: "Gottesdienste", + description: "Begegnung mit Gott", + href: "https://" + }, + { + title: "Rosenkranz", + description: "Gebet der Meditation", + href: "https://" + }, + { + title: "Anbetung", + description: "Stille Begegnung mit Gott", + href: "https://" + }, + { + title: "Lobpreis", + description: "Dank, Ehre und Freude", + href: "https://" + }, + ] + } + ] + } + }, + { + text: 'Kontakt', + href: '/kontakt' + } + ], + rightItems: [ + { + text: 'Mithelfen', + href: '/mithelfen', + }, + { + text: 'Neu hier?', + href: '/ich-bin-neu', + display: "button" + } + ] + } + }, } diff --git a/src/components/Menu/Menu.tsx b/src/components/Menu/Menu.tsx index 0c3c0ac..bae6f08 100644 --- a/src/components/Menu/Menu.tsx +++ b/src/components/Menu/Menu.tsx @@ -4,216 +4,88 @@ import styles from './styles.module.scss' import MenuIcon from './menu.svg' import Image from 'next/image' import classNames from 'classnames' +import {Menu as MenuType, MenuItem as MenuItemType} from "./menu.types" +import { Logo } from '@/components/Logo/Logo' import { useState } from 'react' import { MegaMenu } from '@/components/MegaMenu/MegaMenu' +const MenuItem = ({text, href, display = "normal", megaMenu}: MenuItemType) => { + const className = classNames({ + [styles.menuLink]: display === "normal", + [styles.button]: display === "button" + }); -export const Menu = () => { - const [displayMenu2, setDisplayMenu2] = useState(false); - const [displayMenu1, setDisplayMenu1] = useState(false); - - - const displayFirstMenu = () => { - setDisplayMenu1(true); - setDisplayMenu2(false); - } - - const displaySecondMenu = () => { - setDisplayMenu2(true) - setDisplayMenu1(false) - } - - const displayNothing = () => { - setDisplayMenu1(false); - setDisplayMenu2(false); - } + const [displayMegaMenu, setDisplayMegaMenu] = useState(false) return ( <> - -
setDisplayMenu2(false)} - > - setDisplayMenu2(false)} - groups={[ - { - title: "Sakramenten", - items: [ - { - title: "Taufe", - description: "Neues Leben in Christus", - href: "https://" - }, - { - title: "Eucharistie", - description: "Gemeinschaft durch Brot und Wein", - href: "https://" - }, - { - title: "Firmung", - description: "Stärkung im Heiligen Geist", - href: "https://" - }, - { - title: "Ehe", - description: "Bund in Liebe, Treue", - href: "https://" - }, - { - title: "Beichte", - description: "Sündenbekenntnis, Vergebung und Neuanfang mit Gottes Gnade", - href: "https://" - }, - { - title: "Krankensalbung", - description: "Stärkung und Gottes Beistand", - href: "https://" - } - ] - }, - { - title: "Gebet", - items: [ - { - title: "Gottesdienste", - description: "Begegnung mit Gott", - href: "https://" - }, - { - title: "Rosenkranz", - description: "Gebet der Meditation", - href: "https://" - }, - { - title: "Anbetung", - description: "Stille Begegnung mit Gott", - href: "https://" - }, - { - title: "Lobpreis", - description: "Dank, Ehre und Freude", - href: "https://" - }, - ] - } - ]} /> -
-
setDisplayMenu1(false)} - > - setDisplayMenu1(false)} - groups={[ - { - title: "Gemeinden", - items: [ - { - title: "St. Richard", - description: "Mehr informationen", - href: "/gemeinde/st-richard" - }, - { - title: "St. Christophorus", - description: "Mehr informationen", - href: "/gemeinde/st-christophorus" - }, - { - title: "St. Clara", - description: "Mehr informationen", - href: "/gemeinde/st-clara" - }, - ] - }, - { - title: "Gruppen", - items: [ - { - title: "Kathoccino", - description: "Begegnung mit Gott", - href: "https://" - }, - { - title: "Credo & Agape", - description: "Gebet der Meditation", - href: "https://" - }, - { - title: "Mädchengruppe", - description: "Stille Begegnung mit Gott", - href: "https://" - }, - { - title: "Alphakurs", - description: "Dank, Ehre und Freude", - href: "https://" - }, - ] - }, - { - title: "Aktivitaten", - items: [ - { - title: "Kochen", - description: "Begegnung mit Gott", - href: "https://" - }, - { - title: "Lernen", - description: "Gebet der Meditation", - href: "https://" - }, - { - title: "Wandern", - description: "Stille Begegnung mit Gott", - href: "https://" - }, - { - title: "Singen", - description: "Dank, Ehre und Freude", - href: "https://" - }, - ] - } - ]} /> -
+ } + + + ) +} + +type MenuItemsProps = { + items: MenuItemType[] +} + +const MenuItems = ({items}: MenuItemsProps) => { + return ( + <> + {items.map(item => + + )} + + ) +} + +type MenuProps = { + menu: MenuType +} + +export const Menu = ({menu}: MenuProps) => { + + const [displayMenuMobile, setDisplayMenuMobile] = useState(false) + + + return ( + <> + + ) diff --git a/src/components/Menu/menu.types.ts b/src/components/Menu/menu.types.ts new file mode 100644 index 0000000..308ec24 --- /dev/null +++ b/src/components/Menu/menu.types.ts @@ -0,0 +1,33 @@ +export type Menu = { + leftItems: MenuItem[] + rightItems: MenuItem[] +} + +export type MenuItem = { + text: string, + href?: string + megaMenu?: MegaMenu + display?: "normal" | "button" +} + +type MegaMenu = { + groups: MegaMenuGroup[] + text: MegaMenuText +} + +type MegaMenuGroup = { + title: string + items: MegaMenuItem[] +} + +type MegaMenuItem = { + title: string, + description: string + href: string + icon?: string +} + +type MegaMenuText = { + quote: string + source: string +} \ No newline at end of file diff --git a/src/components/Menu/styles.module.scss b/src/components/Menu/styles.module.scss index 41f2e1b..4b31936 100644 --- a/src/components/Menu/styles.module.scss +++ b/src/components/Menu/styles.module.scss @@ -2,7 +2,6 @@ .nav { display: flex; - align-items: center; gap: 20px; color: $base-color; padding: 15px 45px; @@ -14,6 +13,8 @@ box-sizing: border-box; z-index: 1; backdrop-filter: blur(8px); + font-size: 18px; + align-items: baseline; } .navMobile { @@ -23,6 +24,7 @@ .itemsLeft { display: flex; gap: 30px; + flex-grow: 1; } .menuLink { @@ -30,6 +32,7 @@ text-decoration: none; font-weight: 600; transition: opacity 100ms ease-in; + cursor: pointer; } .menuLink:hover { @@ -37,10 +40,8 @@ } .itemsRight { - margin-left: auto; display: flex; gap: 20px; - justify-content: flex-end; align-items: baseline; } @@ -48,6 +49,8 @@ padding: 10px; border-radius: 10px; border: none; + color: inherit; + text-decoration: none; background-color: #eeeeee; transition: background-color 0.1s ease-in-out; font-family: inherit; @@ -62,17 +65,44 @@ .megaMenu { position: fixed; top: 76px; + left: 0; + width: 100%; z-index: 8; - opacity: 0; - transition: opacity 0.2s ease-in-out; } @media screen and (max-width: 800px) { + .nav { + flex-direction: column; + padding: 15px 15px; + align-items: inherit; + } + + .megaMenu { + position: inherit; + } + .navMobile { - display: block; + display: flex; + align-items: center; + justify-content: space-between; } .itemsLeft { + padding-bottom: 15px; + border-bottom: 1px solid #d0d0d0; + } + + .itemsLeft, .itemsRight { + gap: 10px; + flex-direction: column; + } + + .hide { display: none; } + + .full { + height: 100vh; + overflow: scroll; + } }