Merged in fix/book-149-incorrect-onfocus-behaviour-booking-widget (pull request #3320)

Fix/book 149 incorrect onfocus behaviour booking widget

* fix(BOOK-149): fixed labels shifting

* fix(BOOK-149): reintroduced sticky position

* fix(BOOK-149): added missing border to "where" text field

* added overflow to datepicker

* comment fixes

* removed separate typography declaration

* changed to onPress

* fix(BOOK-149): moved components to separate files

* fix(BOOK-149): removed desktop & mobile specific css classes

* fix(BOOK-149): new implementation of date and room modals

* dependencies update

* fix(BOOK-149): fixed child age dropdown issue, related error message, and Rooms & Guests container height

* updated info button to new variant

* fix(BOOK-149): prevent scrolling of background when modals are open in Tablet mode

* fixed overlay issue and added focus indicator on mobile

* fixed missing space in css

* rebase and fixed icon buttons after update

* simplified to use explicit boolean

* PR comments fixes

* more PR comment fixes

* PR comment fixes

* fixed setIsOpen((prev) => !prev)

* fixed issues with room error not showing properly on mobile

* fixing pr comments

* fixed flickering on GuestRoomModal


Approved-by: Erik Tiekstra
This commit is contained in:
Matilda Haneling
2026-01-12 14:18:51 +00:00
parent 0c6a4cf186
commit 6a008ba342
38 changed files with 1117 additions and 743 deletions
@@ -6,11 +6,11 @@ import { useIntl } from "react-intl"
import { Button } from "@scandic-hotels/design-system/Button"
import { MaterialIcon } from "@scandic-hotels/design-system/Icons/MaterialIcon"
import { Tooltip } from "@scandic-hotels/design-system/Tooltip"
import { Typography } from "@scandic-hotels/design-system/Typography"
import { SEARCH_TYPE_REDEMPTION } from "@scandic-hotels/trpc/constants/booking"
import { useBookingFlowConfig } from "../../../bookingFlowConfig/bookingFlowConfigContext"
import { useIsDesktop } from "../../../hooks/useBreakpoint"
import { GuestsRoom } from "./GuestsRoom"
import styles from "./guests-rooms-picker.module.css"
@@ -30,6 +30,7 @@ export default function GuestsRoomsPickerDialog({
onClose,
}: GuestsRoomsPickerDialogProps) {
const intl = useIntl()
const isDesktop = useIsDesktop()
const config = useBookingFlowConfig()
const { getFieldState, trigger, setValue, getValues } =
useFormContext<BookingWidgetSchema>()
@@ -61,6 +62,11 @@ export default function GuestsRoomsPickerDialog({
defaultMessage:
"Multi-room booking is not available with this booking code.",
})
const isInvalid =
getFieldState("rooms").invalid ||
roomsValue.some((room) =>
room.childrenInRoom.some((child) => child.age === undefined)
)
const handleClose = useCallback(async () => {
const isValid = await trigger("rooms")
@@ -97,13 +103,11 @@ export default function GuestsRoomsPickerDialog({
if (fieldState.invalid) trigger("rooms")
}, [roomsValue, getFieldState, trigger])
const isInvalid =
getFieldState("rooms").invalid ||
roomsValue.some((room) =>
room.childrenInRoom.some((child) => child.age === undefined)
)
const canAddRooms = rooms.length < MAX_ROOMS
const addRoomButtonDisabled =
!!addRoomDisabledTextForSpecialRate || !canAddRooms
return (
<>
<section className={styles.contentWrapper}>
@@ -122,114 +126,89 @@ export default function GuestsRoomsPickerDialog({
onRemove={handleRemoveRoom}
/>
))}
{addRoomDisabledTextForSpecialRate ? (
<div className={styles.addRoomMobileContainer}>
<Button
variant="Text"
color="Primary"
wrapping
onPress={handleAddRoom}
isDisabled
size="sm"
>
<MaterialIcon icon="add" color="CurrentColor" />
{addRoomLabel}
</Button>
<div className={styles.errorContainer}>
<Typography
className={styles.error}
variant="Body/Supporting text (caption)/smRegular"
>
<span>
<MaterialIcon
icon="error"
size={20}
color="Icon/Feedback/Error"
isFilled
/>
{addRoomDisabledTextForSpecialRate}
</span>
</Typography>
</div>
</div>
) : (
canAddRooms && (
<div className={styles.addRoomMobileContainer}>
{!isDesktop && (
<>
<div className={styles.addRoomBtnContainer}>
<Button
className={styles.addRoomBtn}
variant="Text"
wrapping
color="Primary"
onPress={handleAddRoom}
isDisabled={addRoomButtonDisabled}
size="sm"
>
<MaterialIcon icon="add" color="CurrentColor" />
{addRoomLabel}
</Button>
</div>
)
{addRoomDisabledTextForSpecialRate && (
<div className={styles.errorContainer}>
<Typography
className={styles.error}
variant="Body/Supporting text (caption)/smRegular"
>
<span>
<MaterialIcon
icon="error"
size={20}
color="Icon/Feedback/Error"
isFilled
/>
{addRoomDisabledTextForSpecialRate}
</span>
</Typography>
</div>
)}
</>
)}
</div>
</section>
<footer className={styles.footer}>
{addRoomDisabledTextForSpecialRate ? (
<div className={styles.hideOnMobile}>
<Tooltip
text={addRoomDisabledTextForSpecialRate}
position="bottom"
arrow="left"
<div className={styles.footerButtons}>
{isDesktop && (
<Button
variant="Text"
wrapping
color="Primary"
isDisabled={addRoomButtonDisabled}
size="sm"
onPress={handleAddRoom}
>
<Button
variant="Text"
wrapping
color="Primary"
isDisabled
size="sm"
onPress={handleAddRoom}
>
<MaterialIcon icon="add_circle" color="CurrentColor" />
{addRoomLabel}
</Button>
</Tooltip>
</div>
) : (
canAddRooms && (
<div className={styles.hideOnMobile}>
<Button
className={styles.addRoomBtn}
variant="Text"
wrapping
color="Primary"
size="sm"
onPress={handleAddRoom}
>
<MaterialIcon icon="add_circle" color="CurrentColor" />
{addRoomLabel}
</Button>
<MaterialIcon icon="add_circle" color="CurrentColor" />
{addRoomLabel}
</Button>
)}
<Button
onPress={handleClose}
isDisabled={isInvalid}
className={styles.doneButton}
variant={isDesktop ? "Tertiary" : "Primary"}
color="Primary"
size={isDesktop ? "sm" : "md"}
>
{doneLabel}
</Button>
</div>
{/* DESKTOP INLINE ERROR MESSAGE */}
{addRoomDisabledTextForSpecialRate && isDesktop && (
<Typography
className={styles.error}
variant="Body/Supporting text (caption)/smRegular"
>
<div className={styles.errorContainer}>
<MaterialIcon
icon="error"
size={20}
color="Icon/Feedback/Error"
isFilled
/>
{addRoomDisabledTextForSpecialRate}
</div>
)
</Typography>
)}
<Button
onPress={handleClose}
isDisabled={isInvalid}
className={styles.hideOnDesktop}
variant="Tertiary"
color="Primary"
size="sm"
>
{doneLabel}
</Button>
<Button
onPress={handleClose}
isDisabled={isInvalid}
className={styles.hideOnMobile}
variant="Tertiary"
color="Primary"
size="sm"
>
{doneLabel}
</Button>
</footer>
</>
)