diff --git a/apps/scandic-web/components/ContentType/StaticPages/staticPage.module.css b/apps/scandic-web/components/ContentType/StaticPages/staticPage.module.css index 6939328d7..8247dffc0 100644 --- a/apps/scandic-web/components/ContentType/StaticPages/staticPage.module.css +++ b/apps/scandic-web/components/ContentType/StaticPages/staticPage.module.css @@ -59,8 +59,6 @@ .meetingPackageWidget { border-radius: var(--Corner-radius-lg); - background-color: var(--Base-Surface-Primary-light-Normal); - box-shadow: 0px 4px 24px 0px rgba(0, 0, 0, 0.05); overflow: hidden; } @@ -84,6 +82,14 @@ } } +/* Meeting booking widget changes design at 948px */ +@media screen and (min-width: 948px) { + .meetingPackageWidget { + background-color: var(--Base-Surface-Primary-light-Normal); + box-shadow: 0px 4px 24px 0px rgba(0, 0, 0, 0.05); + } +} + @media (min-width: 1367px) { .content .contentContainer { grid-template-areas: "main sidebar"; diff --git a/apps/scandic-web/components/MeetingPackageWidget/Content/Content.tsx b/apps/scandic-web/components/MeetingPackageWidget/Content/Content.tsx new file mode 100644 index 000000000..19c94f939 --- /dev/null +++ b/apps/scandic-web/components/MeetingPackageWidget/Content/Content.tsx @@ -0,0 +1,25 @@ +import { cx } from "class-variance-authority" + +import MeetingPackageWidgetSkeleton from "../Skeleton" +import { useMeetingPackageWidget } from "../useMeetingPackageWidget" + +import styles from "./content.module.css" + +import type { MeetingPackageWidgetProps } from ".." + +export default function MeetingPackageWidgetContent({ + destination, + className, +}: MeetingPackageWidgetProps) { + const { isLoading } = useMeetingPackageWidget(destination) + + return ( +
+ {isLoading && } +
+
+ ) +} diff --git a/apps/scandic-web/components/MeetingPackageWidget/Content/content.module.css b/apps/scandic-web/components/MeetingPackageWidget/Content/content.module.css new file mode 100644 index 000000000..4487dde16 --- /dev/null +++ b/apps/scandic-web/components/MeetingPackageWidget/Content/content.module.css @@ -0,0 +1,8 @@ +.widget { + width: min(var(--max-width-page), 100%); + margin: 0 auto; +} + +.widget.isLoading { + display: none; +} diff --git a/apps/scandic-web/components/MeetingPackageWidget/Skeleton/index.tsx b/apps/scandic-web/components/MeetingPackageWidget/Skeleton/index.tsx index ceb07dbfd..ceef28078 100644 --- a/apps/scandic-web/components/MeetingPackageWidget/Skeleton/index.tsx +++ b/apps/scandic-web/components/MeetingPackageWidget/Skeleton/index.tsx @@ -1,4 +1,4 @@ -import SkeletonShimmer from "../../SkeletonShimmer" +import SkeletonShimmer from "@/components/SkeletonShimmer" import styles from "./skeleton.module.css" diff --git a/apps/scandic-web/components/MeetingPackageWidget/index.tsx b/apps/scandic-web/components/MeetingPackageWidget/index.tsx index 993f70e80..fc4dc7d0d 100644 --- a/apps/scandic-web/components/MeetingPackageWidget/index.tsx +++ b/apps/scandic-web/components/MeetingPackageWidget/index.tsx @@ -1,59 +1,100 @@ "use client" -import { useEffect, useState } from "react" +import { + Button, + Dialog, + DialogTrigger, + Modal, + ModalOverlay, +} from "react-aria-components" +import { useIntl } from "react-intl" +import { useMediaQuery } from "usehooks-ts" -import useLang from "@/hooks/useLang" +import { IconButton } from "@scandic-hotels/design-system/IconButton" +import { MaterialIcon } from "@scandic-hotels/design-system/Icons/MaterialIcon" +import { Typography } from "@scandic-hotels/design-system/Typography" -import MeetingPackageWidgetSkeleton from "./Skeleton" +import MeetingPackageWidgetContent from "./Content/Content" import styles from "./meetingPackageWidget.module.css" -const SOURCE = - "https://scandic-bookingengine.s3.eu-central-1.amazonaws.com/script_stage.js" - -interface MeetingPackageWidgetProps { +export interface MeetingPackageWidgetProps { destination?: string className?: string } -export default function MeetingPackageWidget({ - destination, - className, -}: MeetingPackageWidgetProps) { - const lang = useLang() - const [isLoading, setIsLoading] = useState(true) +export default function MeetingPackageWidget(props: MeetingPackageWidgetProps) { + const intl = useIntl() + /* Meeting booking widget changes design at 948px */ + const isDesktop = useMediaQuery("(min-width: 948px)", { + initializeWithValue: false, + }) - useEffect(() => { - const script = document.createElement("script") - script.src = SOURCE - script.setAttribute("langcode", lang) - script.setAttribute("whitelabel_id", "224905") - script.setAttribute("widget_id", "scandic_default_new") - script.setAttribute("version", "frontpage-scandic") - if (destination) { - script.setAttribute("destination", destination) - } - document.body.appendChild(script) - - function onLoad() { - setIsLoading(false) - } - - script.addEventListener("load", onLoad) - - return () => { - script.removeEventListener("load", onLoad) - document.body.removeChild(script) - } - }, [destination, lang]) - - return ( -
- {isLoading && } -
+ return isDesktop ? ( + + ) : ( +
+ +
+ +
+ + + + {({ close }) => ( + <> +
+ + + +
+ + + )} +
+
+
+
) } diff --git a/apps/scandic-web/components/MeetingPackageWidget/meetingPackageWidget.module.css b/apps/scandic-web/components/MeetingPackageWidget/meetingPackageWidget.module.css index 9db369786..021f60c93 100644 --- a/apps/scandic-web/components/MeetingPackageWidget/meetingPackageWidget.module.css +++ b/apps/scandic-web/components/MeetingPackageWidget/meetingPackageWidget.module.css @@ -1,16 +1,125 @@ -.widget { - width: 100%; - max-width: var(--max-width-page); - margin: 0 auto; +.buttonWrapper { + padding: var(--Space-x15) var(--Space-x2); + display: flex; + background-color: var(--Component-Button-Brand-Primary-On-fill-Default); + color: var(--Text-Default); } -.widget.isLoading { - display: none; +.button { + display: flex; + border-width: 0; + padding: 0; + gap: var(--Space-x1); + align-items: center; + background-color: transparent; + width: 100%; + cursor: pointer; + + &:hover .fakeButton { + background-color: var(--Component-Button-Brand-Primary-Fill-Hover); + border-color: var(--Component-Button-Brand-Primary-Border-Hover); + color: var(--Component-Button-Brand-Primary-On-fill-Hover); + } +} + +.fakeInput { + display: grid; + justify-items: start; + padding: var(--Space-x1) var(--Space-x15); + background-color: var(--Surface-Primary-OnSurface-Default); + border-radius: var(--Corner-radius-md); + flex-grow: 1; +} + +.fakePlaceholder { + color: var(--Text-Interactive-Placeholder); +} + +.fakeButton { + border-radius: var(--Corner-radius-rounded); + border-width: 2px; + border-style: solid; + display: flex; + align-items: center; + justify-content: center; + gap: var(--Space-x05); + padding: 10px var(--Space-x2); + background-color: var(--Component-Button-Brand-Primary-Fill-Default); + border-color: var(--Component-Button-Brand-Primary-Border-Default); + color: var(--Component-Button-Brand-Primary-On-fill-Default); +} + +.overlay { + position: fixed; + inset: 0; + background-color: var(--Overlay-40); + + &[data-entering] { + animation: overlay-fade 200ms; + } + + &[data-exiting] { + animation: overlay-fade 150ms reverse ease-in; + } +} + +.modal { + position: fixed; + bottom: 0; + left: 0; + right: 0; + border-radius: var(--Corner-radius-md) var(--Corner-radius-md) 0 0; + background-color: var(--Surface-Primary-Default); + box-shadow: 0px 0px 14px 6px rgba(0, 0, 0, 0.1); + + &[data-entering] { + animation: modal-anim 200ms; + } + + &[data-exiting] { + animation: modal-anim 150ms reverse ease-in; + } +} + +.dialog { + display: grid; + align-content: start; + gap: var(--Space-x2); + overflow-y: auto; + height: 95dvh; + padding: var(--Space-x3) 0; +} + +.closeButtonWrapper { + display: flex; + justify-content: flex-end; + width: var(--max-width-page); + margin: 0 auto; } /* Meeting booking widget changes design at 948px */ @media screen and (min-width: 948px) { - .widget { - background-color: var(--Base-Surface-Primary-light-Normal); + .overlay { + display: none; + } +} + +@keyframes overlay-fade { + from { + opacity: 0; + } + + to { + opacity: 1; + } +} + +@keyframes modal-anim { + from { + transform: translateY(100%); + } + + to { + transform: translateY(0); } } diff --git a/apps/scandic-web/components/MeetingPackageWidget/useMeetingPackageWidget.ts b/apps/scandic-web/components/MeetingPackageWidget/useMeetingPackageWidget.ts new file mode 100644 index 000000000..81d1597b0 --- /dev/null +++ b/apps/scandic-web/components/MeetingPackageWidget/useMeetingPackageWidget.ts @@ -0,0 +1,37 @@ +import { useEffect, useState } from "react" + +import useLang from "@/hooks/useLang" + +const SOURCE = + "https://scandic-bookingengine.s3.eu-central-1.amazonaws.com/script_stage.js" + +export function useMeetingPackageWidget(destination?: string) { + const lang = useLang() + const [isLoading, setIsLoading] = useState(true) + + useEffect(() => { + const script = document.createElement("script") + script.src = SOURCE + script.setAttribute("langcode", lang || "en") + script.setAttribute("whitelabel_id", "224905") + script.setAttribute("widget_id", "scandic_default_new") + script.setAttribute("version", "frontpage-scandic") + if (destination) { + script.setAttribute("destination", destination) + } + document.body.appendChild(script) + + function onLoad() { + setIsLoading(false) + } + + script.addEventListener("load", onLoad) + + return () => { + script.removeEventListener("load", onLoad) + document.body.removeChild(script) + } + }, [destination, lang]) + + return { isLoading } +} diff --git a/apps/scandic-web/components/MeetingPackageWidget/utils.ts b/apps/scandic-web/components/MeetingPackageWidget/utils.ts index 04d1300cd..6d1514b80 100644 --- a/apps/scandic-web/components/MeetingPackageWidget/utils.ts +++ b/apps/scandic-web/components/MeetingPackageWidget/utils.ts @@ -1,5 +1,6 @@ // Hotel ids are used as keys to map to the destination id for the meeting package widget // The destination id is used to prefill the correct destination +// Last updated: 2025-03-11 export const meetingPackageDestinationByHotelId: Record = { "214": "341161", "215": "371906", diff --git a/apps/scandic-web/components/StickyMeetingPackageWidget/stickyMeetingPackageWidget.module.css b/apps/scandic-web/components/StickyMeetingPackageWidget/stickyMeetingPackageWidget.module.css index f28404fd3..dfe9a7376 100644 --- a/apps/scandic-web/components/StickyMeetingPackageWidget/stickyMeetingPackageWidget.module.css +++ b/apps/scandic-web/components/StickyMeetingPackageWidget/stickyMeetingPackageWidget.module.css @@ -5,11 +5,3 @@ box-shadow: 0px 16px 24px 0px rgba(0, 0, 0, 0.08); z-index: var(--booking-widget-z-index); } - -/* Temporary solution to show the Meeting package widget on mobile, but nonsticky */ -/* Meeting booking widget changes design at 948px */ -@media screen and (max-width: 947px) { - .wrapper { - position: unset; - } -}