diff --git a/components/LanguageSwitcher/LanguageSwitcherContainer/index.tsx b/components/LanguageSwitcher/LanguageSwitcherContainer/index.tsx
new file mode 100644
index 000000000..ada415172
--- /dev/null
+++ b/components/LanguageSwitcher/LanguageSwitcherContainer/index.tsx
@@ -0,0 +1,63 @@
+import { useIntl } from "react-intl"
+
+import useDropdownStore from "@/stores/main-menu"
+
+import { ChevronLeftIcon } from "@/components/Icons"
+import Subtitle from "@/components/TempDesignSystem/Text/Subtitle"
+
+import styles from "./languageSwitcherContainer.module.css"
+
+import { DropdownTypeEnum } from "@/types/components/dropdown/dropdown"
+import {
+ type LanguageSwitcherContainerProps,
+ LanguageSwitcherTypesEnum,
+} from "@/types/components/languageSwitcher/languageSwitcher"
+
+export default function LanguageSwitcherContainer({
+ children,
+ type,
+}: LanguageSwitcherContainerProps) {
+ const { toggleDropdown } = useDropdownStore()
+ const intl = useIntl()
+ const isFooter = type === LanguageSwitcherTypesEnum.Footer
+ const isMobileHeader = type === LanguageSwitcherTypesEnum.MobileHeader
+ const position = isFooter
+ ? DropdownTypeEnum.FooterLanguageSwitcher
+ : DropdownTypeEnum.HamburgerMenu
+
+ return (
+
+ {isMobileHeader ? (
+
+
+
+ ) : null}
+ {isFooter ? (
+
+
+
+ ) : null}
+ {children}
+
+ )
+}
diff --git a/components/LanguageSwitcher/LanguageSwitcherContainer/languageSwitcherContainer.module.css b/components/LanguageSwitcher/LanguageSwitcherContainer/languageSwitcherContainer.module.css
new file mode 100644
index 000000000..e683a5e26
--- /dev/null
+++ b/components/LanguageSwitcher/LanguageSwitcherContainer/languageSwitcherContainer.module.css
@@ -0,0 +1,70 @@
+.backWrapper {
+ background-color: var(--Base-Surface-Secondary-light-Normal);
+ padding: var(--Spacing-x2);
+}
+
+.backButton {
+ background-color: transparent;
+ border: none;
+ padding: 0;
+ cursor: pointer;
+ display: flex;
+ align-items: center;
+ gap: var(--Spacing-x1);
+}
+
+.closeWrapper {
+ display: flex;
+ justify-content: flex-end;
+ padding: var(--Spacing-x2);
+ border-bottom: 1px solid var(--Base-Border-Subtle);
+}
+
+.closeButton {
+ background-color: transparent;
+ border: none;
+ cursor: pointer;
+ justify-self: flex-start;
+ padding: 11px var(--Spacing-x1) var(--Spacing-x2);
+ user-select: none;
+}
+
+.bar,
+.bar::after,
+.bar::before {
+ background: var(--Base-Text-High-contrast);
+ border-radius: 2.3px;
+ display: inline-block;
+ height: 3px;
+ position: relative;
+ transition: all 0.3s;
+ width: var(--Spacing-x4);
+}
+
+.bar::after,
+.bar::before {
+ content: "";
+ left: 0;
+ position: absolute;
+ top: 0;
+ transform-origin: 50% 50%;
+ width: var(--Spacing-x4);
+}
+
+.bar {
+ background: transparent;
+}
+
+.bar::after {
+ transform: rotate(-45deg);
+}
+
+.bar::before {
+ transform: rotate(45deg);
+}
+
+@media screen and (min-width: 768px) {
+ .closeWrapper {
+ display: none;
+ }
+}
diff --git a/components/LanguageSwitcher/LanguageSwitcherContent/index.tsx b/components/LanguageSwitcher/LanguageSwitcherContent/index.tsx
index 9aebfa711..3533ecb93 100644
--- a/components/LanguageSwitcher/LanguageSwitcherContent/index.tsx
+++ b/components/LanguageSwitcher/LanguageSwitcherContent/index.tsx
@@ -3,9 +3,8 @@
import { useIntl } from "react-intl"
import { Lang, languages } from "@/constants/languages"
-import useDropdownStore from "@/stores/main-menu"
-import { CheckIcon, ChevronLeftIcon } from "@/components/Icons"
+import { CheckIcon } from "@/components/Icons"
import Link from "@/components/TempDesignSystem/Link"
import Subtitle from "@/components/TempDesignSystem/Text/Subtitle"
import useLang from "@/hooks/useLang"
@@ -13,38 +12,19 @@ import { useTrapFocus } from "@/hooks/useTrapFocus"
import styles from "./languageSwitcherContent.module.css"
-import { DropdownTypeEnum } from "@/types/components/dropdown/dropdown"
-import type { LanguageSwitcherProps } from "@/types/components/languageSwitcher/languageSwitcher"
+import type { LanguageSwitcherContentProps } from "@/types/components/languageSwitcher/languageSwitcher"
export default function LanguageSwitcherContent({
urls,
- type,
-}: LanguageSwitcherProps) {
+}: LanguageSwitcherContentProps) {
const intl = useIntl()
const currentLanguage = useLang()
- const { toggleDropdown } = useDropdownStore()
+
const languageSwitcherRef = useTrapFocus()
const urlKeys = Object.keys(urls) as Lang[]
- const position =
- type === "footer"
- ? DropdownTypeEnum.FooterLanguageSwitcher
- : DropdownTypeEnum.HamburgerMenu
return (
- {type === "mobileHeader" ? (
-
-
-
- ) : null}
-
{intl.formatMessage({ id: "Select your language" })}
diff --git a/components/LanguageSwitcher/LanguageSwitcherContent/languageSwitcherContent.module.css b/components/LanguageSwitcher/LanguageSwitcherContent/languageSwitcherContent.module.css
index 465b39c23..24e3febb8 100644
--- a/components/LanguageSwitcher/LanguageSwitcherContent/languageSwitcherContent.module.css
+++ b/components/LanguageSwitcher/LanguageSwitcherContent/languageSwitcherContent.module.css
@@ -1,22 +1,3 @@
-.backWrapper {
- background-color: var(--Base-Surface-Secondary-light-Normal);
- padding: var(--Spacing-x2);
-}
-
-.backButton {
- background-color: transparent;
- border: none;
- color: var(--Base-Text-High-contrast);
- font-family: var(--typography-Subtitle-1-fontFamily);
- font-weight: var(--typography-Subtitle-1-fontWeight);
- font-size: var(--typography-Subtitle-1-Mobile-fontSize);
- padding: 0;
- cursor: pointer;
- display: flex;
- align-items: center;
- gap: var(--Spacing-x1);
-}
-
.languageWrapper {
display: grid;
gap: var(--Spacing-x3);
diff --git a/components/LanguageSwitcher/index.tsx b/components/LanguageSwitcher/index.tsx
index 65888d578..7a5ecb6b2 100644
--- a/components/LanguageSwitcher/index.tsx
+++ b/components/LanguageSwitcher/index.tsx
@@ -1,5 +1,6 @@
"use client"
+import { useEffect } from "react"
import { useIntl } from "react-intl"
import { languages } from "@/constants/languages"
@@ -9,13 +10,17 @@ import { ChevronDownIcon, GlobeIcon } from "@/components/Icons"
import { useHandleKeyUp } from "@/hooks/useHandleKeyUp"
import useLang from "@/hooks/useLang"
+import LanguageSwitcherContainer from "./LanguageSwitcherContainer"
import LanguageSwitcherContent from "./LanguageSwitcherContent"
import { languageSwitcherVariants } from "./variants"
import styles from "./languageSwitcher.module.css"
import { DropdownTypeEnum } from "@/types/components/dropdown/dropdown"
-import type { LanguageSwitcherProps } from "@/types/components/languageSwitcher/languageSwitcher"
+import {
+ type LanguageSwitcherProps,
+ LanguageSwitcherTypesEnum,
+} from "@/types/components/languageSwitcher/languageSwitcher"
export default function LanguageSwitcher({
urls,
@@ -30,8 +35,11 @@ export default function LanguageSwitcher({
isHeaderLanguageSwitcherMobileOpen,
} = useDropdownStore()
- const position = type === "footer" ? "footer" : "header"
- const color = type === "footer" ? "pale" : "burgundy"
+ const isFooter = type === LanguageSwitcherTypesEnum.Footer
+ const isHeader = !isFooter
+
+ const position = isFooter ? "footer" : "header"
+ const color = isFooter ? "pale" : "burgundy"
const dropdownType = {
footer: DropdownTypeEnum.FooterLanguageSwitcher,
@@ -40,8 +48,8 @@ export default function LanguageSwitcher({
}[type]
const isLanguageSwitcherOpen =
- (type === "footer" && isFooterLanguageSwitcherOpen) ||
- (type !== "footer" &&
+ (isFooter && isFooterLanguageSwitcherOpen) ||
+ (isHeader &&
(isHeaderLanguageSwitcherOpen || isHeaderLanguageSwitcherMobileOpen))
useHandleKeyUp((event: KeyboardEvent) => {
@@ -50,6 +58,18 @@ export default function LanguageSwitcher({
}
})
+ useEffect(() => {
+ if (isFooter && isFooterLanguageSwitcherOpen) {
+ document.body.style.overflow = "hidden"
+ } else {
+ document.body.style.overflow = ""
+ }
+
+ return () => {
+ document.body.style.overflow = ""
+ }
+ }, [isFooter, isFooterLanguageSwitcherOpen])
+
const classNames = languageSwitcherVariants({ color, position })
return (
@@ -78,7 +98,9 @@ export default function LanguageSwitcher({
className={`${styles.dropdown} ${isLanguageSwitcherOpen ? styles.isExpanded : ""}`}
>
{isLanguageSwitcherOpen ? (
-
+
+
+
) : null}
diff --git a/components/LanguageSwitcher/languageSwitcher.module.css b/components/LanguageSwitcher/languageSwitcher.module.css
index 6c85a22aa..4cde01f31 100644
--- a/components/LanguageSwitcher/languageSwitcher.module.css
+++ b/components/LanguageSwitcher/languageSwitcher.module.css
@@ -31,20 +31,36 @@
.dropdown {
position: fixed;
- top: var(--main-menu-mobile-height);
- right: -100vw;
- bottom: 0;
width: 100%;
background-color: var(--Base-Surface-Primary-light-Normal);
- transition: right 0.3s;
z-index: var(--menu-overlay-z-index);
}
-.dropdown.isExpanded {
+.top .dropdown {
+ right: -100vw;
+ top: var(--main-menu-mobile-height);
+ bottom: 0;
+ transition: right 0.3s;
+}
+
+.top .dropdown.isExpanded {
display: block;
right: 0;
}
+.bottom .dropdown {
+ transition: transform 0.3s;
+ width: 100%;
+ height: 100vh;
+ left: 0;
+ bottom: 0;
+ transform: translateY(100%);
+}
+
+.bottom .dropdown.isExpanded {
+ transform: translateY(0);
+}
+
@media screen and (min-width: 768px) {
.languageSwitcher {
position: relative;
@@ -81,10 +97,16 @@
}
.bottom .dropdown {
- top: auto;
+ transition: none;
+ height: auto;
+ left: -100%;
bottom: 2.25rem;
}
+ .bottom .dropdown.isExpanded {
+ display: block;
+ }
+
.bottom .dropdown::before {
top: 100%;
}
diff --git a/i18n/dictionaries/da.json b/i18n/dictionaries/da.json
index 788d15008..7b6206a20 100644
--- a/i18n/dictionaries/da.json
+++ b/i18n/dictionaries/da.json
@@ -100,6 +100,7 @@
"Log in here": "Log ind her",
"Log in/Join": "Log på/Tilmeld dig",
"Log out": "Log ud",
+ "Main menu": "Hovedmenu",
"Manage preferences": "Administrer præferencer",
"Map": "Kort",
"Map of HOTEL_NAME": "Map of {hotelName}",
diff --git a/i18n/dictionaries/de.json b/i18n/dictionaries/de.json
index fc35327bd..6e1a4b147 100644
--- a/i18n/dictionaries/de.json
+++ b/i18n/dictionaries/de.json
@@ -98,6 +98,7 @@
"Log in here": "Hier einloggen",
"Log in/Join": "Log in/Anmelden",
"Log out": "Ausloggen",
+ "Main menu": "Hauptmenü",
"Manage preferences": "Verwalten von Voreinstellungen",
"Map": "Karte",
"Map of HOTEL_NAME": "Map of {hotelName}",
diff --git a/i18n/dictionaries/en.json b/i18n/dictionaries/en.json
index 0b8c43c6b..bd73a9f0a 100644
--- a/i18n/dictionaries/en.json
+++ b/i18n/dictionaries/en.json
@@ -104,6 +104,7 @@
"Log in here": "Log in here",
"Log in/Join": "Log in/Join",
"Log out": "Log out",
+ "Main menu": "Main menu",
"Manage preferences": "Manage preferences",
"Map": "Map",
"Map of HOTEL_NAME": "Map of {hotelName}",
diff --git a/i18n/dictionaries/fi.json b/i18n/dictionaries/fi.json
index 551943aaf..a97dea3fe 100644
--- a/i18n/dictionaries/fi.json
+++ b/i18n/dictionaries/fi.json
@@ -99,6 +99,7 @@
"Log in here": "Kirjaudu sisään",
"Log in/Join": "Kirjaudu sisään/Liittyä",
"Log out": "Kirjaudu ulos",
+ "Main menu": "Päävalikko",
"Manage preferences": "Asetusten hallinta",
"Map": "Kartta",
"Map of HOTEL_NAME": "Map of {hotelName}",
diff --git a/i18n/dictionaries/no.json b/i18n/dictionaries/no.json
index 511e87c25..81ef12cc2 100644
--- a/i18n/dictionaries/no.json
+++ b/i18n/dictionaries/no.json
@@ -99,6 +99,7 @@
"Log in here": "Logg inn her",
"Log in/Join": "Logg på/Bli med",
"Log out": "Logg ut",
+ "Main menu": "Hovedmeny",
"Manage preferences": "Administrer preferanser",
"Map": "Kart",
"Map of HOTEL_NAME": "Map of {hotelName}",
diff --git a/i18n/dictionaries/sv.json b/i18n/dictionaries/sv.json
index bbb8eed52..0cf45ea96 100644
--- a/i18n/dictionaries/sv.json
+++ b/i18n/dictionaries/sv.json
@@ -101,6 +101,7 @@
"Log in here": "Logga in här",
"Log in/Join": "Logga in/Gå med",
"Log out": "Logga ut",
+ "Main menu": "Huvudmeny",
"Manage preferences": "Hantera inställningar",
"Map": "Karta",
"Map of HOTEL_NAME": "Map of {hotelName}",
diff --git a/types/components/languageSwitcher/languageSwitcher.ts b/types/components/languageSwitcher/languageSwitcher.ts
index 6672fbe83..312d28712 100644
--- a/types/components/languageSwitcher/languageSwitcher.ts
+++ b/types/components/languageSwitcher/languageSwitcher.ts
@@ -1,6 +1,25 @@
+import { ReactElement } from "react"
+
import type { LanguageSwitcherData } from "@/types/requests/languageSwitcher"
+export enum LanguageSwitcherTypesEnum {
+ MobileHeader = "mobileHeader",
+ DesktopHeader = "desktopHeader",
+ Footer = "footer",
+}
+
+export type LanguageSwitcherTypes = `${LanguageSwitcherTypesEnum}`
+
export interface LanguageSwitcherProps {
- type: "mobileHeader" | "desktopHeader" | "footer"
+ type: LanguageSwitcherTypes
urls: LanguageSwitcherData
}
+
+export interface LanguageSwitcherContentProps {
+ urls: LanguageSwitcherData
+}
+
+export interface LanguageSwitcherContainerProps {
+ type: LanguageSwitcherTypes
+ children: ReactElement
+}