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