Merged in feat/SW-1630-implement-mobile-tablet-design (pull request #1395)

Feat/SW-1630 implement mobile tablet design

* feat(SW-1630): add mobile and tablet design

* feat(SW-1630): adjust zoom buttons

* feat(SW-1630): css changes

* feat(SW-1630): modify breakpoints


Approved-by: Erik Tiekstra
This commit is contained in:
Fredrik Thorsson
2025-02-25 10:10:20 +00:00
parent 2c72957dc6
commit f4234334be
13 changed files with 149 additions and 23 deletions

View File

@@ -11,7 +11,23 @@
}
.hotelList {
display: grid;
display: flex;
flex-direction: column;
gap: var(--Spacing-x3);
list-style: none;
}
@media screen and (max-width: 949px) {
.hotelListWrapper {
overflow-y: scroll;
}
.hotelList {
flex-direction: row;
align-items: end;
}
.header {
display: none;
}
}

View File

@@ -1,4 +1,5 @@
.hotelListItem {
display: grid;
background-color: var(--Base-Surface-Primary-light-Normal);
border: 1px solid var(--Base-Border-Subtle);
border-radius: var(--Corner-radius-Medium);
@@ -6,7 +7,8 @@
}
.content {
display: grid;
display: flex;
flex-direction: column;
gap: var(--Spacing-x2);
padding: var(--Spacing-x2) var(--Spacing-x3);
align-content: start;
@@ -41,3 +43,27 @@
.ctaWrapper {
justify-self: stretch;
}
@media screen and (max-width: 950px) {
.hotelListItem {
width: 360px;
min-height: 150px;
grid-template-columns: 1fr 2fr;
}
.content {
padding: var(--Spacing-x-one-and-half);
gap: var(--Spacing-x1);
}
.logo,
.captions,
.amenityItem:nth-child(n + 4),
.amenityName {
display: none;
}
.ctaWrapper {
margin-top: auto;
}
}

View File

@@ -38,7 +38,9 @@ export default function HotelListItem({ hotel, url }: HotelListItemProps) {
/>
<div className={styles.content}>
<div className={styles.intro}>
<HotelLogo hotelId={hotel.operaId} hotelType={hotel.hotelType} />
<div className={styles.logo}>
<HotelLogo hotelId={hotel.operaId} hotelType={hotel.hotelType} />
</div>
<Subtitle type="one" asChild>
<h3>{hotel.name}</h3>
</Subtitle>
@@ -67,7 +69,7 @@ export default function HotelListItem({ hotel, url }: HotelListItemProps) {
{IconComponent && (
<IconComponent color="grey80" width={20} height={20} />
)}
{amenity.name}
<span className={styles.amenityName}>{amenity.name}</span>
</li>
)
})}

View File

@@ -0,0 +1,5 @@
@media screen and (max-width: 949px) {
.title {
display: none;
}
}

View File

