diff --git a/components/Header/MainMenu/MyPagesMenu/Avatar/avatar.module.css b/components/Header/MainMenu/Avatar/avatar.module.css similarity index 100% rename from components/Header/MainMenu/MyPagesMenu/Avatar/avatar.module.css rename to components/Header/MainMenu/Avatar/avatar.module.css diff --git a/components/Header/MainMenu/MyPagesMenu/Avatar/index.tsx b/components/Header/MainMenu/Avatar/index.tsx similarity index 100% rename from components/Header/MainMenu/MyPagesMenu/Avatar/index.tsx rename to components/Header/MainMenu/Avatar/index.tsx diff --git a/components/Header/MainMenu/MobileMenu/mobileMenu.module.css b/components/Header/MainMenu/MobileMenu/mobileMenu.module.css index 1e8fad253..da62ccfff 100644 --- a/components/Header/MainMenu/MobileMenu/mobileMenu.module.css +++ b/components/Header/MainMenu/MobileMenu/mobileMenu.module.css @@ -64,20 +64,6 @@ transform: rotate(45deg); } -@media screen and (min-width: 768px) { - .hamburger { - display: none; - } -} - -.overlay { - position: absolute; - top: var(--main-menu-mobile-height); - bottom: 0; - left: 0; - right: 0; -} - .modal { position: fixed; top: var(--main-menu-mobile-height); @@ -108,3 +94,9 @@ display: grid; gap: var(--Spacing-x2); } + +@media screen and (min-width: 768px) { + .hamburger { + display: none; + } +} diff --git a/components/Header/MainMenu/MyPagesMenu/index.tsx b/components/Header/MainMenu/MyPagesMenu/index.tsx index 42cd370ab..02d30cad7 100644 --- a/components/Header/MainMenu/MyPagesMenu/index.tsx +++ b/components/Header/MainMenu/MyPagesMenu/index.tsx @@ -2,113 +2,54 @@ import { useIntl } from "react-intl" -import { logout } from "@/constants/routes/handleAuth" -import { myPages } from "@/constants/routes/myPages" import useDropdownStore from "@/stores/main-menu" -import { ArrowRightIcon, ChevronDownIcon } from "@/components/Icons" -import Link from "@/components/TempDesignSystem/Link" +import { ChevronDownIcon } from "@/components/Icons" +import Subtitle from "@/components/TempDesignSystem/Text/Subtitle" +import { useHandleKeyUp } from "@/hooks/useHandleKeyUp" import useLang from "@/hooks/useLang" import { getInitials } from "@/utils/user" +import Avatar from "../Avatar" import MainMenuButton from "../MainMenuButton" -import Avatar from "./Avatar" +import MyPagesMenuContent from "../MyPagesMenuContent" import styles from "./myPagesMenu.module.css" import { MyPagesMenuProps } from "@/types/components/header/myPagesMenu" -// This component is mostly the same as MyPagesMobileDropdown, but with a -// different name and some different styles. Should probably be refactored in -// a later stage to fit the design from Figma better. - export default function MyPagesMenu({ navigation, user }: MyPagesMenuProps) { const intl = useIntl() const lang = useLang() const { toggleMyPagesMenu, isMyPagesMenuOpen } = useDropdownStore() - if (!navigation) { - return null - } + useHandleKeyUp((event: KeyboardEvent) => { + if (event.key === "Escape" && isMyPagesMenuOpen) { + toggleMyPagesMenu() + } + }) - return user ? ( + return (
- + {intl.formatMessage({ id: "Hi" })} {user.firstName}! - + - + +
- ) : ( - - - - {intl.formatMessage({ id: "Log in/Join" })} - - ) } diff --git a/components/Header/MainMenu/MyPagesMenu/myPagesMenu.module.css b/components/Header/MainMenu/MyPagesMenu/myPagesMenu.module.css index 8d6b2fe1c..d322955e3 100644 --- a/components/Header/MainMenu/MyPagesMenu/myPagesMenu.module.css +++ b/components/Header/MainMenu/MyPagesMenu/myPagesMenu.module.css @@ -1,97 +1,47 @@ .myPagesMenu { - position: relative; -} - -.chevron { display: none; - transition: transform 0.2s; -} - -.chevron.isExpanded { - transform: rotate(180deg); -} - -.userName { - display: none; - font-weight: 600; - color: var(--Base-Text-High-contrast); -} - -.dropdown { - position: absolute; - top: 46px; - right: 0; - background-color: var(--Base-Surface-Primary-light-Normal); - padding: var(--Spacing-x2) var(--Spacing-x4); - border-radius: var(--Corner-radius-Large); - box-shadow: 0px 0px 14px 6px rgba(0, 0, 0, 0.1); - min-width: 20rem; - z-index: 1; - display: none; -} - -/* Triangle above dropdown */ -.dropdown::before { - content: ""; - position: absolute; - top: -1.25rem; - right: 2.4rem; - transform: rotate(180deg); - border-width: 0.75rem; - border-style: solid; - border-color: var(--Base-Surface-Primary-light-Normal) transparent transparent - transparent; -} - -.dropdown.isExpanded { - display: block; -} - -.friendTypeWrapper { - padding: 0 var(--Spacing-x1) var(--Spacing-x2); - font-weight: 400; - color: var(--UI-Text-Medium-contrast); -} -.friendType { - font-family: var(--typography-Title-5-fontFamily); - letter-spacing: var(--typography-Title-5-letterSpacing); - font-size: var(--typography-Caption-Bold-fontSize); - text-transform: uppercase; -} - -.friendType::after { - content: " · "; - display: inline; - padding: 0 var(--Spacing-x-half); -} - -.groups, -.menuItems { - list-style: none; -} - -.group { - padding: var(--Spacing-x2) 0; - border-top: 1px solid var(--Base-Border-Subtle); -} - -.group:last-child { - padding-bottom: 0; -} - -.arrow { - opacity: 0; -} - -.loginLink { - display: flex; - align-items: center; - gap: var(--Spacing-x1); } @media screen and (min-width: 768px) { - .userName, + .myPagesMenu { + display: block; + position: relative; + } + .chevron { - display: initial; + transition: transform 0.2s; + } + + .chevron.isExpanded { + transform: rotate(180deg); + } + + .dropdown { + position: absolute; + top: 46px; + right: 0; + background-color: var(--Base-Surface-Primary-light-Normal); + border-radius: var(--Corner-radius-Large); + box-shadow: 0px 0px 14px 6px rgba(0, 0, 0, 0.1); + min-width: 20rem; + z-index: 1; + display: none; + } + + /* Triangle above dropdown */ + .dropdown::before { + content: ""; + position: absolute; + top: -1.25rem; + right: 2.4rem; + transform: rotate(180deg); + border-width: 0.75rem; + border-style: solid; + border-color: var(--Base-Surface-Primary-light-Normal) transparent + transparent transparent; + } + + .dropdown.isExpanded { + display: block; } } diff --git a/components/Header/MainMenu/MyPagesMenuContent/index.tsx b/components/Header/MainMenu/MyPagesMenuContent/index.tsx new file mode 100644 index 000000000..e87c25a94 --- /dev/null +++ b/components/Header/MainMenu/MyPagesMenuContent/index.tsx @@ -0,0 +1,81 @@ +"use client" + +import Link from "next/link" +import { useIntl } from "react-intl" + +import { logout } from "@/constants/routes/handleAuth" + +import { ArrowRightIcon } from "@/components/Icons" +import Divider from "@/components/TempDesignSystem/Divider" +import Caption from "@/components/TempDesignSystem/Text/Caption" +import Subtitle from "@/components/TempDesignSystem/Text/Subtitle" +import useLang from "@/hooks/useLang" +import { useTrapFocus } from "@/hooks/useTrapFocus" + +import styles from "./myPagesMenuContent.module.css" + +import { MyPagesMenuContentProps } from "@/types/components/header/myPagesMenu" + +export default function MyPagesMenuContent({ + navigation, + toggleOpenStateFn, + user, +}: MyPagesMenuContentProps) { + const intl = useIntl() + const lang = useLang() + const myPagesMenuContentRef = useTrapFocus() + + if (!navigation) { + return null + } + + return ( + + ) +} diff --git a/components/Header/MainMenu/MyPagesMenuContent/myPagesMenuContent.module.css b/components/Header/MainMenu/MyPagesMenuContent/myPagesMenuContent.module.css new file mode 100644 index 000000000..800f646b5 --- /dev/null +++ b/components/Header/MainMenu/MyPagesMenuContent/myPagesMenuContent.module.css @@ -0,0 +1,74 @@ +.myPagesMenuContent { + padding: var(--Spacing-x3) var(--Spacing-x2); +} + +.intro { + padding: 0 var(--Spacing-x1); +} + +.myPagesMenuContent .friendTypeWrapper { + color: var(--UI-Text-Medium-contrast); +} + +.divider { + margin: var(--Spacing-x2) 0; +} + +.friendType { + font-family: var(--typography-Title-5-fontFamily); + letter-spacing: var(--typography-Title-5-letterSpacing); + font-size: var(--typography-Caption-Bold-fontSize); + text-transform: uppercase; +} + +.friendType::after { + content: " · "; + display: inline; + padding: 0 var(--Spacing-x-half); +} + +.groups, +.menuItems { + list-style: none; +} + +.link { + display: flex; + align-items: center; + justify-content: space-between; + text-decoration: none; + padding: var(--Spacing-x1); + gap: var(--Spacing-x-one-and-half); + color: var(--Scandic-Brand-Burgundy); + font-family: var(--typography-Body-Bold-fontFamily); + font-size: var(--typography-Body-Bold-fontSize); + font-weight: 500; + line-height: var(--typography-Body-Bold-lineHeight); + letter-spacing: var(--typography-Body-Bold-letterSpacing); + border-radius: var(--Corner-radius-Medium); +} + +.link:hover { + background-color: var(--Base-Surface-Primary-light-Hover-alt); +} + +.link.smallLink { + font-family: var(--typography-Body-Regular-fontFamily); + font-size: var(--typography-Body-Regular-fontSize); + font-weight: var(--typography-Body-Regular-fontWeight); + line-height: var(--typography-Body-Regular-lineHeight); + letter-spacing: var(--typography-Body-Regular-letterSpacing); +} + +.link:not(:hover) .arrow { + opacity: 0; +} + +@media screen and (min-width: 768px) { + .myPagesMenuContent { + padding: var(--Spacing-x2) var(--Spacing-x4); + } + .userName { + display: none; + } +} diff --git a/components/Header/MainMenu/MyPagesMobileMenu/index.tsx b/components/Header/MainMenu/MyPagesMobileMenu/index.tsx new file mode 100644 index 000000000..2a9f5dac7 --- /dev/null +++ b/components/Header/MainMenu/MyPagesMobileMenu/index.tsx @@ -0,0 +1,55 @@ +"use client" + +import { Dialog, Modal } from "react-aria-components" +import { useIntl } from "react-intl" + +import useDropdownStore from "@/stores/main-menu" + +import { useHandleKeyUp } from "@/hooks/useHandleKeyUp" +import { getInitials } from "@/utils/user" + +import Avatar from "../Avatar" +import MainMenuButton from "../MainMenuButton" +import MyPagesMenuContent from "../MyPagesMenuContent" + +import styles from "./myPagesMobileMenu.module.css" + +import { MyPagesMenuProps } from "@/types/components/header/myPagesMenu" + +export default function MyPagesMobileMenu({ + navigation, + user, +}: MyPagesMenuProps) { + const intl = useIntl() + const { toggleMyPagesMobileMenu, isMyPagesMobileMenuOpen } = + useDropdownStore() + + useHandleKeyUp((event: KeyboardEvent) => { + if (event.key === "Escape" && isMyPagesMobileMenuOpen) { + toggleMyPagesMobileMenu() + } + }) + + return ( +
+ + + + + + + + +
+ ) +} diff --git a/components/Header/MainMenu/MyPagesMobileMenu/myPagesMobileMenu.module.css b/components/Header/MainMenu/MyPagesMobileMenu/myPagesMobileMenu.module.css new file mode 100644 index 000000000..ba3a687c4 --- /dev/null +++ b/components/Header/MainMenu/MyPagesMobileMenu/myPagesMobileMenu.module.css @@ -0,0 +1,38 @@ +@keyframes slide-in { + from { + right: -100vw; + } + + to { + right: 0; + } +} + +.modal { + position: fixed; + top: var(--main-menu-mobile-height); + right: auto; + bottom: 0; + width: 100%; + background-color: var(--Base-Surface-Primary-light-Normal); + transition: right 0.3s; +} + +.modal[data-entering] { + animation: slide-in 0.3s; +} +.modal[data-exiting] { + animation: slide-in 0.3s reverse; +} + +.dialog { + height: 100%; + overflow-y: auto; +} + +@media screen and (min-width: 767px) { + .myPagesMobileMenu, + .modal { + display: none; + } +} diff --git a/components/Header/MainMenu/index.tsx b/components/Header/MainMenu/index.tsx index db7d448d2..3ce22c53a 100644 --- a/components/Header/MainMenu/index.tsx +++ b/components/Header/MainMenu/index.tsx @@ -1,13 +1,18 @@ -import Link from "next/link" +import NextLink from "next/link" +import { myPages } from "@/constants/routes/myPages" import { serverClient } from "@/lib/trpc/server" import Image from "@/components/Image" +import Link from "@/components/TempDesignSystem/Link" import { getIntl } from "@/i18n" +import { getLang } from "@/i18n/serverContext" import { navigationMenuItems } from "../tempHeaderData" +import Avatar from "./Avatar" import MobileMenu from "./MobileMenu" import MyPagesMenu from "./MyPagesMenu" +import MyPagesMobileMenu from "./MyPagesMobileMenu" import NavigationMenu from "./NavigationMenu" import styles from "./mainMenu.module.css" @@ -16,6 +21,7 @@ import { MainMenuProps } from "@/types/components/header/mainMenu" export default async function MainMenu({ languageUrls }: MainMenuProps) { const intl = await getIntl() + const lang = getLang() const myPagesNavigation = await serverClient().contentstack.myPages.navigation.get() @@ -24,7 +30,7 @@ export default async function MainMenu({ languageUrls }: MainMenuProps) { return (