Merged in feat/SW-1762 (pull request #2050)

feat: make enter details bottom sheet pixed, and add spacing at the bottom of page

* feat: make enter details bottom sheet pixed, and add spacing at the bottom of page


Approved-by: Arvid Norlin
This commit is contained in:
Simon.Emanuelsson
2025-05-12 10:19:39 +00:00
parent 60af31762b
commit 1108105580
10 changed files with 110 additions and 72 deletions

View File

@@ -16,7 +16,7 @@
} }
.summary { .summary {
position: sticky; position: fixed;
bottom: 0; bottom: 0;
left: 0; left: 0;
right: 0; right: 0;

View File

@@ -126,16 +126,19 @@ export default async function DetailsPage({
} }
} }
// attribute data-footer-spacing used to add spacing
// beneath footer to be able to show entire footer upon
// scrolling down to the bottom of the page
return ( return (
<EnterDetailsProvider <main data-footer-spacing>
booking={booking} <EnterDetailsProvider
breakfastPackages={breakfastPackages} booking={booking}
rooms={rooms} breakfastPackages={breakfastPackages}
searchParamsStr={selectRoomParams.toString()} rooms={rooms}
user={user} searchParamsStr={selectRoomParams.toString()}
vat={hotel.vat} user={user}
> vat={hotel.vat}
<main> >
<HotelHeader hotelData={hotelData} /> <HotelHeader hotelData={hotelData} />
<div className={styles.container}> <div className={styles.container}>
<div className={styles.content}> <div className={styles.content}>
@@ -163,14 +166,14 @@ export default async function DetailsPage({
<DesktopSummary isMember={!!user} /> <DesktopSummary isMember={!!user} />
</aside> </aside>
</div> </div>
</main> <EnterDetailsTrackingWrapper
<EnterDetailsTrackingWrapper booking={booking}
booking={booking} hotel={hotel}
hotel={hotel} isMember={!!user}
isMember={!!user} lang={lang}
lang={lang} rooms={rooms}
rooms={rooms} />
/> </EnterDetailsProvider>
</EnterDetailsProvider> </main>
) )
} }

View File

@@ -12,6 +12,9 @@ import styles from "./mainnav.module.css"
import type { FooterMainNavProps } from "@/types/components/footer/navigation" import type { FooterMainNavProps } from "@/types/components/footer/navigation"
export default function FooterMainNav({ mainLinks }: FooterMainNavProps) { export default function FooterMainNav({ mainLinks }: FooterMainNavProps) {
if (!mainLinks.length) {
return null
}
return ( return (
<nav className={styles.mainNavigation}> <nav className={styles.mainNavigation}>
<ul className={styles.mainNavigationList}> <ul className={styles.mainNavigationList}>

View File

@@ -29,32 +29,34 @@ export default function FooterSecondaryNav({
> >
{appDownloads.title} {appDownloads.title}
</Caption> </Caption>
<ul className={styles.secondaryNavigationList}> {appDownloads.links.length ? (
{appDownloads.links.map( <ul className={styles.secondaryNavigationList}>
({ href, type }) => {appDownloads.links.map(
href && ( ({ href, type }) =>
<li key={type} className={styles.appDownloadItem}> href && (
<a <li key={type} className={styles.appDownloadItem}>
href={href.href} <a
target="_blank" href={href.href}
aria-label={href.title} target="_blank"
onClick={() => trackSocialMediaClick(href.title)} aria-label={href.title}
> onClick={() => trackSocialMediaClick(href.title)}
<Image >
src={ <Image
AppDownLoadLinks[ src={
`${type}_${lang}` as keyof typeof AppDownLoadLinks AppDownLoadLinks[
] `${type}_${lang}` as keyof typeof AppDownLoadLinks
} ]
alt="" }
width={125} alt=""
height={40} width={125}
/> height={40}
</a> />
</li> </a>
) </li>
)} )
</ul> )}
</ul>
) : null}
</nav> </nav>
)} )}
{secondaryLinks.map((group) => ( {secondaryLinks.map((group) => (
@@ -66,20 +68,22 @@ export default function FooterSecondaryNav({
> >
{group.title} {group.title}
</Caption> </Caption>
<ul className={styles.secondaryNavigationList}> {group?.links.length ? (
{group?.links?.map((link) => ( <ul className={styles.secondaryNavigationList}>
<li key={link.title} className={styles.secondaryNavigationItem}> {group.links.map((link) => (
<Link <li key={link.title} className={styles.secondaryNavigationItem}>
href={link.url} <Link
target={link.openInNewTab ? "_blank" : undefined} href={link.url}
color="burgundy" target={link.openInNewTab ? "_blank" : undefined}
onClick={() => trackFooterClick(group.title, link.title)} color="burgundy"
> onClick={() => trackFooterClick(group.title, link.title)}
{link.title} >
</Link> {link.title}
</li> </Link>
))} </li>
</ul> ))}
</ul>
) : null}
</nav> </nav>
))} ))}
</div> </div>

View File

@@ -2,7 +2,6 @@
display: flex; display: flex;
flex-direction: column-reverse; flex-direction: column-reverse;
gap: var(--Spacing-x6); gap: var(--Spacing-x6);
margin-top: var(--Spacing-x6);
} }
.secondaryNavigationList { .secondaryNavigationList {
@@ -35,14 +34,15 @@
@media screen and (min-width: 768px) { @media screen and (min-width: 768px) {
.secondaryNavigation { .secondaryNavigation {
margin-top: var(--Spacing-x4);
gap: 120px; gap: 120px;
flex-direction: row; flex-direction: row;
} }
} }
@media screen and (min-width: 1367px) { @media screen and (min-width: 1367px) {
.secondaryNavigation { .secondaryNavigation {
margin-top: 0;
gap: 80px; gap: 80px;
grid-column: 2;
justify-self: flex-end;
} }
} }

View File

@@ -4,10 +4,9 @@
} }
.maxWidth { .maxWidth {
display: grid;
gap: var(--Spacing-x6);
margin: 0 auto; margin: 0 auto;
display: flex;
justify-content: space-between;
flex-direction: column;
max-width: var(--max-width-page); max-width: var(--max-width-page);
} }
@@ -15,13 +14,15 @@
.section { .section {
padding: var(--Spacing-x9) 0; padding: var(--Spacing-x9) 0;
} }
.maxWidth {
gap: var(--Spacing-x4);
}
} }
@media screen and (min-width: 1367px) { @media screen and (min-width: 1367px) {
.section {
padding: var(--Spacing-x9) 0;
}
.maxWidth { .maxWidth {
flex-direction: row; gap: var(--Spacing-x2);
grid-template-columns: 1fr 1fr;
} }
} }

