Merged in feat/SW-1740-final-design-subpages (pull request #1435)

feat/SW-1740 final design subpages

* feat(SW-1740): update design for subpages

* feat(SW-1740): add padding

* feat(SW-1740): use not pseudo class


Approved-by: Erik Tiekstra
Approved-by: Matilda Landström
This commit is contained in:
Fredrik Thorsson
2025-02-27 14:40:21 +00:00
parent 8061ab63a8
commit bda22f39ad
10 changed files with 190 additions and 149 deletions

View File

@@ -22,23 +22,25 @@ export default async function MeetingsSidebar({
return (
<aside className={styles.sidebar}>
<Title level="h3" as="h4">
{intl.formatMessage({ id: "Contact us" })}
</Title>
<div>
<Link href={`tel:${phoneNumber}`}>{phoneNumber}</Link>
{country === Country.Finland ? (
<Body>
{intl.formatMessage({
id: "Price 0,16 €/min + local call charges",
})}
</Body>
) : null}
{email && (
<Link textDecoration="underline" href={`mailto:${email}`}>
{email}
</Link>
)}
<div className={styles.content}>
<Title level="h3" as="h4">
{intl.formatMessage({ id: "Contact us" })}
</Title>
<div>
<Link href={`tel:${phoneNumber}`}>{phoneNumber}</Link>
{country === Country.Finland ? (
<Body>
{intl.formatMessage({
id: "Price 0,16 €/min + local call charges",
})}
</Body>
) : null}
{email && (
<Link textDecoration="underline" href={`mailto:${email}`}>
{email}
</Link>
)}
</div>
</div>
</aside>
)

View File

@@ -1,7 +1,3 @@
import NextLink from "next/link"
import { OpenInNewIcon } from "@/components/Icons"
import Button from "@/components/TempDesignSystem/Button"
import Link from "@/components/TempDesignSystem/Link"
import Body from "@/components/TempDesignSystem/Text/Body"
import Title from "@/components/TempDesignSystem/Text/Title"
@@ -18,43 +14,29 @@ interface HotelSidebarProps {
export default async function ParkingSidebar({ hotel }: HotelSidebarProps) {
const intl = await getIntl()
const parking = hotel.parking
.map((parking) => ({ url: parking.externalParkingUrl, type: parking.type }))
.filter(
(parking): parking is { type: string; url: string } => !!parking.url
)
return (
<aside className={styles.sidebar}>
<Title level="h3" as="h4">
{intl.formatMessage({ id: "Address" })}
</Title>
<div>
<Body color="uiTextHighContrast">{hotel.address.streetAddress}</Body>
<Body color="uiTextHighContrast">
{hotel.address.zipCode} {hotel.address.city}
</Body>
<Body color="uiTextHighContrast">{hotel.address.country}</Body>
<div className={styles.content}>
<Title level="h3" as="h4">
{intl.formatMessage({ id: "Address" })}
</Title>
<div>
<Body color="uiTextHighContrast">{hotel.address.streetAddress}</Body>
<Body color="uiTextHighContrast">
{hotel.address.zipCode} {hotel.address.city}
</Body>
<Body color="uiTextHighContrast">{hotel.address.country}</Body>
</div>
</div>
<Title level="h3" as="h4">
{intl.formatMessage({ id: "Contact us" })}
</Title>
<Link href={`tel:${hotel.contactInformation.phoneNumber}`}>
{hotel.contactInformation.phoneNumber}
</Link>
{parking.map(({ url, type }) => (
<Button key={type} theme="base" intent="primary" variant="icon" asChild>
<NextLink href={url} target="_blank">
{intl.formatMessage(
{ id: "Book {type} parking" },
{ type: type.toLowerCase() }
)}
<OpenInNewIcon />
</NextLink>
</Button>
))}
<div className={styles.content}>
<Title level="h3" as="h4">
{intl.formatMessage({ id: "Contact us" })}
</Title>
<Link href={`tel:${hotel.contactInformation.phoneNumber}`}>
{hotel.contactInformation.phoneNumber}
</Link>
</div>
</aside>
)
}

View File

@@ -6,7 +6,7 @@ import Body from "@/components/TempDesignSystem/Text/Body"
import Title from "@/components/TempDesignSystem/Text/Title"
import { getIntl } from "@/i18n"
import styles from "./restaurantSiderbar.module.css"
import styles from "./sidebar.module.css"
import type { Hotel, Restaurant } from "@/types/hotel"
@@ -42,11 +42,13 @@ export default async function RestaurantSidebar({
</div>
) : null}
{bookTableUrl && (
<Button intent="primary" theme="base" asChild>
<a href={bookTableUrl}>
{intl.formatMessage({ id: "Book a table online" })}
</a>
</Button>
<div className={styles.buttonContainer}>
<Button intent="primary" theme="base" asChild>
<a href={bookTableUrl}>
{intl.formatMessage({ id: "Book a table online" })}
</a>
</Button>
</div>
)}
{restaurant.menus.length ? (
<div className={styles.content}>

View File

@@ -1,15 +0,0 @@
.sidebar {
display: grid;
gap: var(--Spacing-x3);
}
.content {
display: grid;
gap: var(--Spacing-x-one-and-half);
}
.menuList {
display: grid;
gap: var(--Spacing-x-half);
list-style-type: none;
}

View File

@@ -19,59 +19,69 @@ export default async function WellnessSidebar({ hotel }: WellnessSidebarProps) {
return (
<aside className={styles.sidebar}>
<Title level="h3" as="h4">
{intl.formatMessage({ id: "Opening hours" })}
</Title>
{hotel.healthFacilities.map((facility) => (
<div key={facility.type}>
<Subtitle type="two" color="uiTextHighContrast" asChild>
<h4>{translateWellnessType(facility.type, intl)}</h4>
</Subtitle>
<div className={styles.content}>
<Title level="h3" as="h4">
{intl.formatMessage({ id: "Opening hours" })}
</Title>
{hotel.healthFacilities.map((facility) => (
<div key={facility.type}>
<Subtitle type="two" color="uiTextHighContrast" asChild>
<h4>{translateWellnessType(facility.type, intl)}</h4>
</Subtitle>
<Body color="uiTextHighContrast">
{facility.openingDetails.openingHours.ordinary.alwaysOpen
? intl.formatMessage({ id: "Mon-Fri Always open" })
: intl.formatMessage(
{ id: "Mon-Fri {openingTime}-{closingTime}" },
{
openingTime:
facility.openingDetails.openingHours.ordinary
.openingTime,
closingTime:
facility.openingDetails.openingHours.ordinary
.closingTime,
}
)}
</Body>
<Body color="uiTextHighContrast">
{facility.openingDetails.openingHours.weekends.alwaysOpen
? intl.formatMessage({ id: "Sat-Sun Always open" })
: intl.formatMessage(
{ id: "Sat-Sun {openingTime}-{closingTime}" },
{
openingTime:
facility.openingDetails.openingHours.weekends
.openingTime,
closingTime:
facility.openingDetails.openingHours.weekends
.closingTime,
}
)}
</Body>
</div>
))}
</div>
<div className={styles.content}>
<Title level="h3" as="h4">
{intl.formatMessage({ id: "Address" })}
</Title>
<div>
<Body color="uiTextHighContrast">{hotel.address.streetAddress}</Body>
<Body color="uiTextHighContrast">
{facility.openingDetails.openingHours.ordinary.alwaysOpen
? intl.formatMessage({ id: "Mon-Fri Always open" })
: intl.formatMessage(
{ id: "Mon-Fri {openingTime}-{closingTime}" },
{
openingTime:
facility.openingDetails.openingHours.ordinary.openingTime,
closingTime:
facility.openingDetails.openingHours.ordinary.closingTime,
}
)}
</Body>
<Body color="uiTextHighContrast">
{facility.openingDetails.openingHours.weekends.alwaysOpen
? intl.formatMessage({ id: "Sat-Sun Always open" })
: intl.formatMessage(
{ id: "Sat-Sun {openingTime}-{closingTime}" },
{
openingTime:
facility.openingDetails.openingHours.weekends.openingTime,
closingTime:
facility.openingDetails.openingHours.weekends.closingTime,
}
)}
{hotel.address.zipCode} {hotel.address.city}
</Body>
<Body color="uiTextHighContrast">{hotel.address.country}</Body>
</div>
))}
<Title level="h3" as="h4">
{intl.formatMessage({ id: "Address" })}
</Title>
<div>
<Body color="uiTextHighContrast">{hotel.address.streetAddress}</Body>
<Body color="uiTextHighContrast">
{hotel.address.zipCode} {hotel.address.city}
</Body>
<Body color="uiTextHighContrast">{hotel.address.country}</Body>
</div>
<Title level="h3" as="h4">
{intl.formatMessage({ id: "Contact us" })}
</Title>
<Link href={`tel:${hotel.contactInformation.phoneNumber}`}>
{hotel.contactInformation.phoneNumber}
</Link>
<div className={styles.content}>
<Title level="h3" as="h4">
{intl.formatMessage({ id: "Contact us" })}
</Title>
<Link href={`tel:${hotel.contactInformation.phoneNumber}`}>
{hotel.contactInformation.phoneNumber}
</Link>
</div>
</aside>
)
}

View File

@@ -1,6 +1,6 @@
import RestaurantSidebar from "./RestaurantSidebar/RestaurantSidebar"
import MeetingsSidebar from "./MeetingsSidebar"
import ParkingSidebar from "./ParkingSidebar"
import RestaurantSidebar from "./RestaurantSidebar"
import WellnessSidebar from "./WellnessSidebar"
import type { MeetingRooms } from "@/types/components/hotelPage/meetingRooms"

View File

@@ -1,13 +1,32 @@
.sidebar {
display: grid;
gap: var(--Spacing-x2);
gap: var(--Spacing-x3);
grid-column: 1;
}
.content {
display: grid;
gap: var(--Spacing-x-one-and-half);
}
.menuList {
display: grid;
gap: var(--Spacing-x-half);
list-style-type: none;
}
.buttonContainer {
display: none;
}
@media (min-width: 1367px) {
.sidebar {
grid-column: 2;
grid-row: 1;
grid-row: 1 / span 2;
align-items: start;
}
.buttonContainer {
display: block;
}
}

View File

@@ -1,4 +1,4 @@
.hotelSubpage {
.hotelSubpage:not(.hasStickyButton) {
padding-bottom: var(--Spacing-x9);
}
@@ -19,7 +19,7 @@
.contentContainer {
display: grid;
gap: var(--Spacing-x4);
gap: var(--Spacing-x3);
align-items: start;
width: 100%;
max-width: var(--max-width-content);
@@ -49,19 +49,43 @@
text-align: center;
}
.buttonContainer {
position: sticky;
padding: var(--Spacing-x3) var(--Spacing-x2);
background-color: var(--Base-Surface-Secondary-light-Normal);
border-top: 1px solid var(--Base-Border-Subtle);
bottom: 0;
}
@media (min-width: 1367px) {
.hotelSubpage {
padding-bottom: var(--Spacing-x9);
}
.contentContainer {
grid-template-columns: var(--max-width-text-block) 1fr;
grid-template-rows: auto 1fr;
row-gap: var(--Spacing-x2);
column-gap: var(--Spacing-x9);
padding: var(--Spacing-x4) 0 0;
}
.divider {
display: none;
}
.mainContent {
padding: 0;
max-width: none;
margin: 0;
gap: var(--Spacing-x3);
max-width: none;
}
.meetingsContent {
grid-column: 1 / span 2;
}
.buttonContainer {
display: none;
}
}

View File

@@ -10,6 +10,8 @@ import {
import Breadcrumbs from "@/components/Breadcrumbs"
import Hero from "@/components/Hero"
import BreadcrumbsSkeleton from "@/components/TempDesignSystem/Breadcrumbs/BreadcrumbsSkeleton"
import Button from "@/components/TempDesignSystem/Button"
import Divider from "@/components/TempDesignSystem/Divider"
import Preamble from "@/components/TempDesignSystem/Text/Preamble"
import Title from "@/components/TempDesignSystem/Text/Title"
import { getIntl } from "@/i18n"
@@ -56,6 +58,10 @@ export default async function HotelSubpage({
meetingRooms = await getMeetingRooms({ hotelId: hotelId, language: lang })
}
const restaurantButton = restaurants.find(
(restaurant) => restaurant.nameInUrl === subpage
)
const meetingBookingWidget = meetingRooms ? (
<div className={styles.meetingBookingWidget}>
Booking Widget Placeholder
@@ -64,7 +70,9 @@ export default async function HotelSubpage({
return (
<>
<section className={styles.hotelSubpage}>
<section
className={`${styles.hotelSubpage} ${restaurantButton?.bookTableUrl ? styles.hasStickyButton : ""} `}
>
<div className={styles.header}>
<Suspense fallback={<BreadcrumbsSkeleton />}>
<Breadcrumbs
@@ -87,11 +95,20 @@ export default async function HotelSubpage({
</div>
<div className={styles.contentContainer}>
<Title as="h2" level="h1">
{pageData.heading}
</Title>
<HotelSubpageSidebar
subpage={subpage}
hotel={hotel}
additionalData={additionalData}
restaurants={restaurants}
meetingRooms={meetingRooms}
/>
<Divider color="baseSurfaceSubtleHover" className={styles.divider} />
<main className={styles.mainContent}>
<div className={styles.intro}>
<Title as="h2" level="h1">
{pageData.heading}
</Title>
<Preamble>{pageData.elevatorPitch}</Preamble>
</div>
@@ -103,21 +120,21 @@ export default async function HotelSubpage({
additionalData={additionalData}
/>
</main>
{meetingRooms && (
<div className={styles.meetingsContent}>
<MeetingsAdditionalContent rooms={meetingRooms} />
</div>
)}
<HotelSubpageSidebar
subpage={subpage}
hotel={hotel}
additionalData={additionalData}
restaurants={restaurants}
meetingRooms={meetingRooms}
/>
</div>
{restaurantButton?.bookTableUrl && (
<div className={styles.buttonContainer}>
<Button intent="primary" theme="base" asChild>
<a href={restaurantButton.bookTableUrl}>
{intl.formatMessage({ id: "Book a table online" })}
</a>
</Button>
</div>
)}
</section>
{/* Tracking */}
</>

View File

@@ -21,31 +21,31 @@ export default async function OpeningHours({
const weekdayDefinitions = [
{
key: "monday",
label: intl.formatMessage({ id: "monday" }),
label: intl.formatMessage({ id: "Monday" }),
},
{
key: "tuesday",
label: intl.formatMessage({ id: "tuesday" }),
label: intl.formatMessage({ id: "Tuesday" }),
},
{
key: "wednesday",
label: intl.formatMessage({ id: "wednesday" }),
label: intl.formatMessage({ id: "Wednesday" }),
},
{
key: "thursday",
label: intl.formatMessage({ id: "thursday" }),
label: intl.formatMessage({ id: "Thursday" }),
},
{
key: "friday",
label: intl.formatMessage({ id: "friday" }),
label: intl.formatMessage({ id: "Friday" }),
},
{
key: "saturday",
label: intl.formatMessage({ id: "saturday" }),
label: intl.formatMessage({ id: "Saturday" }),
},
{
key: "sunday",
label: intl.formatMessage({ id: "sunday" }),
label: intl.formatMessage({ id: "Sunday" }),
},
] as const