Feat/BOOK-117 svg accessibility

* feat(BOOK-117): Added aria-label to Scandic Friends levels
* feat(BOOK-117): Added aria-label to hotel logos
* feat(BOOK-117): Added alt text to app download images
* feat(BOOK-117): Added same logo component to footer as the one in the header
* feat(BOOK-117): Added aria attributes to icons similar to how we handled MaterialIcon aria attributes

Approved-by: Bianca Widstam
Approved-by: Matilda Landström
This commit is contained in:
Erik Tiekstra
2025-11-13 06:34:18 +00:00
parent c4b564998c
commit ce469bc4b4
117 changed files with 541 additions and 247 deletions

View File

@@ -1,4 +1,3 @@
import Image from "@scandic-hotels/design-system/Image"
import Link from "@scandic-hotels/design-system/OldDSLink"
import SkeletonShimmer from "@scandic-hotels/design-system/SkeletonShimmer"
import { Typography } from "@scandic-hotels/design-system/Typography"
@@ -7,30 +6,21 @@ import { getFooter } from "@/lib/trpc/memoizedRequests"
import LanguageSwitcher from "@/components/LanguageSwitcher"
import { getIntl } from "@/i18n"
import { getLang } from "@/i18n/serverContext"
import { LogoLink } from "../../LogoLink"
import SocialLink from "./SocialLink"
import styles from "./details.module.css"
export default async function FooterDetails() {
const lang = await getLang()
const intl = await getIntl()
// preloaded
const footer = await getFooter()
const currentYear = new Date().getFullYear()
return (
<div className={styles.details}>
<div className={styles.topContainer}>
<Link href={`/${lang}`}>
<Image
alt="Scandic Hotels logo"
height={22}
src="/_static/img/scandic-logotype-white.svg"
width={103}
/>
</Link>
<LogoLink isInverted />
<nav className={styles.socialNav}>
{footer?.socialMedia.links.map(
({ href }) => href && <SocialLink link={href} key={href.title} />
@@ -73,21 +63,13 @@ export default async function FooterDetails() {
}
export async function FooterDetailsSkeleton() {
const lang = await getLang()
const intl = await getIntl()
const currentYear = new Date().getFullYear()
return (
<section className={styles.details}>
<div className={styles.topContainer}>
<Link href={`/${lang}`}>
<Image
alt="Scandic Hotels logo"
height={22}
src="/_static/img/scandic-logotype-white.svg"
width={103}
/>
</Link>
<LogoLink isInverted />
<nav className={styles.socialNav}>
<SkeletonShimmer width="10ch" height="20px" contrast="dark" />
</nav>

View File

@@ -1,5 +1,7 @@
"use client"
import { useIntl } from "react-intl"
import Image from "@scandic-hotels/design-system/Image"
import Link from "@scandic-hotels/design-system/OldDSLink"
import SkeletonShimmer from "@scandic-hotels/design-system/SkeletonShimmer"
@@ -8,9 +10,10 @@ import { Typography } from "@scandic-hotels/design-system/Typography"
import useLang from "@/hooks/useLang"
import { trackFooterClick, trackSocialMediaClick } from "@/utils/tracking"
import { getAppDownloadAttributes } from "./utils"
import styles from "./secondarynav.module.css"
import { AppDownLoadLinks } from "@/types/components/footer/appDownloadIcons"
import { type FooterSecondaryNavProps } from "@/types/components/footer/navigation"
export default function FooterSecondaryNav({
@@ -18,6 +21,7 @@ export default function FooterSecondaryNav({
appDownloads,
}: FooterSecondaryNavProps) {
const lang = useLang()
const intl = useIntl()
return (
<div className={styles.secondaryNavigation}>
@@ -27,30 +31,28 @@ export default function FooterSecondaryNav({
</Typography>
{appDownloads.links.length ? (
<ul className={styles.secondaryNavigationList}>
{appDownloads.links.map(
({ href, type }) =>
href && (
<li key={type}>
<a
href={href.href}
target="_blank"
aria-label={href.title}
onClick={() => trackSocialMediaClick(href.title)}
>
<Image
src={
AppDownLoadLinks[
`${type}_${lang}` as keyof typeof AppDownLoadLinks
]
}
alt={href.title}
width={125}
height={40}
/>
</a>
</li>
)
)}
{appDownloads.links.map(({ href, type }) => {
const attributes = getAppDownloadAttributes(
intl,
`${type}_${lang}`
)
return href && attributes ? (
<li key={type}>
<a
href={href.href}
target="_blank"
onClick={() => trackSocialMediaClick(href.title)}
>
<Image
src={attributes.src}
alt={attributes.alt}
width={125}
height={40}
/>
</a>
</li>
) : null
})}
</ul>
) : null}
</nav>

View File

@@ -0,0 +1,77 @@
import type { IntlShape } from "react-intl"
export function getAppDownloadAttributes(intl: IntlShape, key: string) {
const appleAlt = intl.formatMessage({
id: "footer.appDownloadAlt.apple",
defaultMessage: "Download on the App Store",
})
const googleAlt = intl.formatMessage({
id: "footer.appDownloadAlt.google",
defaultMessage: "Get it on Google Play",
})
switch (key) {
case "Apple_da":
return {
src: "/_static/img/store-badges/app-store-badge-da.svg",
alt: appleAlt,
}
case "Apple_de":
return {
src: "/_static/img/store-badges/app-store-badge-de.svg",
alt: appleAlt,
}
case "Apple_en":
return {
src: "/_static/img/store-badges/app-store-badge-en.svg",
alt: appleAlt,
}
case "Apple_fi":
return {
src: "/_static/img/store-badges/app-store-badge-fi.svg",
alt: appleAlt,
}
case "Apple_no":
return {
src: "/_static/img/store-badges/app-store-badge-no.svg",
alt: appleAlt,
}
case "Apple_sv":
return {
src: "/_static/img/store-badges/app-store-badge-sv.svg",
alt: appleAlt,
}
case "Google_da":
return {
src: "/_static/img/store-badges/google-play-badge-da.svg",
alt: googleAlt,
}
case "Google_de":
return {
src: "/_static/img/store-badges/google-play-badge-de.svg",
alt: googleAlt,
}
case "Google_en":
return {
src: "/_static/img/store-badges/google-play-badge-en.svg",
alt: googleAlt,
}
case "Google_fi":
return {
src: "/_static/img/store-badges/google-play-badge-fi.svg",
alt: googleAlt,
}
case "Google_no":
return {
src: "/_static/img/store-badges/google-play-badge-no.svg",
alt: googleAlt,
}
case "Google_sv":
return {
src: "/_static/img/store-badges/google-play-badge-sv.svg",
alt: googleAlt,
}
default:
return null
}
}