feat(SW-650): added sticky position hook and store

This commit is contained in:
Erik Tiekstra
2024-10-17 15:28:24 +02:00
parent b0fbf8a9e4
commit 20e3c9a35f
9 changed files with 240 additions and 19 deletions

View File

@@ -1,13 +1,15 @@
"use client"
import { zodResolver } from "@hookform/resolvers/zod"
import { useEffect, useState } from "react"
import { useEffect, useRef, useState } from "react"
import { FormProvider, useForm } from "react-hook-form"
import { dt } from "@/lib/dt"
import { StickyElementNameEnum } from "@/stores/sticky-position"
import Form from "@/components/Forms/BookingWidget"
import { bookingWidgetSchema } from "@/components/Forms/BookingWidget/schema"
import { CloseLargeIcon } from "@/components/Icons"
import useStickyPosition from "@/hooks/useStickyPosition"
import { debounce } from "@/utils/debounce"
import { getFormattedUrlQueryParams } from "@/utils/url"
@@ -28,6 +30,11 @@ export default function BookingWidgetClient({
searchParams,
}: BookingWidgetClientProps) {
const [isOpen, setIsOpen] = useState(false)
const bookingWidgetRef = useRef(null)
useStickyPosition({
ref: bookingWidgetRef,
name: StickyElementNameEnum.BOOKING_WIDGET,
})
const sessionStorageSearchData =
typeof window !== "undefined"
@@ -139,7 +146,11 @@ export default function BookingWidgetClient({
return (
<FormProvider {...methods}>
<section className={styles.container} data-open={isOpen}>
<section
ref={bookingWidgetRef}
className={styles.container}
data-open={isOpen}
>
<button
className={styles.close}
onClick={closeMobileSearch}

View File

@@ -0,0 +1,24 @@
"use client"
import { PropsWithChildren, useRef } from "react"
import { StickyElementNameEnum } from "@/stores/sticky-position"
import useStickyPosition from "@/hooks/useStickyPosition"
import styles from "./mapWithCard.module.css"
export default function MapWithCardWrapper({ children }: PropsWithChildren) {
const mapWithCardRef = useRef<HTMLDivElement>(null)
useStickyPosition({
ref: mapWithCardRef,
name: StickyElementNameEnum.HOTEL_STATIC_MAP,
group: "hotelPage",
})
return (
<div ref={mapWithCardRef} className={styles.mapWithCard}>
{children}
</div>
)
}

View File

@@ -0,0 +1,12 @@
.mapWithCard {
position: sticky;
top: var(--booking-widget-desktop-height);
min-height: 500px; /* Fixed min to not cover the marker with the card */
height: calc(
100vh - var(--main-menu-desktop-height) -
var(--booking-widget-desktop-height)
); /* Full height without the header + booking widget */
max-height: 935px; /* Fixed max according to figma */
overflow: hidden;
width: 100%;
}

View File

@@ -1,12 +1,15 @@
"use client"
import { useRouter } from "next/navigation"
import { useEffect } from "react"
import { useEffect, useRef } from "react"
import { useIntl } from "react-intl"
import { StickyElementNameEnum } from "@/stores/sticky-position"
import Link from "@/components/TempDesignSystem/Link"
import useHash from "@/hooks/useHash"
import useScrollSpy from "@/hooks/useScrollSpy"
import useStickyPosition from "@/hooks/useStickyPosition"
import styles from "./tabNavigation.module.css"
@@ -23,6 +26,12 @@ export default function TabNavigation({
const hash = useHash()
const intl = useIntl()
const router = useRouter()
const tabNavigationRef = useRef<HTMLDivElement>(null)
useStickyPosition({
ref: tabNavigationRef,
name: StickyElementNameEnum.HOTEL_TAB_NAVIGATION,
group: "hotelPage",
})
const tabLinks: { hash: HotelHashValues; text: string }[] = [
{
@@ -71,7 +80,7 @@ export default function TabNavigation({
}, [activeSectionId, router])
return (
<div className={styles.stickyWrapper}>
<div ref={tabNavigationRef} className={styles.stickyWrapper}>
<nav className={styles.tabsContainer}>
{tabLinks.map((link) => {
const isActive =

View File

@@ -73,19 +73,6 @@
background-color: var(--Base-Surface-Primary-light-Normal);
}
.mapWithCard {
position: sticky;
top: var(--booking-widget-desktop-height);
min-height: 500px; /* Fixed min to not cover the marker with the card */
height: calc(
100vh - var(--main-menu-desktop-height) -
var(--booking-widget-desktop-height)
); /* Full height without the header + booking widget */
max-height: 935px; /* Fixed max according to figma */
overflow: hidden;
width: 100%;
}
.pageContainer > nav {
padding-left: var(--Spacing-x5);
padding-right: var(--Spacing-x5);

View File

@@ -12,6 +12,7 @@ import { getRestaurantHeading } from "@/utils/facilityCards"
import DynamicMap from "./Map/DynamicMap"
import MapCard from "./Map/MapCard"
import MapWithCardWrapper from "./Map/MapWithCard"
import MobileMapToggle from "./Map/MobileMapToggle"
import StaticMap from "./Map/StaticMap"
import AmenitiesList from "./AmenitiesList"
@@ -107,10 +108,10 @@ export default async function HotelPage() {
{googleMapsApiKey ? (
<>
<aside className={styles.mapContainer}>
<div className={styles.mapWithCard}>
<MapWithCardWrapper>
<StaticMap coordinates={coordinates} hotelName={hotelName} />
<MapCard hotelName={hotelName} pois={topThreePois} />
</div>
</MapWithCardWrapper>
</aside>
<MobileMapToggle />
<DynamicMap