Merged in fix/book-510-rearrange-special-needs-filter-and-code (pull request #3115)

BOOK-510: updated booking chip/special needs filter order on mobile

* BOOK-510: updated booking chip/special needs filter order on mobile

* BOOK-510: updated the close button to IconButton to fix styling issues on iOS

* book-510: added aria-label

* BOOK-510: refctored solution

* small spacing fixes

* fix(BOOK-510) updated aria-label


Approved-by: Erik Tiekstra
This commit is contained in:
Matilda Haneling
2025-11-19 08:21:42 +00:00
parent a1bb07186c
commit 624a106964
4 changed files with 127 additions and 35 deletions

View File

@@ -1,12 +1,16 @@
"use client" "use client"
import { Button as ButtonRAC } from "react-aria-components"
import { cx } from "class-variance-authority"
import { useIntl } from "react-intl"
import { IconButton } from "@scandic-hotels/design-system/IconButton"
import { MaterialIcon } from "@scandic-hotels/design-system/Icons/MaterialIcon" import { MaterialIcon } from "@scandic-hotels/design-system/Icons/MaterialIcon"
import { Typography } from "@scandic-hotels/design-system/Typography" import { Typography } from "@scandic-hotels/design-system/Typography"
import { RoomPackageCodeEnum } from "@scandic-hotels/trpc/enums/roomFilter" import { RoomPackageCodeEnum } from "@scandic-hotels/trpc/enums/roomFilter"
import { useSelectRateContext } from "../../../../../../contexts/SelectRate/SelectRateContext" import { useSelectRateContext } from "../../../../../../contexts/SelectRate/SelectRateContext"
import { useBreakpoint } from "../../../../../../hooks/useBreakpoint" import { useBreakpoint } from "../../../../../../hooks/useBreakpoint"
import { RemoveBookingCodeButton } from "../RemoveBookingCodeButton/RemoveBookingCodeButton"
import PetRoomMessage from "./Form/Checkboxes/PetRoomMessage" import PetRoomMessage from "./Form/Checkboxes/PetRoomMessage"
import { RoomPackageFilterModal } from "./Modal" import { RoomPackageFilterModal } from "./Modal"
import { RoomPackageFilterPopover } from "./Popover" import { RoomPackageFilterPopover } from "./Popover"
@@ -21,8 +25,10 @@ import type { ReactNode } from "react"
export function RoomPackageFilter({ roomIndex }: { roomIndex: number }) { export function RoomPackageFilter({ roomIndex }: { roomIndex: number }) {
const displayAsModal = useBreakpoint("mobile") const displayAsModal = useBreakpoint("mobile")
const intl = useIntl()
const { const {
input: { bookingCode },
getPackagesForRoom, getPackagesForRoom,
actions: { selectPackages }, actions: { selectPackages },
} = useSelectRateContext() } = useSelectRateContext()
@@ -65,32 +71,66 @@ export function RoomPackageFilter({ roomIndex }: { roomIndex: number }) {
}) })
return ( return (
<div className={styles.roomPackageFilter}> <div
<div className={styles.selectedPackages}> className={cx(styles.roomPackageFilter, {
{selectedPackages.map((pkg) => ( [styles.hasBookingCode]: !!bookingCode,
<Typography })}
key={pkg.code} >
variant="Body/Supporting text (caption)/smRegular" <div className={styles.bookingCode}>
> <RemoveBookingCodeButton />
<span className={styles.selectedPackage}> </div>
<MaterialIcon <div
icon={getIconNameByPackageCode(pkg.code)} className={cx(styles.selectedPackages, {
size={16} [styles.hasBookingCode]: !!bookingCode,
color="CurrentColor" })}
/> >
{packageLabels[pkg.code] ?? pkg.description} {selectedPackages.map((pkg) => {
<ButtonRAC const filterLabel = packageLabels[pkg.code] ?? pkg.description
onPress={() => deletePackage(pkg.code)} return (
className={styles.removeButton} <Typography
> key={pkg.code}
<MaterialIcon icon="close" size={16} color="CurrentColor" /> variant="Body/Supporting text (caption)/smRegular"
</ButtonRAC> >
</span> <span className={styles.selectedPackage}>
</Typography> <MaterialIcon
))} icon={getIconNameByPackageCode(pkg.code)}
size={16}
color="CurrentColor"
/>
{filterLabel}
<IconButton
style="Muted"
theme="Inverted"
wrapping
onPress={() => deletePackage(pkg.code)}
aria-label={intl.formatMessage(
{
id: "booking.removeSpecialNeedsFilter",
defaultMessage: "Remove {filter} filter",
},
{
filter: filterLabel,
}
)}
className={styles.removeButton}
>
<MaterialIcon
icon="close"
size={16}
color="Icon/Interactive/Default"
/>
</IconButton>
</span>
</Typography>
)
})}
</div> </div>
{displayAsModal ? ( {displayAsModal ? (
<div> <div
className={cx(styles.filterSelector, {
[styles.hasBookingCode]: !!bookingCode,
})}
>
<RoomPackageFilterModal <RoomPackageFilterModal
availablePackages={packages} availablePackages={packages}
selectedPackages={selectedPackages.map((pkg) => pkg.code)} selectedPackages={selectedPackages.map((pkg) => pkg.code)}
@@ -100,7 +140,11 @@ export function RoomPackageFilter({ roomIndex }: { roomIndex: number }) {
/> />
</div> </div>
) : ( ) : (
<div> <div
className={cx(styles.filterSelector, {
[styles.hasBookingCode]: !!bookingCode,
})}
>
<RoomPackageFilterPopover <RoomPackageFilterPopover
availablePackages={packages} availablePackages={packages}
selectedPackages={selectedPackages.map((pkg) => pkg.code)} selectedPackages={selectedPackages.map((pkg) => pkg.code)}

View File

@@ -1,12 +1,15 @@
.roomPackageFilter { .roomPackageFilter {
display: flex; display: flex;
gap: var(--Space-x1); gap: var(--Space-x1);
flex-direction: column-reverse; width: 100%;
align-items: flex-start; align-items: center;
justify-content: flex-end;
flex-wrap: wrap;
} }
.selectedPackages { .selectedPackages {
display: flex; display: flex;
justify-content: flex-end;
gap: var(--Space-x1); gap: var(--Space-x1);
flex-wrap: wrap; flex-wrap: wrap;
} }
@@ -93,12 +96,58 @@
} }
} }
@media screen and (min-width: 768px) { @media screen and (max-width: 949px) {
.roomPackageFilter {
flex-wrap: wrap-reverse;
&.hasBookingCode {
flex-wrap: wrap;
}
}
.selectedPackages {
order: 1;
&.hasBookingCode {
order: 3;
width: 100%;
}
}
.filterSelector {
order: 2;
display: flex;
justify-content: flex-end;
&.hasBookingCode {
width: fit-content;
order: 2;
}
}
.bookingCode {
&.hasBookingCode {
display: flex;
order: 1;
}
}
}
@media screen and (min-width: 950px) {
.roomPackageFilter { .roomPackageFilter {
flex-direction: row; flex-direction: row;
align-items: stretch; align-items: stretch;
} }
.selectedPackages {
flex: 1 100% auto;
order: 2;
min-width: fit-content;
}
.filterSelector {
order: 3;
flex: 0 0 auto;
}
.bookingCode {
order: 1;
flex: 0 0 auto;
}
}
@media screen and (min-width: 768px) {
.modalOverlay { .modalOverlay {
display: none; display: none;
} }

View File

@@ -2,7 +2,6 @@
import { ErrorBoundary } from "../../../../ErrorBoundary/ErrorBoundary" import { ErrorBoundary } from "../../../../ErrorBoundary/ErrorBoundary"
import NoAvailabilityAlert from "../NoAvailabilityAlert" import NoAvailabilityAlert from "../NoAvailabilityAlert"
import { RemoveBookingCodeButton } from "./RemoveBookingCodeButton/RemoveBookingCodeButton"
import { AvailableRoomsCount } from "./AvailableRoomsCount" import { AvailableRoomsCount } from "./AvailableRoomsCount"
import { RoomPackageFilter } from "./RoomPackageFilter" import { RoomPackageFilter } from "./RoomPackageFilter"
@@ -29,9 +28,7 @@ function InnerRoomsHeader({ roomIndex }: { roomIndex: number }) {
className={styles.noAvailabilityAlert} className={styles.noAvailabilityAlert}
/> />
<div className={styles.filters}> <div className={styles.filters}>
<RemoveBookingCodeButton />
<RoomPackageFilter roomIndex={roomIndex} /> <RoomPackageFilter roomIndex={roomIndex} />
{/* <BookingCodeFilter roomIndex={roomIndex} /> */}
</div> </div>
</div> </div>
) )

View File

@@ -1,7 +1,7 @@
.container { .container {
display: grid; display: grid;
gap: var(--Space-x3); gap: var(--Space-x1);
align-items: center; align-items: flex-start;
grid-template-areas: grid-template-areas:
"availableRoomsCount" "availableRoomsCount"
"noAvailabilityAlert" "noAvailabilityAlert"
@@ -21,11 +21,13 @@
display: flex; display: flex;
gap: var(--Space-x1); gap: var(--Space-x1);
align-items: flex-start; align-items: flex-start;
justify-content: flex-end;
flex-wrap: wrap;
} }
@media screen and (min-width: 768px) { @media screen and (min-width: 768px) {
.container { .container {
grid-template-columns: 1fr auto; grid-template-columns: auto 1fr;
grid-template-areas: grid-template-areas:
"availableRoomsCount filters" "availableRoomsCount filters"
"noAvailabilityAlert noAvailabilityAlert"; "noAvailabilityAlert noAvailabilityAlert";