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,9 +71,22 @@ 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,
})}
>
<div className={styles.bookingCode}>
<RemoveBookingCodeButton />
</div>
<div
className={cx(styles.selectedPackages, {
[styles.hasBookingCode]: !!bookingCode,
})}
>
{selectedPackages.map((pkg) => {
const filterLabel = packageLabels[pkg.code] ?? pkg.description
return (
<Typography <Typography
key={pkg.code} key={pkg.code}
variant="Body/Supporting text (caption)/smRegular" variant="Body/Supporting text (caption)/smRegular"
@@ -78,19 +97,40 @@ export function RoomPackageFilter({ roomIndex }: { roomIndex: number }) {
size={16} size={16}
color="CurrentColor" color="CurrentColor"
/> />
{packageLabels[pkg.code] ?? pkg.description} {filterLabel}
<ButtonRAC <IconButton
style="Muted"
theme="Inverted"
wrapping
onPress={() => deletePackage(pkg.code)} onPress={() => deletePackage(pkg.code)}
aria-label={intl.formatMessage(
{
id: "booking.removeSpecialNeedsFilter",
defaultMessage: "Remove {filter} filter",
},
{
filter: filterLabel,
}
)}
className={styles.removeButton} className={styles.removeButton}
> >
<MaterialIcon icon="close" size={16} color="CurrentColor" /> <MaterialIcon
</ButtonRAC> icon="close"
size={16}
color="Icon/Interactive/Default"
/>
</IconButton>
</span> </span>
</Typography> </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";