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

View File

@@ -1,11 +1,12 @@
"use client"
import { useEffect, useRef, useState } from "react"
import { useFormContext } from "react-hook-form"
import { useIntl } from "react-intl"
import Caption from "@scandic-hotels/design-system/Caption"
import DeprecatedSelect from "@scandic-hotels/design-system/DeprecatedSelect"
import { MaterialIcon } from "@scandic-hotels/design-system/Icons/MaterialIcon"
import { Select } from "@scandic-hotels/design-system/Select"
import { Typography } from "@scandic-hotels/design-system/Typography"
import { ChildBedMapEnum } from "@scandic-hotels/trpc/enums/childBedMapEnum"
import styles from "./child-selector.module.css"
@@ -38,6 +39,34 @@ export default function ChildInfoSelector({
index = 0,
roomIndex = 0,
}: ChildInfoSelectorProps) {
const ageSelectRef = useRef<HTMLDivElement>(null)
const bedPrefSelectRef = useRef<HTMLDivElement>(null)
const [ageWidth, setAgeWidth] = useState<number | undefined>(undefined)
const [bedWidth, setBedWidth] = useState<number | undefined>(undefined)
//Match width of the dropdown with width of parent select
useEffect(() => {
if (!ageSelectRef.current) return
const observer = new ResizeObserver(() => {
setAgeWidth(ageSelectRef.current!.offsetWidth)
})
observer.observe(ageSelectRef.current)
return () => observer.disconnect()
}, [])
useEffect(() => {
if (!bedPrefSelectRef.current) return
const observer = new ResizeObserver(() => {
setBedWidth(bedPrefSelectRef.current!.offsetWidth)
})
observer.observe(bedPrefSelectRef.current)
return () => observer.disconnect()
}, [])
const ageFieldName = `rooms.${roomIndex}.childrenInRoom.${index}.age`
const bedFieldName = `rooms.${roomIndex}.childrenInRoom.${index}.bed`
const intl = useIntl()
@@ -49,10 +78,12 @@ export default function ChildInfoSelector({
id: "booking.bedPreference",
defaultMessage: "Bed preference",
})
const errorMessage = intl.formatMessage({
id: "bookingWidget.child.ageRequiredError",
defaultMessage: "Child age is required",
})
const { setValue, formState } = useFormContext()
function updateSelectedBed(bed: number) {
@@ -113,50 +144,62 @@ export default function ChildInfoSelector({
return (
<>
<div key={index} className={styles.childInfoContainer}>
<div>
<DeprecatedSelect
required={true}
<div ref={ageSelectRef}>
<Select
isRequired
items={ageList}
name={ageFieldName}
label={ageLabel}
aria-label={ageLabel}
value={child.age ?? childDefaultValues.age}
onSelect={(key) => {
onSelectionChange={(key) => {
updateSelectedAge(key as number)
}}
maxHeight={180}
name={ageFieldName}
isNestedInModal={true}
popoverWidth={`${ageWidth}px`}
value={child.age ?? childDefaultValues.age}
isInvalid={!!ageError}
/>
</div>
<div>
<div ref={bedPrefSelectRef}>
{child.age >= 0 ? (
<DeprecatedSelect
<Select
isRequired
items={getAvailableBeds(child.age)}
name={bedFieldName}
label={bedLabel}
aria-label={bedLabel}
value={child.bed ?? childDefaultValues.bed}
onSelect={(key) => {
onSelectionChange={(key) => {
updateSelectedBed(key as number)
}}
name={bedFieldName}
isNestedInModal={true}
popoverWidth={`${bedWidth}px`}
/>
) : null}
</div>
</div>
{roomErrors && roomErrors.message ? (
<Caption color="red" className={styles.error}>
<MaterialIcon icon="error" color="Icon/Interactive/Accent" />
{roomErrors.message}
</Caption>
<Typography
variant="Body/Supporting text (caption)/smRegular"
className={styles.error}
>
<span>
<MaterialIcon icon="error" color="Icon/Interactive/Accent" />
{roomErrors.message}
</span>
</Typography>
) : null}
{ageError || bedError ? (
<Caption color="red" className={styles.error}>
<MaterialIcon icon="error" color="Icon/Interactive/Accent" />
{errorMessage}
</Caption>
<>
<Typography
variant="Body/Supporting text (caption)/smRegular"
className={styles.error}
>
<span>
<MaterialIcon icon="error" color="Icon/Feedback/Error" />
{errorMessage}
</span>
</Typography>
</>
) : null}
</>
)

View File

@@ -15,6 +15,7 @@
}
.error {
color: var(--Text-Interactive-Error);
display: flex;
align-items: center;
gap: var(--Space-x1);