Feat/BOOK-63 hotel subpages branding
* feat(BOOK-63): Replaced css variables and components to apply hotel branding on subpages * feat(BOOK-63): Replaced css variables and components to apply hotel branding on hotel page map view Approved-by: Christel Westerberg Approved-by: Matilda Landström
This commit is contained in:
@@ -94,9 +94,17 @@
|
||||
}
|
||||
|
||||
.usp li:before {
|
||||
content: url("/_static/icons/heart.svg");
|
||||
content: "";
|
||||
position: relative;
|
||||
top: 3px;
|
||||
display: inline-flex;
|
||||
flex-shrink: 0;
|
||||
width: 16px;
|
||||
height: 16px;
|
||||
background-color: var(--Icon-Accent);
|
||||
mask-image: url("/_static/icons/heart.svg");
|
||||
mask-size: contain;
|
||||
mask-repeat: no-repeat;
|
||||
}
|
||||
|
||||
.primaryButton {
|
||||
|
||||
+1
-1
@@ -8,7 +8,7 @@
|
||||
}
|
||||
|
||||
.activeCard {
|
||||
border: 1px solid var(--Border-Interactive-Selected);
|
||||
border: 1px solid var(--Border-Interactive-Active);
|
||||
}
|
||||
|
||||
.content {
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
.sidebar {
|
||||
background-color: var(--Base-Surface-Primary-light-Normal);
|
||||
background-color: var(--Background-Primary);
|
||||
z-index: 2;
|
||||
}
|
||||
|
||||
@@ -36,7 +36,7 @@
|
||||
grid-template-columns: 1fr max-content;
|
||||
align-items: center;
|
||||
gap: var(--Space-x2);
|
||||
background-color: var(--Base-Surface-Primary-light-Normal);
|
||||
background-color: var(--Background-Primary);
|
||||
border-width: 0;
|
||||
color: var(--Text-Default);
|
||||
width: 100%;
|
||||
@@ -86,11 +86,12 @@
|
||||
.sidebarToggle {
|
||||
position: relative;
|
||||
color: var(--Text-Secondary);
|
||||
background-color: var(--Base-Surface-Primary-light-Normal);
|
||||
background-color: var(--Background-Primary);
|
||||
border-width: 0;
|
||||
margin: var(--Space-x2) 0;
|
||||
padding: var(--Space-x2);
|
||||
width: 100%;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.sidebarToggle::before {
|
||||
@@ -124,7 +125,7 @@
|
||||
width: 40vw;
|
||||
min-width: 10rem;
|
||||
max-width: 26.25rem;
|
||||
background-color: var(--Base-Surface-Primary-light-Normal);
|
||||
background-color: var(--Background-Primary);
|
||||
}
|
||||
|
||||
.sidebarToggle {
|
||||
|
||||
@@ -5,13 +5,11 @@
|
||||
display: flex;
|
||||
height: var(--hotel-map-height);
|
||||
width: 100dvw;
|
||||
background-color: var(--Base-Surface-Primary-light-Normal);
|
||||
background-color: var(--Background-Default);
|
||||
z-index: 1;
|
||||
}
|
||||
|
||||
.closeButton {
|
||||
box-shadow: var(--button-box-shadow);
|
||||
color: var(--Component-Button-Inverted-On-fill-Default);
|
||||
pointer-events: initial;
|
||||
gap: var(--Space-x05);
|
||||
}
|
||||
|
||||
+17
-6
@@ -14,10 +14,21 @@
|
||||
list-style-type: none;
|
||||
}
|
||||
|
||||
.heartList > li::before {
|
||||
content: url("/_static/icons/heart.svg");
|
||||
position: relative;
|
||||
height: 8px;
|
||||
top: 3px;
|
||||
margin-right: var(--Space-x1);
|
||||
.heartList > li {
|
||||
display: flex;
|
||||
gap: var(--Space-x1);
|
||||
|
||||
&::before {
|
||||
content: "";
|
||||
position: relative;
|
||||
top: 3px;
|
||||
display: inline-flex;
|
||||
flex-shrink: 0;
|
||||
width: 16px;
|
||||
height: 16px;
|
||||
background-color: var(--Icon-Accent);
|
||||
mask-image: url("/_static/icons/heart.svg");
|
||||
mask-size: contain;
|
||||
mask-repeat: no-repeat;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -5,7 +5,8 @@ import { Suspense } from "react"
|
||||
|
||||
import { dt } from "@scandic-hotels/common/dt"
|
||||
import { safeTry } from "@scandic-hotels/common/utils/safeTry"
|
||||
import { DEFAULT_THEME, type Theme } from "@scandic-hotels/common/utils/theme"
|
||||
import { DEFAULT_THEME } from "@scandic-hotels/common/utils/theme"
|
||||
import { getTheme } from "@scandic-hotels/common/utils/theme/serverContext"
|
||||
import { Alert } from "@scandic-hotels/design-system/Alert"
|
||||
import { TrackingSDK } from "@scandic-hotels/tracking/TrackingSDK"
|
||||
import { type HotelPageData } from "@scandic-hotels/trpc/types/hotelPage"
|
||||
@@ -58,16 +59,15 @@ import { HotelHashValues } from "@/types/enums/hotelPage"
|
||||
interface HotelPageProps {
|
||||
hotelData: HotelData
|
||||
hotelPageData: HotelPageData
|
||||
theme: Theme
|
||||
}
|
||||
|
||||
export default async function HotelPage({
|
||||
hotelData,
|
||||
hotelPageData,
|
||||
theme,
|
||||
}: HotelPageProps) {
|
||||
const lang = await getLang()
|
||||
const intl = await getIntl()
|
||||
const hotelTheme = getTheme()
|
||||
|
||||
const [meetingRoomsData] = await safeTry(
|
||||
getMeetingRooms({ hotelId: hotelData.hotel.operaId, language: lang })
|
||||
@@ -146,7 +146,7 @@ export default async function HotelPage({
|
||||
)
|
||||
const trackingHotelData = getTrackingHotelData(hotelData.hotel)
|
||||
|
||||
const isThemed = theme !== DEFAULT_THEME
|
||||
const isThemed = hotelTheme !== DEFAULT_THEME
|
||||
|
||||
return (
|
||||
<div className={styles.pageContainer}>
|
||||
@@ -226,7 +226,7 @@ export default async function HotelPage({
|
||||
healthAndWellness={healthAndWellness ?? null}
|
||||
pageSections={pageSections}
|
||||
activities={activities}
|
||||
hotelTheme={theme}
|
||||
hotelTheme={hotelTheme}
|
||||
/>
|
||||
{campaignsBlock ? (
|
||||
<HotelCampaigns
|
||||
|
||||
+17
-6
@@ -46,12 +46,23 @@
|
||||
list-style-type: none;
|
||||
}
|
||||
|
||||
.listItem::before {
|
||||
content: url("/_static/icons/heart.svg");
|
||||
position: relative;
|
||||
height: 8px;
|
||||
top: 3px;
|
||||
margin-right: var(--Space-x1);
|
||||
.listItem {
|
||||
display: flex;
|
||||
gap: var(--Space-x1);
|
||||
|
||||
&::before {
|
||||
content: "";
|
||||
position: relative;
|
||||
top: 3px;
|
||||
display: inline-flex;
|
||||
flex-shrink: 0;
|
||||
width: 16px;
|
||||
height: 16px;
|
||||
background-color: var(--Icon-Accent);
|
||||
mask-image: url("/_static/icons/heart.svg");
|
||||
mask-size: contain;
|
||||
mask-repeat: no-repeat;
|
||||
}
|
||||
}
|
||||
|
||||
@media screen and (min-width: 1367px) {
|
||||
|
||||
+7
-10
@@ -72,21 +72,18 @@ export default async function AccessibilitySubpage({
|
||||
<Typography variant="Title/Subtitle/md">
|
||||
<h2>{accessibilityGroup.name}</h2>
|
||||
</Typography>
|
||||
<ul className={styles.list}>
|
||||
{accessibilityGroup.specialNeeds.map((groupItem) => (
|
||||
<Typography
|
||||
key={groupItem.name}
|
||||
variant="Body/Paragraph/mdRegular"
|
||||
>
|
||||
<li className={styles.listItem}>
|
||||
<Typography variant="Body/Paragraph/mdRegular">
|
||||
<ul className={styles.list}>
|
||||
{accessibilityGroup.specialNeeds.map((groupItem) => (
|
||||
<li key={groupItem.name} className={styles.listItem}>
|
||||
{groupItem.details
|
||||
? // eslint-disable-next-line formatjs/no-literal-string-in-jsx
|
||||
`${groupItem.name}: ${groupItem.details}`
|
||||
: groupItem.name}
|
||||
</li>
|
||||
</Typography>
|
||||
))}
|
||||
</ul>
|
||||
))}
|
||||
</ul>
|
||||
</Typography>
|
||||
</div>
|
||||
))}
|
||||
</div>
|
||||
|
||||
+5
-1
@@ -1,7 +1,11 @@
|
||||
.header {
|
||||
display: grid;
|
||||
background-color: var(--Base-Surface-Subtle-Normal);
|
||||
background-color: var(--Background-Primary);
|
||||
padding-bottom: var(--Space-x4);
|
||||
|
||||
&.isThemed {
|
||||
gap: var(--Space-x3);
|
||||
}
|
||||
}
|
||||
|
||||
.heroWrapper {
|
||||
|
||||
@@ -1,5 +1,9 @@
|
||||
import { cx } from "class-variance-authority"
|
||||
import { Suspense } from "react"
|
||||
|
||||
import { DEFAULT_THEME } from "@scandic-hotels/common/utils/theme"
|
||||
import { getTheme } from "@scandic-hotels/common/utils/theme/serverContext"
|
||||
|
||||
import Breadcrumbs from "@/components/Breadcrumbs"
|
||||
import Hero from "@/components/Hero"
|
||||
import BreadcrumbsSkeleton from "@/components/TempDesignSystem/Breadcrumbs/BreadcrumbsSkeleton"
|
||||
@@ -17,10 +21,16 @@ export default async function HeroHeader({
|
||||
breadcrumbsTitle,
|
||||
heroImage,
|
||||
}: HeroHeaderProps) {
|
||||
const hotelTheme = getTheme()
|
||||
const isThemed = hotelTheme !== DEFAULT_THEME
|
||||
return (
|
||||
<div className={styles.header}>
|
||||
<div className={cx(styles.header, { [styles.isThemed]: isThemed })}>
|
||||
<Suspense fallback={<BreadcrumbsSkeleton size="contentWidth" />}>
|
||||
<Breadcrumbs subpageTitle={breadcrumbsTitle} size="contentWidth" />
|
||||
<Breadcrumbs
|
||||
subpageTitle={breadcrumbsTitle}
|
||||
size="contentWidth"
|
||||
isThemed={isThemed}
|
||||
/>
|
||||
</Suspense>
|
||||
|
||||
{heroImage ? (
|
||||
|
||||
+31
-13
@@ -1,21 +1,39 @@
|
||||
.ul,
|
||||
.ol {
|
||||
padding: var(--Space-x2) var(--Space-x0);
|
||||
display: grid;
|
||||
gap: var(--Space-x1);
|
||||
margin-left: var(--Space-x2);
|
||||
}
|
||||
|
||||
.ol > li::marker {
|
||||
color: var(--Primary-Light-On-Surface-Accent);
|
||||
padding: 0;
|
||||
margin: var(--Space-x2) 0;
|
||||
}
|
||||
|
||||
.li {
|
||||
margin-left: var(--Space-x3);
|
||||
display: flex;
|
||||
gap: var(--Space-x1);
|
||||
|
||||
* {
|
||||
display: inline;
|
||||
margin: 0;
|
||||
}
|
||||
}
|
||||
|
||||
.li > p {
|
||||
display: inline;
|
||||
.ul {
|
||||
list-style-type: none;
|
||||
|
||||
.li::before {
|
||||
content: "";
|
||||
position: relative;
|
||||
top: 3px;
|
||||
display: inline-flex;
|
||||
flex-shrink: 0;
|
||||
width: 16px;
|
||||
height: 16px;
|
||||
background-color: var(--Icon-Accent);
|
||||
mask-image: url("/_static/icons/heart.svg");
|
||||
mask-size: contain;
|
||||
mask-repeat: no-repeat;
|
||||
}
|
||||
}
|
||||
|
||||
.ol > .li::marker {
|
||||
color: var(--Icon-Accent);
|
||||
}
|
||||
|
||||
.heading {
|
||||
@@ -27,8 +45,8 @@
|
||||
}
|
||||
|
||||
@media screen and (min-width: 768px) {
|
||||
.ol:has(li:nth-last-child(n + 5)),
|
||||
.ul:has(li:nth-last-child(n + 5)) {
|
||||
.ol:has(.li:nth-last-child(n + 5)),
|
||||
.ul:has(.li:nth-last-child(n + 5)) {
|
||||
grid-template-columns: 1fr 1fr;
|
||||
grid-auto-flow: column;
|
||||
}
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
import { ElementType } from "domelementtype"
|
||||
import parse, { type DOMNode, Element, type Text } from "html-react-parser"
|
||||
|
||||
import Link from "@scandic-hotels/design-system/OldDSLink"
|
||||
import Table from "@scandic-hotels/design-system/Table"
|
||||
import { TextLink } from "@scandic-hotels/design-system/TextLink"
|
||||
import { Typography } from "@scandic-hotels/design-system/Typography"
|
||||
|
||||
import { NodeNames } from "./utils"
|
||||
@@ -98,16 +98,14 @@ function renderNode(domNode: Node, idx: number) {
|
||||
return <span>{renderChildren(domNode)}</span>
|
||||
}
|
||||
return (
|
||||
<Link
|
||||
<TextLink
|
||||
key={domNode.name + idx}
|
||||
color="Text/Interactive/Secondary"
|
||||
textDecoration="underline"
|
||||
weight="bold"
|
||||
target="_blank" //Always open in new tab
|
||||
href={domNode.attribs.href}
|
||||
isInline
|
||||
>
|
||||
{renderChildren(domNode)}
|
||||
</Link>
|
||||
</TextLink>
|
||||
)
|
||||
|
||||
case NodeNames.ul:
|
||||
@@ -117,19 +115,23 @@ function renderNode(domNode: Node, idx: number) {
|
||||
numberOfRows = Math.ceil(half)
|
||||
}
|
||||
return (
|
||||
<ul
|
||||
<Typography
|
||||
key={domNode.name + idx}
|
||||
className={styles.ul}
|
||||
style={
|
||||
numberOfRows
|
||||
? {
|
||||
gridTemplateRows: `repeat(${numberOfRows}, auto)`,
|
||||
}
|
||||
: {}
|
||||
}
|
||||
variant="Body/Paragraph/mdRegular"
|
||||
>
|
||||
{renderChildren(domNode)}
|
||||
</ul>
|
||||
<ul
|
||||
className={styles.ul}
|
||||
style={
|
||||
numberOfRows
|
||||
? {
|
||||
gridTemplateRows: `repeat(${numberOfRows}, auto)`,
|
||||
}
|
||||
: {}
|
||||
}
|
||||
>
|
||||
{renderChildren(domNode)}
|
||||
</ul>
|
||||
</Typography>
|
||||
)
|
||||
|
||||
case NodeNames.ol:
|
||||
@@ -139,23 +141,31 @@ function renderNode(domNode: Node, idx: number) {
|
||||
numberOfOlRows = Math.ceil(half)
|
||||
}
|
||||
return (
|
||||
<ol
|
||||
<Typography
|
||||
key={domNode.name + idx}
|
||||
className={styles.ol}
|
||||
style={
|
||||
numberOfOlRows
|
||||
? {
|
||||
gridTemplateRows: `repeat(${numberOfOlRows}, auto)`,
|
||||
}
|
||||
: {}
|
||||
}
|
||||
variant="Body/Paragraph/mdRegular"
|
||||
>
|
||||
{renderChildren(domNode)}
|
||||
</ol>
|
||||
<ol
|
||||
className={styles.ol}
|
||||
style={
|
||||
numberOfOlRows
|
||||
? {
|
||||
gridTemplateRows: `repeat(${numberOfOlRows}, auto)`,
|
||||
}
|
||||
: {}
|
||||
}
|
||||
>
|
||||
{renderChildren(domNode)}
|
||||
</ol>
|
||||
</Typography>
|
||||
)
|
||||
|
||||
case NodeNames.li:
|
||||
return <li key={domNode.name + idx}>{renderChildren(domNode)}</li>
|
||||
return (
|
||||
<li className={styles.li} key={domNode.name + idx}>
|
||||
{renderChildren(domNode)}
|
||||
</li>
|
||||
)
|
||||
|
||||
case NodeNames.td:
|
||||
return (
|
||||
@@ -208,13 +218,24 @@ function renderNode(domNode: Node, idx: number) {
|
||||
)
|
||||
|
||||
case NodeNames.em:
|
||||
return <em>{renderChildren(domNode)}</em>
|
||||
return <em key={domNode.name + idx}>{renderChildren(domNode)}</em>
|
||||
|
||||
case NodeNames.strong:
|
||||
return <strong>{renderChildren(domNode)}</strong>
|
||||
return (
|
||||
<Typography variant="Body/Paragraph/mdBold" key={domNode.name + idx}>
|
||||
<strong>{renderChildren(domNode)}</strong>
|
||||
</Typography>
|
||||
)
|
||||
|
||||
case NodeNames.span:
|
||||
return <span>{renderChildren(domNode)}</span>
|
||||
return (
|
||||
<Typography
|
||||
variant="Body/Paragraph/mdRegular"
|
||||
key={domNode.name + idx}
|
||||
>
|
||||
<span>{renderChildren(domNode)}</span>
|
||||
</Typography>
|
||||
)
|
||||
}
|
||||
} else if (domNode.type === ElementType.Text) {
|
||||
return domNode.data
|
||||
|
||||
+34
-57
@@ -2,13 +2,12 @@
|
||||
import { useState } from "react"
|
||||
import { useIntl } from "react-intl"
|
||||
|
||||
import { Divider } from "@scandic-hotels/design-system/Divider"
|
||||
import { MaterialIcon } from "@scandic-hotels/design-system/Icons/MaterialIcon"
|
||||
import Image from "@scandic-hotels/design-system/Image"
|
||||
import ImageFallback from "@scandic-hotels/design-system/ImageFallback"
|
||||
import { Typography } from "@scandic-hotels/design-system/Typography"
|
||||
|
||||
import ShowMoreButton from "../ShowMoreButton"
|
||||
import ShowMoreButton from "@/components/TempDesignSystem/ShowMoreButton"
|
||||
|
||||
import { translateRoomLighting, translateSeatingType } from "./utils"
|
||||
|
||||
import styles from "./meetingRoomCard.module.css"
|
||||
@@ -34,72 +33,51 @@ export default function MeetingRoomCard({ room }: MeetingRoomCardProps) {
|
||||
|
||||
return (
|
||||
<article className={styles.card}>
|
||||
{image?.src ? (
|
||||
<Image
|
||||
src={image.src}
|
||||
alt={image.altText || image.altText_En || ""}
|
||||
className={styles.image}
|
||||
width={386}
|
||||
height={200}
|
||||
sizes="(min-width: 768px) 386px, 100vw"
|
||||
/>
|
||||
) : (
|
||||
<ImageFallback />
|
||||
)}
|
||||
<Image
|
||||
src={image?.src || ""}
|
||||
alt={image?.altText || image?.altText_En || ""}
|
||||
className={styles.image}
|
||||
width={386}
|
||||
height={200}
|
||||
sizes="(min-width: 768px) 386px, 100vw"
|
||||
/>
|
||||
<div className={styles.content}>
|
||||
<Typography variant="Title/Subtitle/lg">
|
||||
<h3>{room.name}</h3>
|
||||
</Typography>
|
||||
<div className={styles.capacity}>
|
||||
<div className={styles.iconText}>
|
||||
<MaterialIcon
|
||||
icon="straighten"
|
||||
color="Icon/Interactive/Placeholder"
|
||||
/>
|
||||
<Typography
|
||||
variant="Body/Supporting text (caption)/smRegular"
|
||||
className={styles.roomDetails}
|
||||
>
|
||||
<Typography variant="Body/Supporting text (caption)/smRegular">
|
||||
<div className={styles.capacity}>
|
||||
<span className={styles.roomDetails}>
|
||||
<MaterialIcon icon="straighten" color="CurrentColor" size={16} />
|
||||
{/* eslint-disable-next-line formatjs/no-literal-string-in-jsx */}
|
||||
<span>{room.size} m²</span>
|
||||
</Typography>
|
||||
{room.size} m²
|
||||
</span>
|
||||
{maxSeatings ? (
|
||||
<span className={styles.roomDetails}>
|
||||
<MaterialIcon icon="person" color="CurrentColor" size={16} />
|
||||
{intl.formatMessage(
|
||||
{
|
||||
id: "meetingRoomCard.maxSeatings",
|
||||
defaultMessage: "max {seatings} pers",
|
||||
},
|
||||
{ seatings: maxSeatings }
|
||||
)}
|
||||
</span>
|
||||
) : null}
|
||||
</div>
|
||||
{maxSeatings ? (
|
||||
<div className={styles.iconText}>
|
||||
<MaterialIcon
|
||||
icon="person"
|
||||
color="Icon/Interactive/Placeholder"
|
||||
size={16}
|
||||
/>
|
||||
<Typography
|
||||
variant="Body/Supporting text (caption)/smRegular"
|
||||
className={styles.roomDetails}
|
||||
>
|
||||
<span>
|
||||
{intl.formatMessage(
|
||||
{
|
||||
id: "meetingRoomCard.maxSeatings",
|
||||
defaultMessage: "max {seatings} pers",
|
||||
},
|
||||
{ seatings: maxSeatings }
|
||||
)}
|
||||
</span>
|
||||
</Typography>
|
||||
</div>
|
||||
) : null}
|
||||
</div>
|
||||
</Typography>
|
||||
{room.content.texts.descriptions.medium ? (
|
||||
<Typography>
|
||||
<Typography variant="Body/Paragraph/mdRegular">
|
||||
<p>{room.content.texts.descriptions.medium}</p>
|
||||
</Typography>
|
||||
) : null}
|
||||
{opened && (
|
||||
<table className={styles.openedInfo}>
|
||||
<tbody className={styles.rowItem}>
|
||||
<table className={styles.infoTable}>
|
||||
<tbody className={styles.tableBody}>
|
||||
{room.seatings.map((seating, idx) => (
|
||||
<TableRow
|
||||
key={seating.type}
|
||||
id={String(seating.capacity) + seating.type + idx}
|
||||
id={`${seating.capacity} ${seating.type} ${idx}`}
|
||||
name={translateSeatingType(seating.type, intl)}
|
||||
value={intl.formatMessage(
|
||||
{
|
||||
@@ -111,8 +89,7 @@ export default function MeetingRoomCard({ room }: MeetingRoomCardProps) {
|
||||
/>
|
||||
))}
|
||||
</tbody>
|
||||
<Divider color="Border/Divider/Subtle" />
|
||||
<tbody className={styles.rowItem}>
|
||||
<tbody className={styles.tableBody}>
|
||||
<TableRow
|
||||
name={intl.formatMessage({
|
||||
id: "meetingRoomCard.locationInHotel",
|
||||
+32
-31
@@ -1,38 +1,11 @@
|
||||
.card {
|
||||
background-color: var(--Base-Surface-Primary-light-Normal);
|
||||
background-color: var(--Surface-Primary-Default);
|
||||
border-radius: var(--Corner-radius-md);
|
||||
border: 1px solid var(--Base-Border-Subtle);
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
border: 1px solid var(--Border-Default);
|
||||
display: grid;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
.capacity {
|
||||
display: grid;
|
||||
grid-template-columns: 1fr 1fr;
|
||||
gap: var(--Space-x1);
|
||||
text-align: left;
|
||||
}
|
||||
|
||||
.iconText {
|
||||
display: flex;
|
||||
gap: var(--Space-x05);
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.rowItem {
|
||||
display: grid;
|
||||
gap: var(--Space-x05);
|
||||
}
|
||||
|
||||
.openedInfo {
|
||||
background-color: var(--Base-Surface-Secondary-light-Normal);
|
||||
border-radius: var(--Corner-radius-md);
|
||||
padding: var(--Space-x2);
|
||||
display: grid;
|
||||
gap: var(--Space-x2);
|
||||
}
|
||||
|
||||
.image {
|
||||
height: 200px;
|
||||
width: 100%;
|
||||
@@ -47,10 +20,38 @@
|
||||
flex-grow: 1;
|
||||
}
|
||||
|
||||
.roomDetails {
|
||||
.capacity {
|
||||
display: grid;
|
||||
grid-template-columns: 1fr 1fr;
|
||||
gap: var(--Space-x1);
|
||||
text-align: left;
|
||||
color: var(--Text-Tertiary);
|
||||
}
|
||||
|
||||
.roomDetails {
|
||||
display: flex;
|
||||
gap: var(--Space-x05);
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.infoTable {
|
||||
background-color: var(--Surface-Primary-OnSurface-Default);
|
||||
border-radius: var(--Corner-radius-md);
|
||||
padding: var(--Space-x2);
|
||||
display: grid;
|
||||
gap: var(--Space-x2);
|
||||
}
|
||||
|
||||
.tableBody {
|
||||
display: grid;
|
||||
gap: var(--Space-x05);
|
||||
|
||||
&:not(:first-of-type) {
|
||||
border-top: 1px solid var(--Border-Divider-Default);
|
||||
padding-top: var(--Space-x2);
|
||||
}
|
||||
}
|
||||
|
||||
.leftColumn {
|
||||
color: var(--Text-Secondary);
|
||||
font-weight: inherit;
|
||||
+24
-10
@@ -1,19 +1,24 @@
|
||||
"use client"
|
||||
import { cx } from "class-variance-authority"
|
||||
import { useRef, useState } from "react"
|
||||
|
||||
import Grids from "@/components/TempDesignSystem/Grids"
|
||||
import MeetingRoomCard from "@/components/TempDesignSystem/MeetingRoomCard"
|
||||
import ShowMoreButton from "@/components/TempDesignSystem/ShowMoreButton"
|
||||
|
||||
import MeetingRoomCard from "./MeetingRoomCard"
|
||||
|
||||
import styles from "./meetingRooms.module.css"
|
||||
|
||||
import type { MeetingRooms } from "@/types/components/hotelPage/meetingRooms"
|
||||
|
||||
interface MeetingRoomsProps {
|
||||
interface MeetingRoomsProps extends React.HTMLAttributes<HTMLDivElement> {
|
||||
rooms: MeetingRooms
|
||||
}
|
||||
|
||||
export default function MeetingRooms({ rooms }: MeetingRoomsProps) {
|
||||
export default function MeetingRooms({
|
||||
rooms,
|
||||
className,
|
||||
...props
|
||||
}: MeetingRoomsProps) {
|
||||
const showToggleButton = rooms.length > 3
|
||||
const [allRoomsVisible, setAllRoomsVisible] = useState(!showToggleButton)
|
||||
|
||||
@@ -27,20 +32,29 @@ export default function MeetingRooms({ rooms }: MeetingRoomsProps) {
|
||||
}
|
||||
|
||||
return (
|
||||
<div className={styles.section} ref={scrollRef}>
|
||||
<Grids.Stackable
|
||||
className={`${styles.grid} ${allRoomsVisible ? styles.allVisible : ""}`}
|
||||
<section
|
||||
className={cx(styles.roomsContainer, className)}
|
||||
ref={scrollRef}
|
||||
{...props}
|
||||
>
|
||||
<ul
|
||||
className={cx(styles.roomsList, {
|
||||
[styles.allVisible]: allRoomsVisible,
|
||||
})}
|
||||
>
|
||||
{rooms.map((room) => (
|
||||
<MeetingRoomCard key={room.id} room={room.attributes} />
|
||||
<li key={room.id} className={styles.roomsItem}>
|
||||
<MeetingRoomCard room={room.attributes} />
|
||||
</li>
|
||||
))}
|
||||
</Grids.Stackable>
|
||||
</ul>
|
||||
{showToggleButton ? (
|
||||
<ShowMoreButton
|
||||
className={styles.showMoreButton}
|
||||
loadMoreData={handleShowMore}
|
||||
showLess={allRoomsVisible}
|
||||
/>
|
||||
) : null}
|
||||
</div>
|
||||
</section>
|
||||
)
|
||||
}
|
||||
|
||||
+31
-11
@@ -1,13 +1,33 @@
|
||||
.grid {
|
||||
align-items: flex-start;
|
||||
}
|
||||
|
||||
.grid:not(.allVisible) > :nth-child(n + 4) {
|
||||
display: none;
|
||||
}
|
||||
|
||||
.section {
|
||||
.roomsContainer {
|
||||
position: relative;
|
||||
color: var(--Text-Default);
|
||||
display: grid;
|
||||
gap: var(--Space-x4);
|
||||
z-index: 0;
|
||||
gap: var(--Space-x3);
|
||||
}
|
||||
|
||||
.roomsList {
|
||||
display: grid;
|
||||
gap: var(--Space-x2);
|
||||
grid-template-columns: 1fr;
|
||||
list-style: none;
|
||||
|
||||
&:not(.allVisible) > :nth-child(n + 4) {
|
||||
display: none;
|
||||
}
|
||||
}
|
||||
|
||||
.showMoreButton {
|
||||
justify-self: center;
|
||||
}
|
||||
|
||||
@media screen and (min-width: 768px) {
|
||||
.roomsList {
|
||||
grid-template-columns: repeat(2, 1fr);
|
||||
}
|
||||
}
|
||||
|
||||
@media screen and (min-width: 1367px) {
|
||||
.roomsList {
|
||||
grid-template-columns: repeat(3, 1fr);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -75,12 +75,13 @@ export default async function MeetingsSubpage({
|
||||
|
||||
{mainBody ? <HtmlContent html={mainBody} /> : null}
|
||||
</main>
|
||||
{meetingRooms ? (
|
||||
<div className={styles.meetingsInformation}>
|
||||
<MeetingsAdditionalContent rooms={meetingRooms} />
|
||||
</div>
|
||||
) : null}
|
||||
</div>
|
||||
{meetingRooms ? (
|
||||
<MeetingsAdditionalContent
|
||||
className={styles.additionalContent}
|
||||
rooms={meetingRooms}
|
||||
/>
|
||||
) : null}
|
||||
</section>
|
||||
</>
|
||||
)
|
||||
|
||||
+10
-7
@@ -1,8 +1,7 @@
|
||||
.meetingsSubpage {
|
||||
display: grid;
|
||||
padding-bottom: var(--Space-x9);
|
||||
color: var(--Text-Default);
|
||||
display: grid;
|
||||
gap: var(--Space-x4);
|
||||
}
|
||||
|
||||
.contentContainer {
|
||||
@@ -10,7 +9,11 @@
|
||||
gap: var(--Space-x3);
|
||||
width: var(--max-width-content);
|
||||
margin: 0 auto;
|
||||
color: var(--Text-Default);
|
||||
}
|
||||
|
||||
.additionalContent {
|
||||
width: var(--max-width-content);
|
||||
margin: var(--Space-x4) auto 0;
|
||||
}
|
||||
|
||||
.mainContent {
|
||||
@@ -48,6 +51,10 @@
|
||||
column-gap: var(--Space-x9);
|
||||
}
|
||||
|
||||
.additionalContent {
|
||||
margin-top: var(--Space-x7);
|
||||
}
|
||||
|
||||
.divider {
|
||||
display: none;
|
||||
}
|
||||
@@ -57,8 +64,4 @@
|
||||
grid-row: 1 / span 2;
|
||||
align-items: start;
|
||||
}
|
||||
|
||||
.meetingsInformation {
|
||||
grid-column: 1 / span 2;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -59,6 +59,7 @@ export default async function RestaurantSubpage({
|
||||
<ButtonLink
|
||||
href={bookTableUrl}
|
||||
variant="Primary"
|
||||
size="Medium"
|
||||
typography="Body/Paragraph/mdBold"
|
||||
>
|
||||
{intl.formatMessage({
|
||||
|
||||
+2
-3
@@ -10,7 +10,6 @@
|
||||
gap: var(--Space-x3);
|
||||
width: var(--max-width-content);
|
||||
margin: 0 auto;
|
||||
color: var(--Text-Default);
|
||||
}
|
||||
|
||||
.mainContent {
|
||||
@@ -38,8 +37,8 @@
|
||||
.buttonContainer {
|
||||
position: sticky;
|
||||
padding: var(--Space-x3) var(--Space-x2);
|
||||
background-color: var(--Base-Surface-Secondary-light-Normal);
|
||||
border-top: 1px solid var(--Base-Border-Subtle);
|
||||
background-color: var(--Background-Primary);
|
||||
border-top: 1px solid var(--Border-Default);
|
||||
bottom: 0;
|
||||
}
|
||||
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import Link from "@scandic-hotels/design-system/OldDSLink"
|
||||
import { TextLink } from "@scandic-hotels/design-system/TextLink"
|
||||
import { Typography } from "@scandic-hotels/design-system/Typography"
|
||||
|
||||
import LocalCallCharges from "@/components/LocalCallCharges"
|
||||
@@ -31,13 +31,9 @@ export default async function MeetingsSidebar({
|
||||
</h3>
|
||||
</Typography>
|
||||
<div className={styles.contactDetails}>
|
||||
<Link href={`tel:${phoneNumber}`}>{phoneNumber}</Link>
|
||||
<TextLink href={`tel:${phoneNumber}`}>{phoneNumber}</TextLink>
|
||||
<LocalCallCharges country={country} />
|
||||
{email && (
|
||||
<Link textDecoration="underline" href={`mailto:${email}`}>
|
||||
{email}
|
||||
</Link>
|
||||
)}
|
||||
{email ? <TextLink href={`mailto:${email}`}>{email}</TextLink> : null}
|
||||
</div>
|
||||
</div>
|
||||
</>
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import Link from "@scandic-hotels/design-system/OldDSLink"
|
||||
import { TextLink } from "@scandic-hotels/design-system/TextLink"
|
||||
import { Typography } from "@scandic-hotels/design-system/Typography"
|
||||
|
||||
import LocalCallCharges from "@/components/LocalCallCharges"
|
||||
@@ -52,16 +52,13 @@ export default async function ParkingSidebar({
|
||||
</h3>
|
||||
</Typography>
|
||||
<div className={styles.contactDetails}>
|
||||
<Link href={`tel:${contactInformation.phoneNumber}`}>
|
||||
<TextLink href={`tel:${contactInformation.phoneNumber}`}>
|
||||
{contactInformation.phoneNumber}
|
||||
</Link>
|
||||
</TextLink>
|
||||
<LocalCallCharges country={address.country} />
|
||||
<Link
|
||||
textDecoration="underline"
|
||||
href={`mailto:${contactInformation.email}`}
|
||||
>
|
||||
<TextLink href={`mailto:${contactInformation.email}`}>
|
||||
{contactInformation.email}
|
||||
</Link>
|
||||
</TextLink>
|
||||
</div>
|
||||
</div>
|
||||
</>
|
||||
|
||||
+22
-26
@@ -1,7 +1,7 @@
|
||||
import ButtonLink from "@scandic-hotels/design-system/ButtonLink"
|
||||
import { MaterialIcon } from "@scandic-hotels/design-system/Icons/MaterialIcon"
|
||||
import { OldDSButton as Button } from "@scandic-hotels/design-system/OldDSButton"
|
||||
import Link from "@scandic-hotels/design-system/OldDSLink"
|
||||
import OpeningHours from "@scandic-hotels/design-system/OpeningHours"
|
||||
import { TextLink } from "@scandic-hotels/design-system/TextLink"
|
||||
import { Typography } from "@scandic-hotels/design-system/Typography"
|
||||
|
||||
import LocalCallCharges from "@/components/LocalCallCharges"
|
||||
@@ -47,14 +47,17 @@ export default async function RestaurantSidebar({
|
||||
) : null}
|
||||
{bookTableUrl && (
|
||||
<div className={styles.buttonContainer}>
|
||||
<Button intent="primary" theme="base" asChild>
|
||||
<a href={bookTableUrl}>
|
||||
{intl.formatMessage({
|
||||
id: "restaurantBar.bookATable",
|
||||
defaultMessage: "Book a table",
|
||||
})}
|
||||
</a>
|
||||
</Button>
|
||||
<ButtonLink
|
||||
href={bookTableUrl}
|
||||
variant="Primary"
|
||||
size="Medium"
|
||||
typography="Body/Paragraph/mdBold"
|
||||
>
|
||||
{intl.formatMessage({
|
||||
id: "restaurantBar.bookATable",
|
||||
defaultMessage: "Book a table",
|
||||
})}
|
||||
</ButtonLink>
|
||||
</div>
|
||||
)}
|
||||
{restaurant.menus.length ? (
|
||||
@@ -70,19 +73,14 @@ export default async function RestaurantSidebar({
|
||||
<ul className={styles.menuList}>
|
||||
{restaurant.menus.map(({ name, url }) => (
|
||||
<li key={name}>
|
||||
<Link
|
||||
href={url}
|
||||
color="Text/Interactive/Secondary"
|
||||
textDecoration="underline"
|
||||
variant="icon"
|
||||
>
|
||||
<TextLink href={url} target="_blank">
|
||||
{name}
|
||||
<MaterialIcon
|
||||
icon="open_in_new"
|
||||
size={20}
|
||||
size={24}
|
||||
color="CurrentColor"
|
||||
/>
|
||||
</Link>
|
||||
</TextLink>
|
||||
</li>
|
||||
))}
|
||||
</ul>
|
||||
@@ -116,17 +114,15 @@ export default async function RestaurantSidebar({
|
||||
</h3>
|
||||
</Typography>
|
||||
<div className={styles.contactDetails}>
|
||||
{phoneNumber && (
|
||||
{phoneNumber ? (
|
||||
<>
|
||||
<Link href={`tel:${phoneNumber}`}>{phoneNumber}</Link>
|
||||
<TextLink href={`tel:${phoneNumber}`}>{phoneNumber}</TextLink>
|
||||
<LocalCallCharges country={hotelAddress.country} />
|
||||
</>
|
||||
)}
|
||||
{email && (
|
||||
<Link textDecoration="underline" href={`mailto:${email}`}>
|
||||
{email}
|
||||
</Link>
|
||||
)}
|
||||
) : null}
|
||||
{email ? (
|
||||
<TextLink href={`mailto:${email}`}>{email}</TextLink>
|
||||
) : null}
|
||||
</div>
|
||||
</div>
|
||||
)}
|
||||
|
||||
@@ -6,6 +6,7 @@
|
||||
.content {
|
||||
display: grid;
|
||||
gap: var(--Space-x15);
|
||||
color: var(--Text-Default);
|
||||
}
|
||||
|
||||
.menuList {
|
||||
|
||||
+1
-1
@@ -33,7 +33,7 @@
|
||||
}
|
||||
|
||||
.checkbox:has(input:checked) {
|
||||
border-color: var(--Border-Interactive-Selected);
|
||||
border-color: var(--Border-Interactive-Active);
|
||||
}
|
||||
|
||||
.checkbox:has(input:checked) span[class*="checkbox_checkbox_"] {
|
||||
|
||||
Reference in New Issue
Block a user