fix: refactor breadcrumbs to take page type variants to better match margins

This commit is contained in:
Christel Westerberg
2025-01-03 11:39:24 +01:00
parent 053ef4a1c9
commit 5901cab440
46 changed files with 286 additions and 175 deletions

View File

@@ -3,7 +3,11 @@ import { serverClient } from "@/lib/trpc/server"
import BreadcrumbsComp from "@/components/TempDesignSystem/Breadcrumbs"
import { generateBreadcrumbsSchema } from "@/utils/jsonSchemas"
export default async function Breadcrumbs() {
import type { BreadcrumbsProps } from "@/components/TempDesignSystem/Breadcrumbs/breadcrumbs"
export default async function Breadcrumbs({
variant,
}: Pick<BreadcrumbsProps, "variant">) {
const breadcrumbs = await serverClient().contentstack.breadcrumbs.get()
if (!breadcrumbs?.length) {
@@ -19,7 +23,7 @@ export default async function Breadcrumbs() {
__html: JSON.stringify(jsonSchema.jsonLd),
}}
/>
<BreadcrumbsComp breadcrumbs={breadcrumbs} />
<BreadcrumbsComp breadcrumbs={breadcrumbs} variant={variant} />
</>
)
}

View File

@@ -3,7 +3,7 @@
gap: 8px;
position: relative;
width: 100%;
padding: var(--Spacing-x2) var(--Spacing-x2) 0;
padding: 0 var(--Spacing-x2);
z-index: 0;
}
@@ -14,6 +14,8 @@
height: 100%;
max-height: 30vh;
cursor: pointer;
max-width: var(--max-width-page);
margin: 0 auto;
}
.imageWrapper > :nth-child(2),
@@ -28,6 +30,12 @@
z-index: 1;
}
@media screen and (min-width: 768px) {
.seeAllButton {
right: calc(var(--Spacing-x2) + var(--Layout-Tablet-Margin-Margin-min));
}
}
@media screen and (min-width: 1367px) {
.imageWrapper {
grid-template-columns: 70% 30%;
@@ -35,7 +43,7 @@
grid-template-areas:
"main side1"
"main side2";
padding: var(--Spacing-x2) var(--Spacing-x5) 0;
padding: 0 var(--Spacing-x5);
}
.image {

View File

@@ -12,9 +12,10 @@
display: flex;
gap: var(--Spacing-x4);
justify-content: flex-start;
padding: 0 var(--Spacing-x2);
width: 100%;
overflow-x: auto;
max-width: var(--max-width-page);
margin: 0 auto;
}
@media screen and (min-width: 768px) {
@@ -28,5 +29,6 @@
padding: 0 var(--Spacing-x5);
max-width: calc(100% - var(--hotel-page-map-desktop-width));
overflow-x: visible;
margin: 0;
}
}

View File

