refactor(SW-1877): a bit of cleanup of code to maintain patterns and separate components and types

This commit is contained in:
Christian Andolf
2025-03-31 11:47:53 +02:00
parent 52b461fbb4
commit 19723856c3
6 changed files with 91 additions and 79 deletions

View File

@@ -3,13 +3,13 @@ import { serverClient } from "@/lib/trpc/server"
import BreadcrumbsComp from "@/components/TempDesignSystem/Breadcrumbs" import BreadcrumbsComp from "@/components/TempDesignSystem/Breadcrumbs"
import { generateBreadcrumbsSchema } from "@/utils/jsonSchemas" import { generateBreadcrumbsSchema } from "@/utils/jsonSchemas"
import type { Breadcrumbs } from "@/types/trpc/routers/contentstack/breadcrumbs"
import type { BreadcrumbsProps } from "@/components/TempDesignSystem/Breadcrumbs/breadcrumbs" import type { BreadcrumbsProps } from "@/components/TempDesignSystem/Breadcrumbs/breadcrumbs"
export default async function Breadcrumbs({ interface Props extends Pick<BreadcrumbsProps, "variant"> {
variant, subpageTitle?: string
subpageTitle, }
}: Pick<BreadcrumbsProps, "variant" | "subpageTitle">) {
export default async function Breadcrumbs({ variant, subpageTitle }: Props) {
const breadcrumbs = await serverClient().contentstack.breadcrumbs.get() const breadcrumbs = await serverClient().contentstack.breadcrumbs.get()
if (!breadcrumbs?.length) { if (!breadcrumbs?.length) {
return null return null

View File

@@ -0,0 +1,37 @@
import { cx } from "class-variance-authority"
import { Breadcrumb as AriaBreadcrumb } from "react-aria-components"
import { MaterialIcon } from "@scandic-hotels/design-system/Icons"
import Link from "@/components/TempDesignSystem/Link"
import styles from "./breadcrumbs.module.css"
import type { BreadcrumbProps } from "./breadcrumbs"
export function Breadcrumb({
className = "",
href,
children,
...props
}: BreadcrumbProps) {
return (
<AriaBreadcrumb className={cx(styles.listItem, className)} {...props}>
{href ? (
<>
<Link color="peach80" href={href} variant="breadcrumb">
{children}
</Link>
<MaterialIcon
icon="chevron_right"
size={20}
aria-hidden="true"
color="Icon/Interactive/Secondary"
/>
</>
) : (
children
)}
</AriaBreadcrumb>
)
}

View File

@@ -27,6 +27,12 @@
padding-inline-start: 0; padding-inline-start: 0;
} }
.list .listItem:last-of-type {
flex: 1;
max-width: 100%;
min-width: 0;
}
.listItem { .listItem {
align-items: center; align-items: center;
display: flex; display: flex;
@@ -43,19 +49,6 @@
flex-shrink: 0; flex-shrink: 0;
} }
.last {
flex: 1;
max-width: 100%;
min-width: 0;
}
.last > button {
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
text-align: left;
}
.button { .button {
border: none; border: none;
background: transparent; background: transparent;
@@ -103,6 +96,13 @@
} }
} }
.tooltipTrigger {
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
text-align: left;
}
.tooltip { .tooltip {
background-color: var(--Surface-UI-Fill-Intense); background-color: var(--Surface-UI-Fill-Intense);
padding: var(--Spacing-x-half) var(--Spacing-x1); padding: var(--Spacing-x-half) var(--Spacing-x1);

View File

@@ -1,15 +1,22 @@
import type { VariantProps } from "class-variance-authority" import type { VariantProps } from "class-variance-authority"
import type { PropsWithChildren } from "react"
import type { BreadcrumbProps as AriaBreadcrumbProps } from "react-aria-components"
import type { breadcrumbsVariants } from "./variants" import type { breadcrumbsVariants } from "./variants"
export type Breadcrumb = { export type { Breadcrumb, BreadcrumbProps, BreadcrumbsProps }
type Breadcrumb = {
title: string title: string
uid: string uid: string
href?: string href?: string
} }
export interface BreadcrumbsProps interface BreadcrumbsProps extends VariantProps<typeof breadcrumbsVariants> {
extends VariantProps<typeof breadcrumbsVariants> {
subpageTitle?: string
breadcrumbs: Breadcrumb[] breadcrumbs: Breadcrumb[]
} }
interface BreadcrumbProps extends PropsWithChildren<AriaBreadcrumbProps> {
className?: string
href?: string
}

View File

@@ -1,10 +1,9 @@
"use client" "use client"
import { cx } from "class-variance-authority" import { cx } from "class-variance-authority"
import { type PropsWithChildren, useEffect, useState } from "react" import { useEffect, useState } from "react"
import { import {
Breadcrumb as AriaBreadcrumb, Breadcrumbs as AriaBreadcrumbs,
Breadcrumbs as AriaBreadCrumbs,
Button, Button,
Dialog, Dialog,
DialogTrigger, DialogTrigger,
@@ -15,19 +14,18 @@ import {
import { MaterialIcon } from "@scandic-hotels/design-system/Icons" import { MaterialIcon } from "@scandic-hotels/design-system/Icons"
import { Typography } from "@scandic-hotels/design-system/Typography" import { Typography } from "@scandic-hotels/design-system/Typography"
import Link from "@/components/TempDesignSystem/Link"
import Footnote from "@/components/TempDesignSystem/Text/Footnote"
import { debounce } from "@/utils/debounce" import { debounce } from "@/utils/debounce"
import Link from "../Link"
import { Arrow } from "../Popover/Arrow" import { Arrow } from "../Popover/Arrow"
import Footnote from "../Text/Footnote"
import { Breadcrumb } from "./Breadcrumb"
import { splitBreadcrumbs } from "./utils"
import { breadcrumbsVariants } from "./variants" import { breadcrumbsVariants } from "./variants"
import styles from "./breadcrumbs.module.css" import styles from "./breadcrumbs.module.css"
import type { import type { BreadcrumbsProps } from "./breadcrumbs"
Breadcrumb,
BreadcrumbsProps,
} from "@/components/TempDesignSystem/Breadcrumbs/breadcrumbs"
export default function Breadcrumbs({ export default function Breadcrumbs({
breadcrumbs, breadcrumbs,
@@ -69,7 +67,7 @@ export default function Breadcrumbs({
return ( return (
<nav aria-label="Breadcrumbs" className={classNames}> <nav aria-label="Breadcrumbs" className={classNames}>
<AriaBreadCrumbs className={styles.list}> <AriaBreadcrumbs className={styles.list}>
<Breadcrumb <Breadcrumb
href={homeBreadcrumb.href} href={homeBreadcrumb.href}
aria-label={homeBreadcrumb.title} aria-label={homeBreadcrumb.title}
@@ -85,10 +83,10 @@ export default function Breadcrumbs({
> >
{remainingBreadcrumbs[0].title} {remainingBreadcrumbs[0].title}
</Breadcrumb> </Breadcrumb>
<AriaBreadcrumb className={cx(styles.listItem, styles.mobile)}> <Breadcrumb className={styles.mobile}>
<DialogTrigger> <DialogTrigger>
<Footnote color="burgundy" type="bold" asChild> <Footnote color="burgundy" type="bold" asChild>
<Button className={styles.button}>...</Button> <Button className={styles.button}></Button>
</Footnote> </Footnote>
<Popover> <Popover>
<Dialog className={styles.dialog}> <Dialog className={styles.dialog}>
@@ -111,7 +109,7 @@ export default function Breadcrumbs({
aria-hidden="true" aria-hidden="true"
color="Icon/Interactive/Secondary" color="Icon/Interactive/Secondary"
/> />
</AriaBreadcrumb> </Breadcrumb>
</> </>
) : ( ) : (
remainingBreadcrumbs.map((breadcrumb) => ( remainingBreadcrumbs.map((breadcrumb) => (
@@ -133,7 +131,7 @@ export default function Breadcrumbs({
<DialogTrigger> <DialogTrigger>
<Footnote color="burgundy" type="bold" asChild> <Footnote color="burgundy" type="bold" asChild>
<Button <Button
className={styles.button} className={cx(styles.button, styles.tooltipTrigger)}
ref={attachRef} ref={attachRef}
isDisabled={isTooltipDisabled} isDisabled={isTooltipDisabled}
> >
@@ -152,49 +150,7 @@ export default function Breadcrumbs({
</Popover> </Popover>
</DialogTrigger> </DialogTrigger>
</Breadcrumb> </Breadcrumb>
</AriaBreadCrumbs> </AriaBreadcrumbs>
</nav> </nav>
) )
} }
function Breadcrumb({
className = "",
href,
children,
...props
}: PropsWithChildren<{
className?: string
href?: string
}>) {
return (
<AriaBreadcrumb
className={cx(styles.listItem, { [styles.last]: !href }, className)}
{...props}
>
{href ? (
<>
<Link color="peach80" href={href} variant="breadcrumb">
{children}
</Link>
<MaterialIcon
icon="chevron_right"
size={20}
aria-hidden="true"
color="Icon/Interactive/Secondary"
/>
</>
) : (
children
)}
</AriaBreadcrumb>
)
}
function splitBreadcrumbs(
breadcrumbs: Breadcrumb[]
): [Breadcrumb, Breadcrumb[], Breadcrumb] {
const copy = breadcrumbs.slice(0)
const first = copy.shift()!
const last = copy.pop()!
return [first, copy, last]
}

View File

@@ -0,0 +1,12 @@
import type { Breadcrumb } from "./breadcrumbs"
export { splitBreadcrumbs }
function splitBreadcrumbs(
breadcrumbs: Breadcrumb[]
): [Breadcrumb, Breadcrumb[], Breadcrumb] {
const copy = breadcrumbs.slice(0)
const first = copy.shift()!
const last = copy.pop()!
return [first, copy, last]
}