Merged in fix/SW-1041-design-feedback-select-hotel (pull request #986)

fix(SW-1041): fix UI design feedback

* fix(SW-1041): fix UI design feedback

* fix(SW-1041): small fix

* fix(SW-1041): add filter and sort badge

* fix(SW-1041): update activefilter when entering map view

* fix(SW-1041): create hook with activefilters

* fix(SW-1041): hook only sets filter

* fix(SW-1041): fix padding breadcrumbs

* fix(SW-1041): rename hook

* fix(SW-1041): fix double scroll


Approved-by: Pontus Dreij
Approved-by: Niclas Edenvin
This commit is contained in:
Bianca Widstam
2024-11-28 07:42:52 +00:00
parent 4a11833b4d
commit 8f3d203b70
22 changed files with 205 additions and 95 deletions

View File

@@ -3,6 +3,4 @@
flex-direction: column;
gap: var(--Spacing-x2);
margin-bottom: var(--Spacing-x2);
max-height: 100vh;
overflow-y: auto;
}

View File

@@ -59,22 +59,42 @@
.content {
flex-direction: column;
gap: var(--Spacing-x3);
display: flex;
height: 100%;
}
.sorter {
padding: var(--Spacing-x2);
padding: var(--Spacing-x-one-and-half) var(--Spacing-x2) var(--Spacing-x-half)
var(--Spacing-x2);
flex: 0 0 auto;
}
.badge {
background-color: var(--Base-Text-Accent);
border-radius: var(--Corner-radius-xLarge);
width: 20px;
height: 20px;
color: #ffffff;
display: flex;
align-items: center;
justify-content: center;
}
.filters {
padding: var(--Spacing-x2);
padding-top: calc(var(--Spacing-x3) + var(--Spacing-x-half));
flex: 1 1 auto;
overflow-y: auto;
}
.filters ul {
margin-top: var(--Spacing-x3);
}
.filters ul li {
padding-bottom: var(--Spacing-x1);
}
.header {
text-align: right;
padding: var(--Spacing-x-one-and-half);
@@ -93,11 +113,15 @@
padding: 0;
}
.divider {
display: none;
}
.footer {
display: flex;
flex-direction: column-reverse;
flex-direction: column;
gap: var(--Spacing-x1);
padding: var(--Spacing-x2);
padding: var(--Spacing-x3) var(--Spacing-x2);
flex: 0 0 auto;
border-top: 1px solid var(--Base-Border-Subtle);
}
@@ -112,6 +136,11 @@
overflow-y: auto;
}
.divider {
display: block;
padding: 0 var(--Spacing-x3);
}
.header {
display: grid;
grid-template-columns: auto 1fr;
@@ -139,6 +168,10 @@
overflow-y: unset;
}
.sorter {
padding: var(--Spacing-x2);
}
.sorter,
.filters,
.footer,
@@ -158,19 +191,27 @@
padding: var(--Spacing-x2) var(--Spacing-x3);
}
.filters aside h1 {
margin-bottom: var(--Spacing-x2);
.filters aside > form {
gap: var(--Spacing-x2);
}
.filters aside > div:last-child {
margin-top: var(--Spacing-x4);
padding-bottom: 0;
.filters aside form > div:last-child {
margin-top: var(--Spacing-x2);
}
.filters aside ul {
display: grid;
grid-template-columns: 1fr 1fr;
margin-top: var(--Spacing-x3);
margin-top: var(--Spacing-x1);
}
.filters ul li:hover {
background: var(--UI-Input-Controls-Surface-Hover);
border-radius: var(--Corner-radius-Medium,);
outline: none;
}
.filters ul li {
padding: var(--Spacing-x1) var(--Spacing-x-one-and-half);
}
}
@media screen and (min-width: 1024) {

View File

@@ -13,7 +13,9 @@ import { useHotelFilterStore } from "@/stores/hotel-filters"
import { CloseLargeIcon, FilterIcon } from "@/components/Icons"
import Button from "@/components/TempDesignSystem/Button"
import Divider from "@/components/TempDesignSystem/Divider"
import Footnote from "@/components/TempDesignSystem/Text/Footnote"
import Subtitle from "@/components/TempDesignSystem/Text/Subtitle"
import useInitializeFiltersFromUrl from "@/hooks/useInitializeFiltersFromUrl"
import HotelFilter from "../HotelFilter"
import HotelSorter from "../HotelSorter"
@@ -26,15 +28,20 @@ export default function FilterAndSortModal({
filters,
}: FilterAndSortModalProps) {
const intl = useIntl()
useInitializeFiltersFromUrl()
const resultCount = useHotelFilterStore((state) => state.resultCount)
const setFilters = useHotelFilterStore((state) => state.setFilters)
const activeFilters = useHotelFilterStore((state) => state.activeFilters)
return (
<>
<DialogTrigger>
<Button intent="secondary" size="small" theme="base">
<FilterIcon color="burgundy" />
<Button intent="secondary" size="small" theme="base" variant="icon">
<FilterIcon color="baseTextHighcontrast" />
{intl.formatMessage({ id: "Filter and sort" })}
{activeFilters.length > 0 && (
<Footnote className={styles.badge}>{activeFilters.length}</Footnote>
)}
</Button>
<ModalOverlay className={styles.overlay} isDismissable>
<Modal className={styles.modal}>
@@ -60,7 +67,9 @@ export default function FilterAndSortModal({
<div className={styles.sorter}>
<HotelSorter />
</div>
<Divider color="subtle" className="divider" />
<div className={styles.divider}>
<Divider color="subtle" />
</div>
<div className={styles.filters}>
<HotelFilter filters={filters} />
</div>
@@ -76,7 +85,6 @@ export default function FilterAndSortModal({
{ count: resultCount }
)}
</Button>
<Button
onClick={() => setFilters([])}
intent="text"

View File

@@ -26,4 +26,5 @@
align-items: center;
justify-content: center;
forced-color-adjust: none;
background: var(--UI-Input-Controls-Surface-Normal);
}

View File

@@ -20,6 +20,9 @@
.facilities ul {
margin-top: var(--Spacing-x2);
}
.facilities:last-child {
padding-bottom: 0;
}
.filter {
display: grid;

View File

@@ -8,6 +8,7 @@ import { useHotelFilterStore } from "@/stores/hotel-filters"
import Subtitle from "@/components/TempDesignSystem/Text/Subtitle"
import Title from "@/components/TempDesignSystem/Text/Title"
import useInitializeFiltersFromUrl from "@/hooks/useInitializeFiltersFromUrl"
import FilterCheckbox from "./FilterCheckbox"
@@ -20,19 +21,9 @@ export default function HotelFilter({ className, filters }: HotelFiltersProps) {
const searchParams = useSearchParams()
const pathname = usePathname()
const toggleFilter = useHotelFilterStore((state) => state.toggleFilter)
const setFilters = useHotelFilterStore((state) => state.setFilters)
useInitializeFiltersFromUrl()
const activeFilters = useHotelFilterStore((state) => state.activeFilters)
// Initialize the filters from the URL
useEffect(() => {
const filtersFromUrl = searchParams.get("filters")
if (filtersFromUrl) {
setFilters(filtersFromUrl.split(","))
} else {
setFilters([])
}
}, [searchParams, setFilters])
// Update the URL when the filters changes
useEffect(() => {
const newSearchParams = new URLSearchParams(searchParams)
@@ -60,42 +51,46 @@ export default function HotelFilter({ className, filters }: HotelFiltersProps) {
return (
<aside className={`${styles.container} ${className}`}>
<Title as="h4">{intl.formatMessage({ id: "Filter by" })}</Title>
<div className={styles.facilities}>
<Subtitle>{intl.formatMessage({ id: "Hotel facilities" })}</Subtitle>
<ul>
{filters.facilityFilters.map((filter) => (
<li key={`li-${filter.id}`} className={styles.filter}>
<FilterCheckbox
name={filter.name}
id={filter.id.toString()}
onChange={() => toggleFilter(filter.id.toString())}
isSelected={
!!activeFilters.find((f) => f === filter.id.toString())
}
/>
</li>
))}
</ul>
</div>
<form>
<Title as="h4">{intl.formatMessage({ id: "Filter by" })}</Title>
<div className={styles.facilities}>
<Subtitle>{intl.formatMessage({ id: "Hotel facilities" })}</Subtitle>
<ul>
{filters.facilityFilters.map((filter) => (
<li key={`li-${filter.id}`} className={styles.filter}>
<FilterCheckbox
name={filter.name}
id={filter.id.toString()}
onChange={() => toggleFilter(filter.id.toString())}
isSelected={
!!activeFilters.find((f) => f === filter.id.toString())
}
/>
</li>
))}
</ul>
</div>
<div className={styles.facilities}>
<Subtitle>{intl.formatMessage({ id: "Hotel surroundings" })}</Subtitle>
<ul>
{filters.surroundingsFilters.map((filter) => (
<li key={`li-${filter.id}`} className={styles.filter}>
<FilterCheckbox
name={filter.name}
id={filter.id.toString()}
onChange={() => toggleFilter(filter.id.toString())}
isSelected={
!!activeFilters.find((f) => f === filter.id.toString())
}
/>
</li>
))}
</ul>
</div>
<div className={styles.facilities}>
<Subtitle>
{intl.formatMessage({ id: "Hotel surroundings" })}
</Subtitle>
<ul>
{filters.surroundingsFilters.map((filter) => (
<li key={`li-${filter.id}`} className={styles.filter}>
<FilterCheckbox
name={filter.name}
id={filter.id.toString()}
onChange={() => toggleFilter(filter.id.toString())}
isSelected={
!!activeFilters.find((f) => f === filter.id.toString())
}
/>
</li>
))}
</ul>
</div>
</form>
</aside>
)
}

View File

@@ -25,13 +25,20 @@ export default function MobileMapButtonContainer({
return (
<div className={styles.buttonContainer}>
<Button asChild variant="icon" intent="secondary" size="small">
<Button
asChild
theme="base"
variant="icon"
intent="secondary"
size="small"
>
<Link
href={selectHotelMap(lang)}
color="baseButtonTextOnFillNormal"
keepSearchParams
color="burgundy"
weight="bold"
>
<MapIcon color="burgundy" />
<MapIcon color="baseTextHighcontrast" />
{intl.formatMessage({ id: "See on map" })}
</Link>
</Button>

View File

@@ -23,6 +23,10 @@
height: 44px;
}
.container .listingContainer .filterContainer > button {
border: none;
}
@media (min-width: 768px) {
.container .closeButton {
display: flex;