feat(SW-187): Fixed LanguageSwitcher for footer
This commit is contained in:
@@ -65,5 +65,6 @@
|
||||
border-bottom: 0;
|
||||
padding-bottom: 0;
|
||||
margin-bottom: 0;
|
||||
gap: var(--Spacing-x4);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -6,8 +6,6 @@ import Footnote from "@/components/TempDesignSystem/Text/Footnote"
|
||||
import { getIntl } from "@/i18n"
|
||||
import { getLang } from "@/i18n/serverContext"
|
||||
|
||||
import { footer } from "../mockedData"
|
||||
|
||||
import styles from "./details.module.css"
|
||||
|
||||
import type { FooterDetailsProps } from "@/types/components/footer/navigation"
|
||||
@@ -22,11 +20,12 @@ function SocialIcon({ iconName }: SocialIconsProps) {
|
||||
export default async function FooterDetails({
|
||||
socialMedia,
|
||||
tertiaryLinks,
|
||||
languageUrls,
|
||||
}: FooterDetailsProps) {
|
||||
const lang = getLang()
|
||||
const { formatMessage } = await getIntl()
|
||||
const currentYear = new Date().getFullYear()
|
||||
const { languageSwitcher } = footer
|
||||
|
||||
return (
|
||||
<section className={styles.details}>
|
||||
<div className={styles.topContainer}>
|
||||
@@ -85,7 +84,9 @@ export default async function FooterDetails({
|
||||
)
|
||||
)}
|
||||
</nav>
|
||||
<LanguageSwitcher type="desktopFooter" urls={languageSwitcher.urls} />
|
||||
{languageUrls && (
|
||||
<LanguageSwitcher type="footer" urls={languageUrls} />
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
@@ -22,7 +22,7 @@
|
||||
justify-content: space-between;
|
||||
}
|
||||
|
||||
@media screen and (min-width: 767px) {
|
||||
@media screen and (min-width: 1367px) {
|
||||
.mainNavigation {
|
||||
max-width: 360px;
|
||||
}
|
||||
|
||||
@@ -27,8 +27,14 @@
|
||||
|
||||
@media screen and (min-width: 767px) {
|
||||
.secondaryNavigation {
|
||||
margin-top: 0;
|
||||
gap: 80px;
|
||||
margin-top: var(--Spacing-x4);
|
||||
gap: 120px;
|
||||
flex-direction: row;
|
||||
}
|
||||
}
|
||||
@media screen and (min-width: 1367px) {
|
||||
.secondaryNavigation {
|
||||
margin-top: 0;
|
||||
gap: 80px;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -13,10 +13,7 @@
|
||||
|
||||
@media screen and (min-width: 767px) {
|
||||
.section {
|
||||
padding: var(--Spacing-x9) var(--Spacing-x6);
|
||||
}
|
||||
.maxWidth {
|
||||
flex-direction: row;
|
||||
padding: var(--Spacing-x9) var(--Spacing-x5);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -24,4 +21,7 @@
|
||||
.section {
|
||||
padding: var(--Spacing-x9) 0;
|
||||
}
|
||||
.maxWidth {
|
||||
flex-direction: row;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -9,7 +9,9 @@ export default async function Footer() {
|
||||
const footerData = await serverClient().contentstack.base.footer({
|
||||
lang: getLang(),
|
||||
})
|
||||
if (!footerData) {
|
||||
const languages = await serverClient().contentstack.languageSwitcher.get()
|
||||
|
||||
if (!footerData || !languages) {
|
||||
return <FooterDetails />
|
||||
}
|
||||
return (
|
||||
@@ -22,6 +24,7 @@ export default async function Footer() {
|
||||
<FooterDetails
|
||||
socialMedia={footerData.socialMedia}
|
||||
tertiaryLinks={footerData.tertiaryLinks}
|
||||
languageUrls={languages.urls}
|
||||
/>
|
||||
</footer>
|
||||
)
|
||||
|
||||
@@ -25,7 +25,7 @@ export default function MobileMenu({
|
||||
const {
|
||||
isHamburgerMenuOpen,
|
||||
isMyPagesMobileMenuOpen,
|
||||
isLanguageSwitcherOpen,
|
||||
isHeaderLanguageSwitcherOpen,
|
||||
toggleHamburgerMenu,
|
||||
toggleMyPagesMobileMenu,
|
||||
toggleLanguageSwitcher,
|
||||
@@ -41,8 +41,8 @@ export default function MobileMenu({
|
||||
if (isMyPagesMobileMenuOpen) {
|
||||
toggleMyPagesMobileMenu()
|
||||
} else {
|
||||
if (isLanguageSwitcherOpen) {
|
||||
toggleLanguageSwitcher()
|
||||
if (isHeaderLanguageSwitcherOpen) {
|
||||
toggleLanguageSwitcher("header")
|
||||
}
|
||||
|
||||
toggleHamburgerMenu()
|
||||
|
||||
@@ -24,6 +24,7 @@ export default function LanguageSwitcherContent({
|
||||
const { toggleLanguageSwitcher } = useDropdownStore()
|
||||
const languageSwitcherRef = useTrapFocus()
|
||||
const urlKeys = Object.keys(urls) as Lang[]
|
||||
const position = type === "footer" ? "footer" : "header"
|
||||
|
||||
return (
|
||||
<div className={styles.languageSwitcherContent} ref={languageSwitcherRef}>
|
||||
@@ -32,7 +33,7 @@ export default function LanguageSwitcherContent({
|
||||
<button
|
||||
type="button"
|
||||
className={styles.backButton}
|
||||
onClick={toggleLanguageSwitcher}
|
||||
onClick={() => toggleLanguageSwitcher(position)}
|
||||
>
|
||||
<ChevronLeftIcon color="red" />
|
||||
<Subtitle type="one">Main Menu</Subtitle>
|
||||
|
||||
@@ -10,6 +10,7 @@ import { useHandleKeyUp } from "@/hooks/useHandleKeyUp"
|
||||
import useLang from "@/hooks/useLang"
|
||||
|
||||
import LanguageSwitcherContent from "./LanguageSwitcherContent"
|
||||
import { languageSwitcherVariants } from "./variants"
|
||||
|
||||
import styles from "./languageSwitcher.module.css"
|
||||
|
||||
@@ -21,16 +22,29 @@ export default function LanguageSwitcher({
|
||||
}: LanguageSwitcherProps) {
|
||||
const intl = useIntl()
|
||||
const currentLanguage = useLang()
|
||||
const { toggleLanguageSwitcher, isLanguageSwitcherOpen } = useDropdownStore()
|
||||
const {
|
||||
toggleLanguageSwitcher,
|
||||
isHeaderLanguageSwitcherOpen,
|
||||
isFooterLanguageSwitcherOpen,
|
||||
} = useDropdownStore()
|
||||
|
||||
const position = type === "footer" ? "footer" : "header"
|
||||
const color = type === "footer" ? "pale" : "burgundy"
|
||||
const isLanguageSwitcherOpen =
|
||||
type === "footer"
|
||||
? isFooterLanguageSwitcherOpen
|
||||
: isHeaderLanguageSwitcherOpen
|
||||
|
||||
useHandleKeyUp((event: KeyboardEvent) => {
|
||||
if (event.key === "Escape" && isLanguageSwitcherOpen) {
|
||||
toggleLanguageSwitcher()
|
||||
toggleLanguageSwitcher(position)
|
||||
}
|
||||
})
|
||||
|
||||
const classNames = languageSwitcherVariants({ color, position })
|
||||
|
||||
return (
|
||||
<div className={styles.languageSwitcher}>
|
||||
<div className={classNames}>
|
||||
<button
|
||||
type="button"
|
||||
className={styles.button}
|
||||
@@ -39,15 +53,15 @@ export default function LanguageSwitcher({
|
||||
? "Close language menu"
|
||||
: "Open language menu",
|
||||
})}
|
||||
onClick={toggleLanguageSwitcher}
|
||||
onClick={() => toggleLanguageSwitcher(position)}
|
||||
>
|
||||
<GlobeIcon width={20} height={20} color="burgundy" />
|
||||
<GlobeIcon width={20} height={20} color={color} />
|
||||
<span>{languages[currentLanguage]}</span>
|
||||
<ChevronDownIcon
|
||||
className={`${styles.chevron} ${isLanguageSwitcherOpen ? styles.isExpanded : ""}`}
|
||||
width={20}
|
||||
height={20}
|
||||
color="burgundy"
|
||||
color={color}
|
||||
/>
|
||||
</button>
|
||||
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
.button {
|
||||
background-color: transparent;
|
||||
color: var(--Base-Text-High-contrast);
|
||||
font-family: var(--typography-Caption-Regular-fontFamily);
|
||||
font-size: var(--typography-Caption-Regular-fontSize);
|
||||
border-width: 0;
|
||||
@@ -13,6 +12,14 @@
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.burgundy .button {
|
||||
color: var(--Base-Text-High-contrast);
|
||||
}
|
||||
|
||||
.pale .button {
|
||||
color: var(--Primary-Dark-On-Surface-Text);
|
||||
}
|
||||
|
||||
.chevron {
|
||||
justify-self: end;
|
||||
transition: transform 0.3s;
|
||||
@@ -45,29 +52,43 @@
|
||||
|
||||
.dropdown {
|
||||
position: absolute;
|
||||
top: 2.25rem;
|
||||
background-color: var(--Base-Surface-Primary-light-Normal);
|
||||
border-radius: var(--Corner-radius-Large);
|
||||
box-shadow: 0px 0px 14px 6px #0000001a;
|
||||
display: none;
|
||||
min-width: 12.5rem;
|
||||
z-index: 1;
|
||||
}
|
||||
.top .dropdown {
|
||||
top: 2.25rem;
|
||||
bottom: auto;
|
||||
}
|
||||
|
||||
/* Triangle above dropdown */
|
||||
.top .dropdown::before {
|
||||
top: -1.25rem;
|
||||
transform: rotate(180deg);
|
||||
}
|
||||
|
||||
/* Triangle 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;
|
||||
}
|
||||
|
||||
.bottom .dropdown {
|
||||
top: auto;
|
||||
bottom: 2.25rem;
|
||||
}
|
||||
|
||||
.bottom .dropdown::before {
|
||||
top: 100%;
|
||||
}
|
||||
|
||||
.button {
|
||||
grid-template-columns: repeat(3, max-content);
|
||||
font-size: var(--typography-Body-Bold-fontSize);
|
||||
|
||||
20
components/LanguageSwitcher/variants.ts
Normal file
20
components/LanguageSwitcher/variants.ts
Normal file
@@ -0,0 +1,20 @@
|
||||
import { cva } from "class-variance-authority"
|
||||
|
||||
import styles from "./languageSwitcher.module.css"
|
||||
|
||||
export const languageSwitcherVariants = cva(styles.languageSwitcher, {
|
||||
variants: {
|
||||
color: {
|
||||
burgundy: styles.burgundy,
|
||||
pale: styles.pale,
|
||||
},
|
||||
position: {
|
||||
header: styles.top,
|
||||
footer: styles.bottom,
|
||||
},
|
||||
defaultVariants: {
|
||||
color: "burgundy",
|
||||
position: "top",
|
||||
},
|
||||
},
|
||||
})
|
||||
@@ -6,18 +6,20 @@ interface DropdownState {
|
||||
isHamburgerMenuOpen: boolean
|
||||
isMyPagesMobileMenuOpen: boolean
|
||||
isMyPagesMenuOpen: boolean
|
||||
isLanguageSwitcherOpen: boolean
|
||||
isHeaderLanguageSwitcherOpen: boolean
|
||||
isFooterLanguageSwitcherOpen: boolean
|
||||
toggleHamburgerMenu: () => void
|
||||
toggleMyPagesMobileMenu: () => void
|
||||
toggleMyPagesMenu: () => void
|
||||
toggleLanguageSwitcher: () => void
|
||||
toggleLanguageSwitcher: (location: "header" | "footer") => void
|
||||
}
|
||||
|
||||
const useDropdownStore = create<DropdownState>((set) => ({
|
||||
isHamburgerMenuOpen: false,
|
||||
isMyPagesMobileMenuOpen: false,
|
||||
isMyPagesMenuOpen: false,
|
||||
isLanguageSwitcherOpen: false,
|
||||
isHeaderLanguageSwitcherOpen: false,
|
||||
isFooterLanguageSwitcherOpen: false,
|
||||
toggleHamburgerMenu: () =>
|
||||
set(
|
||||
({ isHamburgerMenuOpen, isMyPagesMenuOpen, isMyPagesMobileMenuOpen }) => {
|
||||
@@ -39,7 +41,8 @@ const useDropdownStore = create<DropdownState>((set) => ({
|
||||
isMyPagesMenuOpen,
|
||||
isMyPagesMobileMenuOpen,
|
||||
isHamburgerMenuOpen,
|
||||
isLanguageSwitcherOpen,
|
||||
isHeaderLanguageSwitcherOpen,
|
||||
isFooterLanguageSwitcherOpen,
|
||||
}) => {
|
||||
// Close the other dropdowns if they're open
|
||||
if (!isMyPagesMobileMenuOpen) {
|
||||
@@ -49,8 +52,11 @@ const useDropdownStore = create<DropdownState>((set) => ({
|
||||
if (isHamburgerMenuOpen) {
|
||||
set({ isHamburgerMenuOpen: false })
|
||||
}
|
||||
if (isLanguageSwitcherOpen) {
|
||||
set({ isLanguageSwitcherOpen: false })
|
||||
if (isHeaderLanguageSwitcherOpen) {
|
||||
set({ isHeaderLanguageSwitcherOpen: false })
|
||||
}
|
||||
if (isFooterLanguageSwitcherOpen) {
|
||||
set({ isFooterLanguageSwitcherOpen: false })
|
||||
}
|
||||
}
|
||||
return { isMyPagesMobileMenuOpen: !isMyPagesMobileMenuOpen }
|
||||
@@ -60,7 +66,8 @@ const useDropdownStore = create<DropdownState>((set) => ({
|
||||
set(
|
||||
({
|
||||
isHamburgerMenuOpen,
|
||||
isLanguageSwitcherOpen,
|
||||
isHeaderLanguageSwitcherOpen,
|
||||
isFooterLanguageSwitcherOpen,
|
||||
isMyPagesMenuOpen,
|
||||
isMyPagesMobileMenuOpen,
|
||||
}) => {
|
||||
@@ -72,32 +79,40 @@ const useDropdownStore = create<DropdownState>((set) => ({
|
||||
if (isMyPagesMobileMenuOpen) {
|
||||
set({ isMyPagesMobileMenuOpen: false })
|
||||
}
|
||||
if (isLanguageSwitcherOpen) {
|
||||
set({ isLanguageSwitcherOpen: false })
|
||||
if (isHeaderLanguageSwitcherOpen) {
|
||||
set({ isHeaderLanguageSwitcherOpen: false })
|
||||
}
|
||||
if (isFooterLanguageSwitcherOpen) {
|
||||
set({ isFooterLanguageSwitcherOpen: false })
|
||||
}
|
||||
}
|
||||
return { isMyPagesMenuOpen: !isMyPagesMenuOpen }
|
||||
}
|
||||
),
|
||||
toggleLanguageSwitcher: () =>
|
||||
set(
|
||||
({
|
||||
isLanguageSwitcherOpen,
|
||||
isMyPagesMenuOpen,
|
||||
isMyPagesMobileMenuOpen,
|
||||
}) => {
|
||||
// Close the other dropdowns if they're open
|
||||
if (!isLanguageSwitcherOpen) {
|
||||
if (isMyPagesMenuOpen) {
|
||||
set({ isMyPagesMenuOpen: false })
|
||||
}
|
||||
if (isMyPagesMobileMenuOpen) {
|
||||
set({ isMyPagesMobileMenuOpen: false })
|
||||
}
|
||||
toggleLanguageSwitcher: (location: "header" | "footer") =>
|
||||
set((state) => {
|
||||
const isCurrentlyOpen =
|
||||
location === "header"
|
||||
? state.isHeaderLanguageSwitcherOpen
|
||||
: state.isFooterLanguageSwitcherOpen
|
||||
|
||||
if (!isCurrentlyOpen) {
|
||||
return {
|
||||
isHeaderLanguageSwitcherOpen: location === "header",
|
||||
isFooterLanguageSwitcherOpen: location === "footer",
|
||||
isMyPagesMenuOpen: false,
|
||||
isMyPagesMobileMenuOpen: false,
|
||||
isHamburgerMenuOpen: false,
|
||||
}
|
||||
return { isLanguageSwitcherOpen: !isLanguageSwitcherOpen }
|
||||
}
|
||||
),
|
||||
|
||||
return {
|
||||
isHeaderLanguageSwitcherOpen:
|
||||
location === "header" ? false : state.isHeaderLanguageSwitcherOpen,
|
||||
isFooterLanguageSwitcherOpen:
|
||||
location === "footer" ? false : state.isFooterLanguageSwitcherOpen,
|
||||
}
|
||||
}),
|
||||
}))
|
||||
|
||||
export default useDropdownStore
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import { LanguageSwitcherData } from "@/types/requests/languageSwitcher"
|
||||
|
||||
export interface LanguageSwitcherProps {
|
||||
type: "mobileHeader" | "mobileFooter" | "desktopHeader" | "desktopFooter"
|
||||
type: "mobileHeader" | "desktopHeader" | "footer"
|
||||
urls: LanguageSwitcherData
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user