diff --git a/components/HotelReservation/HotelCard/index.tsx b/components/HotelReservation/HotelCard/index.tsx index 808e9ac9f..1836d4130 100644 --- a/components/HotelReservation/HotelCard/index.tsx +++ b/components/HotelReservation/HotelCard/index.tsx @@ -7,7 +7,6 @@ import { selectHotelMap, selectRate } from "@/constants/routes/hotelReservation" import { mapFacilityToIcon } from "@/components/ContentType/HotelPage/data" import ImageGallery from "@/components/ImageGallery" -import Alert from "@/components/TempDesignSystem/Alert" import Button from "@/components/TempDesignSystem/Button" import Divider from "@/components/TempDesignSystem/Divider" import Link from "@/components/TempDesignSystem/Link" @@ -133,13 +132,6 @@ export default function HotelCard({ hotel={hotelData} showCTA={true} /> - {hotelData.specialAlerts.length > 0 && ( -
- {hotelData.specialAlerts.map((alert) => ( - - ))} -
- )} diff --git a/components/HotelReservation/HotelCardListing/index.tsx b/components/HotelReservation/HotelCardListing/index.tsx index ab2d45d3e..191c7acde 100644 --- a/components/HotelReservation/HotelCardListing/index.tsx +++ b/components/HotelReservation/HotelCardListing/index.tsx @@ -1,9 +1,12 @@ "use client" import { useSearchParams } from "next/navigation" -import { useMemo } from "react" +import { useEffect, useMemo, useState } from "react" +import { useIntl } from "react-intl" import { useHotelFilterStore } from "@/stores/hotel-filters" +import { BackToTopButton } from "@/components/TempDesignSystem/BackToTopButton" + import HotelCard from "../HotelCard" import { DEFAULT_SORT } from "../SelectHotel/HotelSorter" @@ -22,9 +25,11 @@ export default function HotelCardListing({ activeCard, onHotelCardHover, }: HotelCardListingProps) { + const intl = useIntl() const searchParams = useSearchParams() const activeFilters = useHotelFilterStore((state) => state.activeFilters) const setResultCount = useHotelFilterStore((state) => state.setResultCount) + const [showBackToTop, setShowBackToTop] = useState(false) const sortBy = useMemo( () => searchParams.get("sort") ?? DEFAULT_SORT, @@ -82,6 +87,20 @@ export default function HotelCardListing({ return filteredHotels }, [activeFilters, sortedHotels, setResultCount]) + useEffect(() => { + const handleScroll = () => { + const hasScrolledPast = window.scrollY > 490 + setShowBackToTop(hasScrolledPast) + } + + window.addEventListener("scroll", handleScroll, { passive: true }) + return () => window.removeEventListener("scroll", handleScroll) + }, []) + + function scrollToTop() { + window.scrollTo({ top: 0, behavior: "smooth" }) + } + return (
{hotels?.length @@ -95,6 +114,7 @@ export default function HotelCardListing({ /> )) : null} + {showBackToTop && }
) } diff --git a/components/HotelReservation/SelectHotel/SelectHotelMap/index.tsx b/components/HotelReservation/SelectHotel/SelectHotelMap/index.tsx index 215c7ae66..ce3d2173d 100644 --- a/components/HotelReservation/SelectHotel/SelectHotelMap/index.tsx +++ b/components/HotelReservation/SelectHotel/SelectHotelMap/index.tsx @@ -7,8 +7,9 @@ import { useMediaQuery } from "usehooks-ts" import { selectHotel } from "@/constants/routes/hotelReservation" -import { CloseIcon, CloseLargeIcon } from "@/components/Icons" +import { ArrowUpIcon, CloseIcon, CloseLargeIcon } from "@/components/Icons" import InteractiveMap from "@/components/Maps/InteractiveMap" +import { BackToTopButton } from "@/components/TempDesignSystem/BackToTopButton" import Button from "@/components/TempDesignSystem/Button" import useLang from "@/hooks/useLang" @@ -109,17 +110,7 @@ export default function SelectHotelMap({ activeHotelPin={activeHotelPin} setActiveHotelPin={setActiveHotelPin} /> - {showBackToTop && ( - - )} + {showBackToTop && } + + + + + + ) +} diff --git a/components/Icons/index.tsx b/components/Icons/index.tsx index 1bc195717..7ec502ca0 100644 --- a/components/Icons/index.tsx +++ b/components/Icons/index.tsx @@ -6,6 +6,7 @@ export { default as AirIcon } from "./Air" export { default as AirplaneIcon } from "./Airplane" export { default as AllergyIcon } from "./Allergy" export { default as ArrowRightIcon } from "./ArrowRight" +export { default as ArrowUpIcon } from "./ArrowUp" export { default as BarIcon } from "./Bar" export { default as BathtubIcon } from "./Bathtub" export { default as BedDoubleIcon } from "./BedDouble" diff --git a/components/TempDesignSystem/BackToTopButton/backToTopButton.module.css b/components/TempDesignSystem/BackToTopButton/backToTopButton.module.css new file mode 100644 index 000000000..4ce70972b --- /dev/null +++ b/components/TempDesignSystem/BackToTopButton/backToTopButton.module.css @@ -0,0 +1,45 @@ +.backToTopButton { + border-radius: var(--Corner-radius-Rounded); + cursor: pointer; + display: flex; + align-items: flex-end; + position: fixed; + bottom: 20px; + right: 20px; + z-index: 1000; + background-color: var(--Base-Surface-Primary-light-Normal); + color: var(--Base-Button-Secondary-On-Fill-Normal); + border: 2px solid var(--Base-Button-Secondary-On-Fill-Normal); + gap: var(--Spacing-x-half); + padding: var(--Spacing-x1); + text-align: center; + transition: + background-color 300ms ease, + color 300ms ease; + font-family: var(--typography-Body-Bold-fontFamily); + font-weight: 500; + font-size: var(--typography-Caption-Bold-fontSize); + line-height: var(--typography-Caption-Bold-lineHeight); + letter-spacing: 0.6%; + text-decoration: none; +} + +.backToTopButtonText { + display: none; +} + +@media (min-width: 768px) { + .backToTopButtonText { + display: initial; + } + .backToTopButton:hover { + background-color: var(--Base-Button-Tertiary-Fill-Normal); + color: var(--Base-Button-Tertiary-On-Fill-Hover); + } + .backToTopButton:hover > svg * { + fill: var(--Base-Button-Tertiary-On-Fill-Hover); + } + .backToTopButton { + padding: calc(var(--Spacing-x1) + 2px) var(--Spacing-x2); + } +} diff --git a/components/TempDesignSystem/BackToTopButton/index.tsx b/components/TempDesignSystem/BackToTopButton/index.tsx new file mode 100644 index 000000000..a50f8329f --- /dev/null +++ b/components/TempDesignSystem/BackToTopButton/index.tsx @@ -0,0 +1,20 @@ +"use client" + +import { Button as ButtonRAC } from "react-aria-components" +import { useIntl } from "react-intl" + +import { ArrowUpIcon } from "@/components/Icons" + +import styles from "./backToTopButton.module.css" + +export function BackToTopButton({ onClick }: { onClick: () => void }) { + const intl = useIntl() + return ( + + + + {intl.formatMessage({ id: "Back to top" })} + + + ) +}