Skeleton loader for footer
This commit is contained in:
@@ -1,11 +1,17 @@
|
|||||||
import { env } from "@/env/server"
|
import { env } from "@/env/server"
|
||||||
|
|
||||||
import CurrentLoadingSpinner from "@/components/Current/LoadingSpinner"
|
import CurrentLoadingSpinner from "@/components/Current/LoadingSpinner"
|
||||||
import LoadingSpinner from "@/components/LoadingSpinner"
|
import { FooterDetailsSkeleton } from "@/components/Footer/Details"
|
||||||
|
import { FooterNavigationSkeleton } from "@/components/Footer/Navigation"
|
||||||
|
|
||||||
export default function LoadingFooter() {
|
export default function LoadingFooter() {
|
||||||
if (env.HIDE_FOR_NEXT_RELEASE) {
|
if (env.HIDE_FOR_NEXT_RELEASE) {
|
||||||
return <CurrentLoadingSpinner />
|
return <CurrentLoadingSpinner />
|
||||||
}
|
}
|
||||||
return <LoadingSpinner />
|
return (
|
||||||
|
<footer>
|
||||||
|
<FooterNavigationSkeleton />
|
||||||
|
<FooterDetailsSkeleton />
|
||||||
|
</footer>
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -3,6 +3,7 @@ import { getFooter, getLanguageSwitcher } from "@/lib/trpc/memoizedRequests"
|
|||||||
import { getIconByIconName } from "@/components/Icons/get-icon-by-icon-name"
|
import { getIconByIconName } from "@/components/Icons/get-icon-by-icon-name"
|
||||||
import Image from "@/components/Image"
|
import Image from "@/components/Image"
|
||||||
import LanguageSwitcher from "@/components/LanguageSwitcher"
|
import LanguageSwitcher from "@/components/LanguageSwitcher"
|
||||||
|
import SkeletonShimmer from "@/components/SkeletonShimmer"
|
||||||
import Link from "@/components/TempDesignSystem/Link"
|
import Link from "@/components/TempDesignSystem/Link"
|
||||||
import Footnote from "@/components/TempDesignSystem/Text/Footnote"
|
import Footnote from "@/components/TempDesignSystem/Text/Footnote"
|
||||||
import { getIntl } from "@/i18n"
|
import { getIntl } from "@/i18n"
|
||||||
@@ -92,3 +93,40 @@ export default async function FooterDetails() {
|
|||||||
</section>
|
</section>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export async function FooterDetailsSkeleton() {
|
||||||
|
const lang = 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>
|
||||||
|
<nav className={styles.socialNav}>
|
||||||
|
<SkeletonShimmer width="10ch" height="20px" contrast="dark" />
|
||||||
|
</nav>
|
||||||
|
</div>
|
||||||
|
<div className={styles.bottomContainer}>
|
||||||
|
<div className={styles.copyrightContainer}>
|
||||||
|
<Footnote type="label" textTransform="uppercase">
|
||||||
|
© {currentYear}{" "}
|
||||||
|
{intl.formatMessage({ id: "Copyright all rights reserved" })}
|
||||||
|
</Footnote>
|
||||||
|
</div>
|
||||||
|
<div className={styles.navigationContainer}>
|
||||||
|
<nav className={styles.navigation}>
|
||||||
|
<SkeletonShimmer width="40ch" height="20px" contrast="dark" />
|
||||||
|
</nav>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</section>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|||||||
@@ -1,4 +1,5 @@
|
|||||||
import { ArrowRightIcon } from "@/components/Icons"
|
import { ArrowRightIcon } from "@/components/Icons"
|
||||||
|
import SkeletonShimmer from "@/components/SkeletonShimmer"
|
||||||
import Link from "@/components/TempDesignSystem/Link"
|
import Link from "@/components/TempDesignSystem/Link"
|
||||||
import Subtitle from "@/components/TempDesignSystem/Text/Subtitle"
|
import Subtitle from "@/components/TempDesignSystem/Text/Subtitle"
|
||||||
|
|
||||||
@@ -30,3 +31,24 @@ export default function FooterMainNav({ mainLinks }: FooterMainNavProps) {
|
|||||||
</nav>
|
</nav>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export function FooterMainNavSkeleton() {
|
||||||
|
const items = Array.from({ length: 4 }).map((_, i) => i)
|
||||||
|
|
||||||
|
return (
|
||||||
|
<nav className={styles.mainNavigation}>
|
||||||
|
<ul className={styles.mainNavigationList}>
|
||||||
|
{items.map((x) => (
|
||||||
|
<li key={x} className={styles.mainNavigationItem}>
|
||||||
|
<Subtitle color="baseTextMediumContrast" type="two" asChild>
|
||||||
|
<span className={styles.mainNavigationLink}>
|
||||||
|
<SkeletonShimmer width="80%" />
|
||||||
|
<ArrowRightIcon color="peach80" />
|
||||||
|
</span>
|
||||||
|
</Subtitle>
|
||||||
|
</li>
|
||||||
|
))}
|
||||||
|
</ul>
|
||||||
|
</nav>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
import Image from "@/components/Image"
|
import Image from "@/components/Image"
|
||||||
|
import SkeletonShimmer from "@/components/SkeletonShimmer"
|
||||||
import Link from "@/components/TempDesignSystem/Link"
|
import Link from "@/components/TempDesignSystem/Link"
|
||||||
import Body from "@/components/TempDesignSystem/Text/Body"
|
|
||||||
import Caption from "@/components/TempDesignSystem/Text/Caption"
|
import Caption from "@/components/TempDesignSystem/Text/Caption"
|
||||||
import { getLang } from "@/i18n/serverContext"
|
import { getLang } from "@/i18n/serverContext"
|
||||||
|
|
||||||
@@ -80,3 +80,46 @@ export default function FooterSecondaryNav({
|
|||||||
</div>
|
</div>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export function FooterSecondaryNavSkeleton() {
|
||||||
|
return (
|
||||||
|
<div className={styles.secondaryNavigation}>
|
||||||
|
<nav className={styles.secondaryNavigationGroup}>
|
||||||
|
<SkeletonShimmer width="10ch" />
|
||||||
|
<ul className={styles.secondaryNavigationList}>
|
||||||
|
<li className={styles.appDownloadItem}>
|
||||||
|
<SkeletonShimmer width="16ch" />
|
||||||
|
</li>
|
||||||
|
<li className={styles.appDownloadItem}>
|
||||||
|
<SkeletonShimmer width="16ch" />
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
|
</nav>
|
||||||
|
<nav className={styles.secondaryNavigationGroup}>
|
||||||
|
<SkeletonShimmer width="20ch" />
|
||||||
|
<ul className={styles.secondaryNavigationList}>
|
||||||
|
<li className={styles.secondaryNavigationItem}>
|
||||||
|
<SkeletonShimmer width="25ch" />
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
|
</nav>
|
||||||
|
<nav className={styles.secondaryNavigationGroup}>
|
||||||
|
<SkeletonShimmer width="15ch" />
|
||||||
|
<ul className={styles.secondaryNavigationList}>
|
||||||
|
<li className={styles.secondaryNavigationItem}>
|
||||||
|
<SkeletonShimmer width="30ch" />
|
||||||
|
</li>
|
||||||
|
<li className={styles.secondaryNavigationItem}>
|
||||||
|
<SkeletonShimmer width="36ch" />
|
||||||
|
</li>
|
||||||
|
<li className={styles.secondaryNavigationItem}>
|
||||||
|
<SkeletonShimmer width="12ch" />
|
||||||
|
</li>
|
||||||
|
<li className={styles.secondaryNavigationItem}>
|
||||||
|
<SkeletonShimmer width="20ch" />
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
|
</nav>
|
||||||
|
</div>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
import { getFooter } from "@/lib/trpc/memoizedRequests"
|
import { getFooter } from "@/lib/trpc/memoizedRequests"
|
||||||
|
|
||||||
import FooterMainNav from "./MainNav"
|
import FooterMainNav, { FooterMainNavSkeleton } from "./MainNav"
|
||||||
import FooterSecondaryNav from "./SecondaryNav"
|
import FooterSecondaryNav, { FooterSecondaryNavSkeleton } from "./SecondaryNav"
|
||||||
|
|
||||||
import styles from "./navigation.module.css"
|
import styles from "./navigation.module.css"
|
||||||
|
|
||||||
@@ -10,6 +10,7 @@ export default async function FooterNavigation() {
|
|||||||
if (!footer) {
|
if (!footer) {
|
||||||
return null
|
return null
|
||||||
}
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<section className={styles.section}>
|
<section className={styles.section}>
|
||||||
<div className={styles.maxWidth}>
|
<div className={styles.maxWidth}>
|
||||||
@@ -22,3 +23,14 @@ export default async function FooterNavigation() {
|
|||||||
</section>
|
</section>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export function FooterNavigationSkeleton() {
|
||||||
|
return (
|
||||||
|
<section className={styles.section}>
|
||||||
|
<div className={styles.maxWidth}>
|
||||||
|
<FooterMainNavSkeleton />
|
||||||
|
<FooterSecondaryNavSkeleton />
|
||||||
|
</div>
|
||||||
|
</section>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|||||||
@@ -3,13 +3,15 @@ import styles from "./skeleton.module.css"
|
|||||||
export default function SkeletonShimmer({
|
export default function SkeletonShimmer({
|
||||||
height,
|
height,
|
||||||
width,
|
width,
|
||||||
|
contrast = "light",
|
||||||
}: {
|
}: {
|
||||||
height?: string
|
height?: string
|
||||||
width?: string
|
width?: string
|
||||||
|
contrast?: "light" | "dark"
|
||||||
}) {
|
}) {
|
||||||
return (
|
return (
|
||||||
<div
|
<div
|
||||||
className={styles.shimmer}
|
className={`${styles.shimmer} ${styles[contrast]}`}
|
||||||
style={{
|
style={{
|
||||||
height: height,
|
height: height,
|
||||||
width: width,
|
width: width,
|
||||||
|
|||||||
@@ -1,9 +1,29 @@
|
|||||||
|
.shimmer.dark {
|
||||||
|
--shimmer-background: rgba(255, 255, 255, 0.1);
|
||||||
|
--shimmer: linear-gradient(
|
||||||
|
120deg,
|
||||||
|
rgba(255, 255, 255, 0) 0,
|
||||||
|
rgba(255, 255, 255, 0.1) 40%,
|
||||||
|
rgba(255, 255, 255, 0.1) 60%,
|
||||||
|
rgba(255, 255, 255, 0) 100%
|
||||||
|
);
|
||||||
|
}
|
||||||
.shimmer {
|
.shimmer {
|
||||||
background-color: hsla(0, 0%, 85%, 0.5);
|
--shimmer-background: rgba(217, 217, 217, 0.5);
|
||||||
|
--shimmer: linear-gradient(
|
||||||
|
90deg,
|
||||||
|
rgba(255, 255, 255, 0) 0,
|
||||||
|
rgba(255, 255, 255, 0.2) 20%,
|
||||||
|
rgba(255, 255, 255, 0.5) 60%,
|
||||||
|
rgba(255, 255, 255, 0) 100%
|
||||||
|
);
|
||||||
|
|
||||||
|
background-color: var(--shimmer-background);
|
||||||
position: relative;
|
position: relative;
|
||||||
overflow: hidden;
|
overflow: hidden;
|
||||||
border-radius: 4px;
|
border-radius: 4px;
|
||||||
min-height: 1em;
|
min-height: 1em;
|
||||||
|
min-width: 2ch;
|
||||||
}
|
}
|
||||||
.shimmer::after {
|
.shimmer::after {
|
||||||
position: absolute;
|
position: absolute;
|
||||||
@@ -12,13 +32,7 @@
|
|||||||
bottom: 0;
|
bottom: 0;
|
||||||
left: 0;
|
left: 0;
|
||||||
transform: translateX(-100%);
|
transform: translateX(-100%);
|
||||||
background-image: linear-gradient(
|
background-image: var(--shimmer);
|
||||||
90deg,
|
|
||||||
rgba(255, 255, 255, 0) 0,
|
|
||||||
rgba(255, 255, 255, 0.2) 20%,
|
|
||||||
rgba(255, 255, 255, 0.5) 60%,
|
|
||||||
rgba(255, 255, 255, 0) 100%
|
|
||||||
);
|
|
||||||
animation: shimmer 3s infinite;
|
animation: shimmer 3s infinite;
|
||||||
content: "";
|
content: "";
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user