@@ -7,6 +7,8 @@ import { getIntl } from "@/i18n"
import Map from "../../Map"
import HotelList from "./HotelList"
import styles from "./cityMap.module.css"
import type { CityLocation } from "@/types/trpc/routers/hotel/locations"
interface CityMapProps {
@@ -27,7 +29,12 @@ export default async function CityMap({ city, cityIdentifier }: CityMapProps) {
apiKey={env.GOOGLE_STATIC_MAP_KEY}
pageType="city"
>
<Title level="h2" as="h3" textTransform="regular">
<Title
level="h2"
as="h3"
textTransform="regular"
className={styles.title}
>
{intl.formatMessage({ id: `Hotels in {city}` }, { city: city.name })}
</Title>
<HotelList hotels={hotels} />

View File

@@ -11,7 +11,23 @@
}
.cityList {
display: grid;
display: flex;
flex-direction: column;
gap: var(--Spacing-x3);
list-style: none;
}
@media screen and (max-width: 949px) {
.cityListWrapper {
overflow-x: scroll;
}
.cityList {
flex-direction: row;
align-items: end;
}
.header {
display: none;
}
}

View File

@@ -1,4 +1,5 @@
.cityListItem {
display: grid;
background-color: var(--Base-Surface-Primary-light-Normal);
border: 1px solid var(--Base-Border-Subtle);
border-radius: var(--Corner-radius-Medium);
@@ -20,3 +21,28 @@
gap: var(--Spacing-x2);
padding: var(--Spacing-x2) var(--Spacing-x3);
}
@media screen and (max-width: 949px) {
.cityListItem {
width: 360px;
min-height: 120px;
grid-template-columns: 1fr 2fr;
}
.imageWrapper {
height: 100%;
}
.content {
padding: var(--Spacing-x-one-and-half);
gap: var(--Spacing-x1);
}
.experienceList {
display: none;
}
.ctaWrapper {
margin-top: auto;
}
}

View File

@@ -36,15 +36,19 @@ export default async function CityListItem({ city }: CityListItemProps) {
<Subtitle asChild>
<h3>{city.heading}</h3>
</Subtitle>
<ExperienceList experiences={city.experiences} />
<Button intent="tertiary" theme="base" size="small" asChild>
<Link href={city.url}>
{intl.formatMessage(
{ id: "Explore {city}" },
{ city: city.cityName }
)}
</Link>
</Button>
<div className={styles.experienceList}>
<ExperienceList experiences={city.experiences} />
</div>
<div className={styles.ctaWrapper}>
<Button intent="tertiary" theme="base" size="small" asChild>
<Link href={city.url}>
{intl.formatMessage(
{ id: "Explore {city}" },
{ city: city.cityName }
)}
</Link>
</Button>
</div>
</section>
</article>
)

View File

@@ -0,0 +1,5 @@
@media screen and (max-width: 949px) {
.title {
display: none;
}
}

View File

@@ -10,6 +10,8 @@ import { getIntl } from "@/i18n"
import Map from "../../Map"
import CityList from "./CityList"
import styles from "./countryMap.module.css"
import type { Country } from "@/types/enums/country"
interface CountryMapProps {
@@ -34,7 +36,12 @@ export default async function CountryMap({ country }: CountryMapProps) {
apiKey={env.GOOGLE_STATIC_MAP_KEY}
pageType="country"
>
<Title level="h2" as="h3" textTransform="regular">
<Title
level="h2"
as="h3"
textTransform="regular"
className={styles.title}
>
{intl.formatMessage({ id: `Destinations in {country}` }, { country })}
</Title>
<CityList cities={cities} />

View File

@@ -53,7 +53,7 @@
box-shadow: var(--button-box-shadow);
}
@media screen and (min-width: 768px) {
@media screen and (min-width: 950px) {
.ctaButtons {
top: var(--Spacing-x4);
right: var(--Spacing-x4);
@@ -63,5 +63,6 @@
.zoomButtons {
display: flex;
flex-direction: row-reverse;
}
}

View File

@@ -100,10 +100,10 @@ export default function DynamicMap({
variant="icon"
size="small"
className={styles.zoomButton}
onClick={zoomOut}
aria-label={intl.formatMessage({ id: "Zoom in" })}
onClick={zoomIn}
aria-label={intl.formatMessage({ id: "Zoom out" })}
>
<MinusIcon color="burgundy" width={20} height={20} />
<PlusIcon color="burgundy" width={20} height={20} />
</Button>
<Button
theme="base"
@@ -111,10 +111,10 @@ export default function DynamicMap({
variant="icon"
size="small"
className={styles.zoomButton}
onClick={zoomIn}
aria-label={intl.formatMessage({ id: "Zoom out" })}
onClick={zoomOut}
aria-label={intl.formatMessage({ id: "Zoom in" })}
>
<PlusIcon color="burgundy" width={20} height={20} />
<MinusIcon color="burgundy" width={20} height={20} />
</Button>
</div>
</div>

View File

@@ -33,3 +33,14 @@
box-shadow: var(--button-box-shadow);
gap: var(--Spacing-x-half);
}
@media screen and (max-width: 949px) {
.sidebar {
position: absolute;
max-width: none;
padding: 0 var(--Spacing-x2) var(--Spacing-x3);
overflow: hidden;
bottom: 0;
z-index: 3;
}
}