Merged in fix/SW-378-footer-language-switcher (pull request #579)

fix(SW-378): Added close button to footer language switcher and made it slide up from below

Approved-by: Fredrik Thorsson
Approved-by: Matilda Landström
This commit is contained in:
Pontus Dreij
2024-09-13 15:01:13 +00:00
13 changed files with 219 additions and 56 deletions

View File

@@ -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 (
<div>
{isMobileHeader ? (
<div className={styles.backWrapper}>
<button
type="button"
className={styles.backButton}
onClick={() => toggleDropdown(position)}
>
<ChevronLeftIcon color="red" />
<Subtitle type="one">
{intl.formatMessage({
id: "Main menu",
})}
</Subtitle>
</button>
</div>
) : null}
{isFooter ? (
<div className={styles.closeWrapper}>
<button
type="button"
className={styles.closeButton}
aria-label={intl.formatMessage({
id: "Close menu",
})}
onClick={() => toggleDropdown(position)}
>
<span className={styles.bar}></span>
</button>
</div>
) : null}
{children}
</div>
)
}

View File

@@ -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;
}
}

View File

@@ -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 (
<div className={styles.languageSwitcherContent} ref={languageSwitcherRef}>
{type === "mobileHeader" ? (
<div className={styles.backWrapper}>
<button
type="button"
className={styles.backButton}
onClick={() => toggleDropdown(position)}
>
<ChevronLeftIcon color="red" />
<Subtitle type="one">Main Menu</Subtitle>
</button>
</div>
) : null}
<div className={styles.languageWrapper}>
<Subtitle className={styles.subtitle} type="two">
{intl.formatMessage({ id: "Select your language" })}

View File

@@ -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);

View File

@@ -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 ? (
<LanguageSwitcherContent urls={urls} type={type} />
<LanguageSwitcherContainer type={type}>
<LanguageSwitcherContent urls={urls} />
</LanguageSwitcherContainer>
) : null}
</div>
</div>

View File

@@ -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%;
}