View File

@@ -1,3 +1,18 @@
.footer { .footer {
--bottom-sheet-height: 7.5em;
--promo-height: 50px;
margin-top: auto; margin-top: auto;
} }
@media screen and (max-width: 1366px) {
:has([data-footer-spacing]) ~ .footer {
background: var(--Base-Text-High-contrast);
padding-bottom: var(--bottom-sheet-height);
}
:has([data-footer-spacing-signup]) ~ .footer {
background: var(--Base-Text-High-contrast);
padding-bottom: calc(var(--bottom-sheet-height) + var(--promo-height));
}
}

View File

@@ -191,8 +191,16 @@ export default function RateSummary() {
mainRoomCurrency = rateProduct.public.localPrice.currency mainRoomCurrency = rateProduct.public.localPrice.currency
} }
// attribute data-footer-spacing used to add spacing
// beneath footer to be able to show entire footer upon
// scrolling down to the bottom of the page
return ( return (
<form action={`details?${params}`} method="GET" onSubmit={handleSubmit}> <form
data-footer-spacing
action={`details?${params}`}
method="GET"
onSubmit={handleSubmit}
>
<div className={styles.summary}> <div className={styles.summary}>
<div className={styles.content}> <div className={styles.content}>
<div className={styles.summaryText}> <div className={styles.summaryText}>

View File

@@ -9,7 +9,10 @@ import styles from "./signupPromo.module.css"
export default function SignupPromoMobile() { export default function SignupPromoMobile() {
const intl = useIntl() const intl = useIntl()
return ( return (
<div className={styles.memberDiscountBannerMobile}> <div
data-footer-spacing-signup
className={styles.memberDiscountBannerMobile}
>
<Footnote color="burgundy"> <Footnote color="burgundy">
{intl.formatMessage({ {intl.formatMessage({
defaultMessage: "Join or log in while booking for member pricing.", defaultMessage: "Join or log in while booking for member pricing.",

View File

@@ -6,6 +6,7 @@
align-items: center; align-items: center;
justify-content: center; justify-content: center;
} }
.memberDiscountBannerDesktop { .memberDiscountBannerDesktop {
display: none; display: none;
background: var(--Primary-Light-Surface-Normal); background: var(--Primary-Light-Surface-Normal);
@@ -32,7 +33,7 @@
overflow: hidden; overflow: hidden;
} }
@media (min-width: 768px) { @media (min-width: 1367px) {
.memberDiscountBannerMobile { .memberDiscountBannerMobile {
display: none; display: none;
} }