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"
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 { Typography } from "@scandic-hotels/design-system/Typography"
import { RoomPackageCodeEnum } from "@scandic-hotels/trpc/enums/roomFilter"
import { useSelectRateContext } from "../../../../../../contexts/SelectRate/SelectRateContext"
import { useBreakpoint } from "../../../../../../hooks/useBreakpoint"
import { RemoveBookingCodeButton } from "../RemoveBookingCodeButton/RemoveBookingCodeButton"
import PetRoomMessage from "./Form/Checkboxes/PetRoomMessage"
import { RoomPackageFilterModal } from "./Modal"
import { RoomPackageFilterPopover } from "./Popover"
@@ -21,8 +25,10 @@ import type { ReactNode } from "react"
export function RoomPackageFilter({ roomIndex }: { roomIndex: number }) {
const displayAsModal = useBreakpoint("mobile")
const intl = useIntl()
const {
input: { bookingCode },
getPackagesForRoom,
actions: { selectPackages },
} = useSelectRateContext()
@@ -65,32 +71,66 @@ export function RoomPackageFilter({ roomIndex }: { roomIndex: number }) {
})
return (
<div className={styles.roomPackageFilter}>
<div className={styles.selectedPackages}>
{selectedPackages.map((pkg) => (
<Typography
key={pkg.code}
variant="Body/Supporting text (caption)/smRegular"
>
<span className={styles.selectedPackage}>
<MaterialIcon
icon={getIconNameByPackageCode(pkg.code)}
size={16}
color="CurrentColor"
/>
{packageLabels[pkg.code] ?? pkg.description}
<ButtonRAC
onPress={() => deletePackage(pkg.code)}
className={styles.removeButton}
>
<MaterialIcon icon="close" size={16} color="CurrentColor" />
</ButtonRAC>
</span>
</Typography>
))}
<div
className={cx(styles.roomPackageFilter, {
[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
key={pkg.code}
variant="Body/Supporting text (caption)/smRegular"
>
<span className={styles.selectedPackage}>
<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>
{displayAsModal ? (
<div>
<div
className={cx(styles.filterSelector, {
[styles.hasBookingCode]: !!bookingCode,
})}
>
<RoomPackageFilterModal
availablePackages={packages}
selectedPackages={selectedPackages.map((pkg) => pkg.code)}
@@ -100,7 +140,11 @@ export function RoomPackageFilter({ roomIndex }: { roomIndex: number }) {
/>
</div>
) : (
<div>
<div
className={cx(styles.filterSelector, {
[styles.hasBookingCode]: !!bookingCode,
})}
>
<RoomPackageFilterPopover
availablePackages={packages}
selectedPackages={selectedPackages.map((pkg) => pkg.code)}

View File

@@ -1,12 +1,15 @@
.roomPackageFilter {
display: flex;
gap: var(--Space-x1);
flex-direction: column-reverse;
align-items: flex-start;
width: 100%;
align-items: center;
justify-content: flex-end;
flex-wrap: wrap;
}
.selectedPackages {
display: flex;
justify-content: flex-end;
gap: var(--Space-x1);
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 {
flex-direction: row;
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 {
display: none;
}

View File

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

View File

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