@@ -13,7 +13,6 @@
"tabNavigation"
"mainSection"
"mapContainer";
margin: 0 auto;
max-width: var(--max-width);
}
@@ -26,7 +25,9 @@
grid-area: mainSection;
display: grid;
gap: var(--Spacing-x9);
padding: var(--Spacing-x4) var(--Spacing-x2);
padding: var(--Spacing-x4) 0;
max-width: var(--max-width-page);
margin: 0 auto;
}
.mapContainer {
@@ -51,6 +52,17 @@
gap: var(--Spacing-x2);
}
@media screen and (min-width: 768px) {
.pageContainer {
margin: 0 auto;
}
.mainSection {
max-width: 100%;
padding: var(--Spacing-x6) var(--Layout-Tablet-Margin-Margin-min);
}
}
@media screen and (min-width: 1367px) {
.pageContainer {
grid-template-areas:
@@ -61,7 +73,7 @@
}
.mainSection {
grid-area: mainSection;
padding: var(--Spacing-x6) var(--Spacing-x4);
padding: var(--Spacing-x6) var(--Layout-Desktop-Margin-Margin-min);
}
.mapContainer {
display: flex;

View File

@@ -42,6 +42,7 @@ import { FacilityCardTypeEnum } from "@/types/components/hotelPage/facilities"
import type { HotelPageProps } from "@/types/components/hotelPage/hotelPage"
import { HotelHashValues } from "@/types/components/hotelPage/tabNavigation"
import type { Facility } from "@/types/hotel"
import { PageContentTypeEnum } from "@/types/requests/contentType"
export default async function HotelPage({ hotelId }: HotelPageProps) {
const lang = getLang()
@@ -122,7 +123,7 @@ export default async function HotelPage({ hotelId }: HotelPageProps) {
/>
<header className={styles.header}>
<Suspense fallback={<BreadcrumbsSkeleton />}>
<Breadcrumbs />
<Breadcrumbs variant={PageContentTypeEnum.hotelPage} />
</Suspense>
{images?.length ? (
<PreviewImages images={images} hotelName={name} />

View File

@@ -3,8 +3,8 @@
grid-template-areas: "main";
grid-template-columns: 1fr;
gap: var(--Spacing-x5);
padding: 0 var(--Spacing-x2) var(--Spacing-x9);
max-width: var(--max-width);
padding-bottom: var(--Spacing-x9);
max-width: var(--max-width-page);
margin: 0 auto;
width: 100%;
}
@@ -27,10 +27,6 @@
}
@media screen and (min-width: 1367px) {
.content {
padding: 0 var(--Spacing-x5) var(--Spacing-x9);
}
.content:has(> aside) {
grid-template-areas: "sidebar main";
grid-template-columns: 360px 1fr;

View File

@@ -4,7 +4,7 @@
.header {
background-color: var(--Base-Surface-Subtle-Normal);
padding: var(--Spacing-x4) var(--Spacing-x2);
padding: var(--Spacing-x4) 0;
}
.headerContent {
@@ -32,9 +32,9 @@
}
.contentContainer {
padding-top: var(--Spacing-x4);
width: 100%;
padding: var(--Spacing-x4) var(--Spacing-x2) 0;
max-width: var(--max-width-content);
margin: 0 auto;
}
.content .contentContainer {
@@ -48,9 +48,10 @@
.mainContent {
display: grid;
gap: var(--Spacing-x4);
width: 100%;
gap: var(--Spacing-x6);
margin: 0 auto;
max-width: var(--max-width-content);
}
.content .mainContent {
@@ -58,9 +59,21 @@
}
@media (min-width: 768px) {
.contentContainer {
padding: var(--Spacing-x4) 0;
}
.heroContainer {
padding: var(--Spacing-x4) 0;
}
.headerIntro {
gap: var(--Spacing-x3);
}
.header {
padding: var(--Spacing-x4) 0;
}
}
@media (min-width: 1367px) {
@@ -70,6 +83,8 @@
.contentContainer {
padding: var(--Spacing-x4) 0 0;
max-width: var(--max-width-content);
margin: 0 auto;
}
.content .contentContainer {
@@ -80,5 +95,8 @@
.mainContent {
gap: var(--Spacing-x9);
padding: 0;
max-width: none;
margin: 0;
}
}

View File

@@ -10,7 +10,7 @@
position: relative;
text-align: center;
box-sizing: content-box;
max-width: 1200px;
max-width: var(--max-width-page);
margin: 0 auto;
padding: 70px 30px;
}

View File

@@ -1,20 +1,23 @@
.details {
background: var(--Base-Text-High-contrast);
color: var(--Primary-Dark-On-Surface-Text);
padding: var(--Spacing-x3) var(--Spacing-x2) var(--Spacing-x6);
padding: var(--Spacing-x3) 0 var(--Spacing-x6);
}
.topContainer {
display: flex;
justify-content: space-between;
padding-bottom: var(--Spacing-x2);
margin-bottom: var(--Spacing-x2);
max-width: var(--max-width-page);
margin: 0 auto var(--Spacing-x2);
}
.bottomContainer {
display: flex;
justify-content: space-between;
flex-direction: column-reverse;
max-width: var(--max-width-page);
margin: 0 auto;
}
.socialNav {
@@ -55,7 +58,7 @@
@media screen and (min-width: 767px) {
.details {
padding: var(--Spacing-x6) var(--Spacing-x5) var(--Spacing-x4);
padding: var(--Spacing-x6) 0 var(--Spacing-x4);
}
.bottomContainer {

View File

@@ -1,6 +1,6 @@
.section {
background: var(--Base-Surface-Subtle-Normal);
padding: var(--Spacing-x7) var(--Spacing-x2);
padding: var(--Spacing-x7) 0;
}
.maxWidth {
@@ -8,12 +8,12 @@
display: flex;
justify-content: space-between;
flex-direction: column;
max-width: var(--max-width-content);
max-width: var(--max-width-page);
}
@media screen and (min-width: 767px) {
.section {
padding: var(--Spacing-x9) var(--Spacing-x5);
padding: var(--Spacing-x9) 0;
}
}

View File

@@ -104,10 +104,11 @@
@media screen and (min-width: 768px) and (max-width: 1366px) {
.inputContainer {
padding: var(--Spacing-x2) var(--Spacing-x2);
padding: var(--Spacing-x2) var(--Spacing-x2) var(--Spacing-x2)
var(--Layout-Tablet-Margin-Margin-min);
}
.buttonContainer {
padding-right: var(--Spacing-x2);
padding-right: var(--Layout-Tablet-Margin-Margin-min);
}
.input .buttonContainer .button {
padding: var(--Spacing-x1);
@@ -125,7 +126,7 @@
display: flex;
background: var(--Base-Surface-Primary-light-Hover);
border-bottom: 1px solid var(--Primary-Light-On-Surface-Divider-subtle);
padding: var(--Spacing-x2);
padding: var(--Spacing-x2) var(--Layout-Tablet-Margin-Margin-min);
}
.voucherContainer {
display: none;

View File

@@ -2,15 +2,11 @@
align-items: center;
display: grid;
margin: 0 auto;
width: min(
calc(100dvw - (var(--Spacing-x2) * 2)),
var(--max-width-navigation)
);
width: 100dvw;
}
.form {
display: grid;
width: 100%;
}
@media screen and (max-width: 767px) {
@@ -20,11 +16,6 @@
}
@media screen and (min-width: 768px) {
.section {
display: flex;
width: 100%;
}
.default {
border-radius: var(--Corner-radius-Medium);
}
@@ -36,14 +27,12 @@
var(--Spacing-x-one-and-half) var(--Spacing-x1);
}
.section {
width: min(
calc(100dvw - (var(--Spacing-x2) * 2)),
var(--max-width-navigation)
);
}
.full {
padding: var(--Spacing-x1) 0;
}
.form {
width: 100%;
max-width: var(--max-width-page);
margin: 0 auto;
}
}

View File

@@ -6,7 +6,7 @@
background-color: transparent;
color: var(--Base-Text-High-contrast);
border-width: 0;
padding: var(--Spacing-x-half) var(--Spacing-x1);
padding: var(--Spacing-x-half) 0;
cursor: pointer;
font-family: var(--typography-Body-Bold-fontFamily);
font-weight: 500; /* Should be fixed when variables starts working: var(--typography-Body-Bold-fontWeight); */

View File

@@ -1,6 +1,6 @@
.mainMenu {
background-color: var(--Base-Surface-Primary-light-Normal);
padding: var(--Spacing-x2);
padding: var(--Spacing-x2) 0;
border-bottom: 1px solid var(--Primary-Light-On-Surface-Divider-subtle);
}
@@ -12,6 +12,8 @@
grid-template-columns: max-content 1fr;
align-items: center;
gap: var(--Spacing-x2);
max-width: var(--max-width-page);
margin: 0 auto;
}
.menus {
@@ -31,6 +33,9 @@
}
@media screen and (min-width: 768px) {
.mainMenu {
padding: var(--Spacing-x2) 0;
}
.nav {
display: flex;
justify-content: space-between;

View File

@@ -1,11 +1,11 @@
.topMenu {
display: none;
background-color: var(--Base-Surface-Subtle-Normal);
padding: var(--Spacing-x2);
padding: var(--Spacing-x2) 0;
}
.content {
max-width: var(--max-width-navigation);
max-width: var(--max-width-page);
margin: 0 auto;
}

View File

@@ -11,10 +11,12 @@
.bottomSheet {
display: grid;
grid-template-columns: 1fr auto;
padding: var(--Spacing-x2) var(--Spacing-x3) var(--Spacing-x5)
var(--Spacing-x3);
padding: var(--Spacing-x2) 0 var(--Spacing-x5);
align-items: flex-start;
transition: 0.5s ease-in-out;
max-width: var(--max-width-page);
width: 100%;
margin: 0 auto;
}
.priceDetailsButton {
@@ -25,6 +27,7 @@
transition: padding 0.5s ease-in-out;
cursor: pointer;
white-space: nowrap;
padding: 0;
}
.wrapper[data-open="true"] {
@@ -51,6 +54,12 @@
overflow: hidden;
}
@media screen and (min-width: 768px) {
.bottomSheet {
padding: var(--Spacing-x2) 0 var(--Spacing-x7);
}
}
@keyframes fadeIn {
from {
opacity: 0;

View File

@@ -37,7 +37,8 @@
.listingContainer {
background-color: var(--Base-Surface-Secondary-light-Normal);
padding: var(--Spacing-x3) var(--Spacing-x4);
padding: var(--Spacing-x3) var(--Spacing-x4) var(--Spacing-x3)
var(--Layout-Tablet-Margin-Margin-min);
overflow-y: auto;
min-width: 420px;
width: 420px;
@@ -59,3 +60,10 @@
gap: var(--Spacing-x2);
}
}
@media (min-width: 1367px) {
.listingContainer {
padding: var(--Spacing-x3) var(--Spacing-x4) var(--Spacing-x3)
var(--Layout-Desktop-Margin-Margin-min);
}
}

View File

@@ -12,15 +12,18 @@ export function SelectHotelSkeleton({ count = 4 }: Props) {
return (
<div className={styles.skeletonContainer}>
<header className={styles.header}>
<div className={styles.breadcrumbs}>
<SkeletonShimmer height={"25px"} width={"300px"} />
</div>
<div className={styles.title}>
<div className={styles.cityInformation}>
<SkeletonShimmer height={"25px"} width={"200px"} />
<div className={styles.headerContent}>
<div className={styles.breadcrumbs}>
<SkeletonShimmer height={"25px"} width={"300px"} />
</div>
<div className={styles.sorter}>
<SkeletonShimmer height={"60px"} width={"100%"} />
<div className={styles.title}>
<div className={styles.cityInformation}>
<SkeletonShimmer height={"25px"} width={"200px"} />
</div>
<div className={styles.sorter}>
<SkeletonShimmer height={"60px"} width={"100%"} />
</div>
</div>
</div>
</header>

View File

@@ -133,17 +133,19 @@ export default async function SelectHotel({
return (
<>
<header className={styles.header}>
<Breadcrumbs breadcrumbs={breadcrumbs} />
<div className={styles.title}>
<div className={styles.cityInformation}>
<Subtitle>{city.name}</Subtitle>
<HotelCount />
</div>
<div className={styles.sorter}>
<HotelSorter discreet />
<div className={styles.headerContent}>
<Breadcrumbs breadcrumbs={breadcrumbs} />
<div className={styles.title}>
<div className={styles.cityInformation}>
<Subtitle>{city.name}</Subtitle>
<HotelCount />
</div>
<div className={styles.sorter}>
<HotelSorter discreet />
</div>
</div>
<MobileMapButtonContainer filters={filterList} />
</div>
<MobileMapButtonContainer filters={filterList} />
</header>
<main className={styles.main}>
<div className={styles.sideBar}>

View File

@@ -1,21 +1,25 @@
.main {
display: flex;
padding: 0 var(--Spacing-x2) var(--Spacing-x3) var(--Spacing-x2);
background-color: var(--Scandic-Brand-Warm-White);
min-height: 100dvh;
flex-direction: column;
max-width: var(--max-width);
max-width: var(--max-width-page);
margin: 0 auto;
}
.header {
padding: var(--Spacing-x3) 0 var(--Spacing-x2);
}
.headerContent {
max-width: var(--max-width-page);
margin: 0 auto;
display: flex;
flex-direction: column;
gap: var(--Spacing-x2);
padding: var(--Spacing-x3) var(--Spacing-x2) 0 var(--Spacing-x2);
}
.header nav {
.headerContent nav {
display: none;
}
@@ -70,16 +74,18 @@
@media (min-width: 768px) {
.main {
padding: var(--Spacing-x5);
}
.header {
display: block;
background-color: var(--Base-Surface-Subtle-Normal);
padding: var(--Spacing-x4) var(--Spacing-x5) var(--Spacing-x3)
var(--Spacing-x5);
padding: var(--Spacing-x5) 0;
}
.header nav {
.headerContent {
display: block;
}
.header {
background-color: var(--Base-Surface-Subtle-Normal);
padding: var(--Spacing-x4) 0 var(--Spacing-x3);
}
.headerContent nav {
display: block;
max-width: var(--max-width-navigation);
padding: 0;

View File

@@ -1,12 +1,12 @@
.container {
background-color: var(--Base-Surface-Subtle-Normal);
padding: var(--Spacing-x3) var(--Spacing-x2);
padding: var(--Spacing-x3) 0;
}
.wrapper {
display: flex;
margin: 0 auto;
max-width: var(--max-width-navigation);
max-width: var(--max-width-page);
position: relative;
flex-direction: column;
gap: var(--Spacing-x2);
@@ -62,11 +62,17 @@
}
.hotelAlert {
max-width: var(--max-width-navigation);
max-width: var(--max-width-page);
margin: 0 auto;
padding-top: var(--Spacing-x-one-and-half);
}
@media screen and (min-width: 768px) {
.container {
padding: var(--Spacing-x4) 0;
}
}
@media screen and (min-width: 1367px) {
.container {
padding: var(--Spacing-x4) var(--Spacing-x5);

View File

@@ -13,7 +13,7 @@
.content {
width: 100%;
max-width: var(--max-width-navigation);
max-width: var(--max-width-page);
margin: 0 auto;
display: flex;
flex-direction: column;
@@ -29,7 +29,7 @@
display: flex;
flex-direction: row;
gap: var(--Spacing-x4);
padding: var(--Spacing-x2) var(--Spacing-x3) 0;
padding-top: var(--Spacing-x2);
width: 100%;
}
@@ -72,7 +72,7 @@
@media (min-width: 768px) {
.summary {
padding: var(--Spacing-x3) var(--Spacing-x7) var(--Spacing-x5);
padding: var(--Spacing-x3) 0 var(--Spacing-x5);
}
.content {
flex-direction: row;

View File

@@ -1,7 +1,6 @@
.container {
padding: var(--Spacing-x2);
margin: 0 auto;
max-width: var(--max-width);
max-width: var(--max-width-page);
}
.filterContainer {

View File

@@ -1,8 +1,8 @@
.content {
max-width: var(--max-width);
max-width: var(--max-width-page);
margin: 0 auto;
display: flex;
flex-direction: column;
gap: var(--Spacing-x2);
padding: var(--Spacing-x2);
padding: var(--Spacing-x2) 0;
}

View File

@@ -11,7 +11,7 @@
.content {
width: 100%;
max-width: var(--max-width-navigation);
max-width: var(--max-width-page);
margin: 0 auto;
display: flex;
gap: var(--Spacing-x2);
@@ -60,7 +60,6 @@
/* Intent: banner */
.banner {
padding: 0 var(--Spacing-x3);
border-left-width: 6px;
border-left-style: solid;
}
@@ -90,9 +89,6 @@
}
@media screen and (min-width: 768px) {
.banner {
padding: 0 var(--Spacing-x5);
}
.innerContent {
flex-direction: row;
align-items: center;

View File

@@ -1,17 +1,35 @@
.breadcrumbs {
display: block;
padding: var(--Spacing-x2) var(--Spacing-x2) 0;
max-width: var(--max-width);
padding: var(--Spacing-x4) 0 var(--Spacing-x3);
margin: 0 auto;
width: 100%;
}
.contentWidth.breadcrumbs {
background-color: var(--Base-Surface-Subtle-Normal);
padding-bottom: 0;
}
.hotelHeaderWidth.breadcrumbs {
max-width: min(var(--max-width-page), calc(100% - var(--max-width-spacing)));
}
.fullWidth .list {
max-width: var(--max-width-navigation);
}
.contentWidth .list {
max-width: var(--max-width-content);
}
.list {
align-items: center;
display: flex;
gap: var(--Spacing-x-quarter);
justify-content: flex-start;
list-style: none;
margin: 0 auto;
max-width: var(--max-width-page);
}
.listItem {
@@ -23,10 +41,3 @@
.homeLink {
display: flex;
}
@media screen and (min-width: 1367px) {
.breadcrumbs {
padding-left: var(--Spacing-x5);
padding-right: var(--Spacing-x5);
}
}

View File

@@ -1,9 +1,14 @@
import type { VariantProps } from "class-variance-authority"
import type { breadcrumbsVariants } from "./variants"
type Breadcrumb = {
title: string
uid: string
href?: string
}
export interface BreadcrumbsProps {
export interface BreadcrumbsProps
extends VariantProps<typeof breadcrumbsVariants> {
breadcrumbs: Breadcrumb[]
}

View File

@@ -3,18 +3,27 @@ import ChevronRightSmallIcon from "@/components/Icons/ChevronRightSmall"
import Link from "@/components/TempDesignSystem/Link"
import Footnote from "@/components/TempDesignSystem/Text/Footnote"
import { breadcrumbsVariants } from "./variants"
import styles from "./breadcrumbs.module.css"
import type { BreadcrumbsProps } from "@/components/TempDesignSystem/Breadcrumbs/breadcrumbs"
export default function Breadcrumbs({ breadcrumbs }: BreadcrumbsProps) {
export default function Breadcrumbs({
breadcrumbs,
variant,
}: BreadcrumbsProps) {
if (!breadcrumbs?.length) {
return null
}
const classNames = breadcrumbsVariants({
variant,
})
const homeBreadcrumb = breadcrumbs.shift()
return (
<nav className={styles.breadcrumbs}>
<nav className={classNames}>
<ul className={styles.list}>
{homeBreadcrumb ? (
<li className={styles.listItem}>

View File

@@ -0,0 +1,21 @@
import { cva } from "class-variance-authority"
import styles from "./breadcrumbs.module.css"
import { PageContentTypeEnum } from "@/types/requests/contentType"
export const breadcrumbsVariants = cva(styles.breadcrumbs, {
variants: {
variant: {
[PageContentTypeEnum.accountPage]: styles.fullWidth,
[PageContentTypeEnum.contentPage]: styles.contentWidth,
[PageContentTypeEnum.collectionPage]: styles.contentWidth,
[PageContentTypeEnum.hotelPage]: styles.hotelHeaderWidth,
[PageContentTypeEnum.loyaltyPage]: styles.fullWidth,
default: styles.fullWidth,
},
},
defaultVariants: {
variant: "default",
},
})