fix(BOOK-711): Added isFloating prop to decide when the booking widget should have a border radius
Approved-by: Bianca Widstam
This commit is contained in:
@@ -1,3 +1,8 @@
|
||||
.formContent {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
}
|
||||
|
||||
.vouchersHeader {
|
||||
display: flex;
|
||||
gap: var(--Space-x15);
|
||||
@@ -100,25 +105,25 @@
|
||||
height: fit-content;
|
||||
}
|
||||
|
||||
.input {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
@media screen and (min-width: 768px) and (max-width: 1366px) {
|
||||
.formContent.floating .voucherContainer {
|
||||
border-bottom-left-radius: var(--Corner-Radius-lg);
|
||||
border-bottom-right-radius: var(--Corner-Radius-lg);
|
||||
}
|
||||
}
|
||||
|
||||
@media screen and (min-width: 768px) {
|
||||
.input {
|
||||
.formContent {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
flex-direction: row;
|
||||
}
|
||||
|
||||
.inputContainer {
|
||||
display: flex;
|
||||
flex: 2;
|
||||
gap: var(--Space-x15);
|
||||
}
|
||||
.voucherContainer {
|
||||
border-radius: 0 0 var(--Corner-Radius-md) var(--Corner-Radius-md);
|
||||
}
|
||||
|
||||
.rooms,
|
||||
.when,
|
||||
@@ -154,7 +159,7 @@
|
||||
}
|
||||
|
||||
@media screen and (min-width: 768px) and (max-width: 1366px) {
|
||||
.input {
|
||||
.formContent {
|
||||
flex-wrap: wrap;
|
||||
}
|
||||
.inputRow {
|
||||
@@ -197,8 +202,8 @@
|
||||
.inputContainer {
|
||||
margin-left: calc(-1 * var(--Space-x15));
|
||||
}
|
||||
.input {
|
||||
gap: var(--Space-x15);
|
||||
.formContent {
|
||||
gap: var(--Space-x2);
|
||||
}
|
||||
.inputRow {
|
||||
flex: 1;
|
||||
|
||||
@@ -31,11 +31,13 @@ type BookingWidgetFormContentProps = {
|
||||
formId: string
|
||||
onSubmit: () => void
|
||||
isSearching: boolean
|
||||
isFloating: boolean
|
||||
}
|
||||
export default function FormContent({
|
||||
formId,
|
||||
onSubmit,
|
||||
isSearching,
|
||||
isFloating,
|
||||
}: BookingWidgetFormContentProps) {
|
||||
const intl = useIntl()
|
||||
const {
|
||||
@@ -61,7 +63,7 @@ export default function FormContent({
|
||||
const nights = dt(selectedDate.toDate).diff(dt(selectedDate.fromDate), "days")
|
||||
|
||||
return (
|
||||
<div className={styles.input}>
|
||||
<div className={cx(styles.formContent, { [styles.floating]: isFloating })}>
|
||||
<div className={styles.inputRow}>
|
||||
<div className={styles.inputContainer}>
|
||||
<div className={styles.where}>
|
||||
@@ -170,7 +172,7 @@ export function BookingWidgetFormContentSkeleton() {
|
||||
const intl = useIntl()
|
||||
|
||||
return (
|
||||
<div className={styles.input}>
|
||||
<div className={styles.formContent}>
|
||||
<div className={styles.inputRow}>
|
||||
<div className={styles.inputContainer}>
|
||||
<div className={styles.where}>
|
||||
|
||||
@@ -32,9 +32,14 @@ const formId = "booking-widget"
|
||||
|
||||
type BookingWidgetFormProps = {
|
||||
type?: BookingWidgetType
|
||||
isFloating: boolean
|
||||
onClose: () => void
|
||||
}
|
||||
export default function Form({ type, onClose }: BookingWidgetFormProps) {
|
||||
export default function Form({
|
||||
type,
|
||||
isFloating,
|
||||
onClose,
|
||||
}: BookingWidgetFormProps) {
|
||||
const router = useRouter()
|
||||
const pathname = usePathname()
|
||||
const lang = useLang()
|
||||
@@ -106,6 +111,7 @@ export default function Form({ type, onClose }: BookingWidgetFormProps) {
|
||||
formId={formId}
|
||||
onSubmit={handleSubmit(onSubmit)}
|
||||
isSearching={isPending}
|
||||
isFloating={isFloating}
|
||||
/>
|
||||
</FormRAC>
|
||||
</section>
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
"use client"
|
||||
|
||||
import { zodResolver } from "@hookform/resolvers/zod"
|
||||
import { cx } from "class-variance-authority"
|
||||
import { useSearchParams } from "next/navigation"
|
||||
import { use, useEffect, useRef, useState } from "react"
|
||||
import { FormProvider, useForm } from "react-hook-form"
|
||||
@@ -43,6 +44,7 @@ export type BookingWidgetClientProps = {
|
||||
type?: BookingWidgetType
|
||||
data: BookingWidgetSearchData
|
||||
pageSettingsBookingCodePromise: Promise<string> | null
|
||||
isFloating?: boolean
|
||||
}
|
||||
export const FOCUS_WIDGET = "focusWidget"
|
||||
|
||||
@@ -50,6 +52,7 @@ export default function BookingWidgetClient({
|
||||
type,
|
||||
data,
|
||||
pageSettingsBookingCodePromise,
|
||||
isFloating = false,
|
||||
}: BookingWidgetClientProps) {
|
||||
const searchParams = useSearchParams()
|
||||
const focusWidget = searchParams.get(FOCUS_WIDGET) === "true"
|
||||
@@ -245,10 +248,13 @@ export default function BookingWidgetClient({
|
||||
<FormProvider {...methods}>
|
||||
<section
|
||||
ref={bookingWidgetRef}
|
||||
className={classNames}
|
||||
className={cx(classNames, { [styles.floating]: isFloating })}
|
||||
data-booking-widget-open={isOpen}
|
||||
>
|
||||
<MobileToggleButton openMobileSearch={openMobileSearch} />
|
||||
<MobileToggleButton
|
||||
openMobileSearch={openMobileSearch}
|
||||
isFloating={isFloating}
|
||||
/>
|
||||
<div className={styles.backdrop} onClick={closeMobileSearch} />
|
||||
<div className={formContainerClassNames}>
|
||||
<button
|
||||
@@ -258,7 +264,11 @@ export default function BookingWidgetClient({
|
||||
>
|
||||
<MaterialIcon icon="close" />
|
||||
</button>
|
||||
<Form type={type} onClose={closeMobileSearch} />
|
||||
<Form
|
||||
type={type}
|
||||
onClose={closeMobileSearch}
|
||||
isFloating={isFloating}
|
||||
/>
|
||||
</div>
|
||||
</section>
|
||||
</FormProvider>
|
||||
|
||||
@@ -56,7 +56,11 @@ export function FloatingBookingWidgetClient(props: Props) {
|
||||
ref={containerRef}
|
||||
>
|
||||
<div className={styles.floatingBackground}>
|
||||
<BookingWidgetClient {...props} type="compact" />
|
||||
<BookingWidgetClient
|
||||
{...props}
|
||||
type="compact"
|
||||
isFloating={!stickyTop}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
)
|
||||
|
||||
@@ -14,7 +14,10 @@
|
||||
/* To avoid this "flash" the styling is set to transparent) */
|
||||
/* It is a non-standard css proprty, so shouldn't have too much of an effect on accessibility. */
|
||||
-webkit-tap-highlight-color: transparent;
|
||||
border-radius: var(--Corner-Radius-md);
|
||||
|
||||
&.floating {
|
||||
border-radius: var(--Corner-Radius-md);
|
||||
}
|
||||
}
|
||||
|
||||
.complete {
|
||||
|
||||
@@ -20,9 +20,11 @@ import type { BookingWidgetSchema } from "../Client"
|
||||
|
||||
type BookingWidgetToggleButtonProps = {
|
||||
openMobileSearch: () => void
|
||||
isFloating: boolean
|
||||
}
|
||||
export default function MobileToggleButton({
|
||||
openMobileSearch,
|
||||
isFloating,
|
||||
}: BookingWidgetToggleButtonProps) {
|
||||
const intl = useIntl()
|
||||
const lang = useLang()
|
||||
@@ -99,7 +101,8 @@ export default function MobileToggleButton({
|
||||
<Button
|
||||
className={cx(
|
||||
styles.mobileToggleButton,
|
||||
locationAndDateIsSet ? styles.complete : styles.partial
|
||||
locationAndDateIsSet ? styles.complete : styles.partial,
|
||||
{ [styles.floating]: isFloating }
|
||||
)}
|
||||
onPress={openMobileSearch}
|
||||
>
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
.wrapper {
|
||||
.bookingWidgetContainer {
|
||||
position: sticky;
|
||||
z-index: var(--booking-widget-z-index);
|
||||
width: 100%;
|
||||
@@ -14,7 +14,9 @@
|
||||
z-index: 1;
|
||||
transform: translateY(0);
|
||||
visibility: visible;
|
||||
border-radius: var(--Corner-Radius-lg);
|
||||
}
|
||||
|
||||
@media screen and (max-width: 767px) {
|
||||
.backdrop {
|
||||
position: fixed;
|
||||
@@ -30,13 +32,16 @@
|
||||
&:has([data-rooms-open="true"]) {
|
||||
z-index: var(--booking-widget-open-z-index);
|
||||
}
|
||||
|
||||
&.floating .formContainer {
|
||||
border-radius: var(--Corner-Radius-lg);
|
||||
}
|
||||
}
|
||||
|
||||
.formContainer {
|
||||
display: grid;
|
||||
grid-template-rows: auto 1fr;
|
||||
background-color: var(--UI-Input-Controls-Surface-Normal);
|
||||
border-radius: 0;
|
||||
gap: var(--Space-x3);
|
||||
height: calc(100dvh - max(var(--sitewide-alert-sticky-height), 20px));
|
||||
width: 100%;
|
||||
@@ -53,18 +58,6 @@
|
||||
}
|
||||
}
|
||||
|
||||
.compact {
|
||||
.formContainer {
|
||||
border-radius: var(--Corner-Radius-lg);
|
||||
}
|
||||
}
|
||||
|
||||
@media screen and (max-width: 767px) {
|
||||
.formContainer {
|
||||
border-radius: var(--Corner-Radius-lg) var(--Corner-Radius-lg) 0 0;
|
||||
}
|
||||
}
|
||||
|
||||
.close {
|
||||
background: none;
|
||||
border: none;
|
||||
@@ -74,7 +67,7 @@
|
||||
}
|
||||
|
||||
@media screen and (min-width: 768px) {
|
||||
.wrapper {
|
||||
.bookingWidgetContainer {
|
||||
top: 0;
|
||||
}
|
||||
|
||||
|
||||
@@ -2,18 +2,21 @@ import { cva } from "class-variance-authority"
|
||||
|
||||
import styles from "./bookingWidget.module.css"
|
||||
|
||||
export const bookingWidgetContainerVariants = cva(styles.wrapper, {
|
||||
variants: {
|
||||
type: {
|
||||
default: "",
|
||||
full: "",
|
||||
compact: styles.compact,
|
||||
export const bookingWidgetContainerVariants = cva(
|
||||
styles.bookingWidgetContainer,
|
||||
{
|
||||
variants: {
|
||||
type: {
|
||||
default: "",
|
||||
full: "",
|
||||
compact: styles.compact,
|
||||
},
|
||||
},
|
||||
},
|
||||
defaultVariants: {
|
||||
type: "full",
|
||||
},
|
||||
})
|
||||
defaultVariants: {
|
||||
type: "full",
|
||||
},
|
||||
}
|
||||
)
|
||||
|
||||
export const formContainerVariants = cva(styles.formContainer, {
|
||||
variants: {
|
||||
|
||||
Reference in New Issue
Block a user