Files
web/packages/design-system/lib/components/TeaserCard/TeaserCard.stories.tsx
2026-01-21 07:50:43 +00:00

344 lines
8.5 KiB
TypeScript

import type { Meta, StoryObj } from "@storybook/nextjs-vite"
import { TeaserCard } from "./TeaserCard.tsx"
import { config } from "./variants.ts"
const PRIMARY_BUTTON = {
title: "Primary action",
href: "#",
openInNewTab: false,
}
const SECONDARY_BUTTON = {
...PRIMARY_BUTTON,
title: "Secondary action",
}
const SIDEPEEK_CONTENT = {
heading: "Sidepeek heading",
content: {
json: {
type: "doc",
attrs: {},
uid: "8126b570ffef4090a78f8c863d73c3b8",
children: [
{
type: "p",
attrs: {},
uid: "ed82964e32764cf589e07a251014543b",
children: [
{
text: "Lorem ipsum dolor sit amet, consectetur adipiscing elit. Curabitur vitae neque non ipsum efficitur hendrerit at ut nulla. Cras in tellus et ligula posuere ullamcorper. Praesent pulvinar rutrum metus ut gravida.",
},
],
},
{
type: "h3",
attrs: {},
uid: "799903bc123d479d9bcf29cb4ba24b65",
children: [
{
text: "Lorem ipsum",
},
],
},
{
type: "p",
attrs: {},
uid: "00886e5b0a5d4268930a1472b58e9170",
children: [
{
text: "Lorem ipsum dolor sit amet, consectetur adipiscing elit. Curabitur vitae neque non ipsum efficitur hendrerit at ut nulla. Cras in tellus et ligula posuere ullamcorper. Praesent pulvinar rutrum metus ut gravida.",
},
],
},
{
type: "p",
attrs: {},
uid: "6bd20356e8bd4612a99e1af6061f861c",
children: [
{
text: "",
},
{
uid: "28e963603b714055b948a038539bfd98",
type: "a",
attrs: {
url: "https://www.scandichotels.com/en",
target: "_blank",
},
children: [
{
text: "Learn more about this",
},
],
},
{
text: "",
},
],
},
{
type: "h3",
attrs: {},
uid: "9db195292c5b49ac970edc8b4be19081",
children: [
{
text: "Dolor sit amet",
},
],
},
{
type: "p",
attrs: {},
uid: "f45861b9146040ff8a6076cc2bc4d218",
children: [
{
text: "Lorem ipsum dolor sit amet, consectetur adipiscing elit. Curabitur vitae neque non ipsum efficitur hendrerit at ut nulla. Cras in tellus et ligula posuere ullamcorper. Praesent pulvinar rutrum metus ut gravida.",
},
],
},
{
uid: "a40eb77a4c26401689255e0caa2f564a",
type: "ul",
children: [
{
type: "li",
attrs: {},
uid: "701d76e63827483cb80180056d1b396e",
children: [
{
text: "Lorem ipsum",
id: "",
},
],
},
{
type: "li",
attrs: {},
uid: "f3f28b61c4b54162a7c723995a38a063",
children: [
{
text: "Dolor sit amet consectetur adipiscing elit.",
id: "",
},
],
},
{
type: "li",
attrs: {},
uid: "27f51d6ad42e4dafb5037b5ee790f0b2",
children: [
{
text: "Curabitur vitae neque non ipsum efficitur",
id: "",
},
],
},
],
attrs: {},
},
],
_version: 16,
},
embedded_itemsConnection: {
edges: [],
},
},
primary_button: {
title: "Sidepeek primary action",
href: "#",
openInNewTab: false,
},
}
const DEFAULT_ARGS = {
heading: "Lorem ipsum",
bodyText:
"Dolor sit amet, consectetur adipiscing elit. Curabitur vitae neque non ipsum efficitur hendrerit at ut nulla.",
image: {
id: 1,
url: "./img/img2.jpg",
title: "Placeholder image",
meta: {
alt: "Placeholder image",
caption: "This is a placeholder image",
},
focalPoint: { x: 50, y: 50 },
dimensions: { width: 1920, height: 1189, aspectRatio: 1.61 },
},
primaryButton: PRIMARY_BUTTON,
secondaryButton: SECONDARY_BUTTON,
alwaysStack: false,
}
const meta: Meta<typeof TeaserCard> = {
title: "Core Components/Cards/TeaserCard",
parameters: {
docs: {
description: {
component:
"The card itself does not have a maximum width, but it will adapt to the width of its container. The card is mostly used together with other content cards. It is recommended to use the ContentCard inside a grid or a container with a set maximum width for best results.",
},
},
},
component: TeaserCard,
argTypes: {
heading: {
control: "text",
table: {
type: { summary: "string" },
},
},
bodyText: {
control: "text",
table: {
type: { summary: "string" },
},
},
primaryButton: {
control: "object",
table: {
type: {
summary:
"{ title: string, href: string, openInNewTab?: boolean, onPress?: () => void } | undefined",
},
},
},
secondaryButton: {
control: "object",
table: {
type: {
summary:
"{ title: string, href: string, openInNewTab?: boolean, onPress?: () => void } | undefined",
},
},
},
sidePeekButton: {
control: "object",
table: {
type: {
summary: "{ call_to_action_text: string } | undefined",
},
},
},
sidePeekContent: {
control: "object",
table: {
type: {
summary: "any | undefined",
},
},
},
image: {
control: "object",
table: {
type: {
summary: "ImageVaultAsset | undefined",
detail:
"{ id: number, url: string, meta: {alt?: string | null, caption?: string | null}, focalPoint: { x: number, y: number }, dimensions: { width: number, height: number, aspectRatio: number } }",
},
},
},
style: {
control: "select",
options: Object.keys(config.variants.style),
table: {
type: { summary: Object.keys(config.variants.style).join(" | ") },
},
defaultValue: config.defaultVariants.style,
},
alwaysStack: {
control: "boolean",
table: {
type: { summary: "boolean" },
},
defaultValue: config.defaultVariants.alwaysStack.toString(),
description:
"If true, the buttons will always be stacked vertically, regardless if these would fit next to each other.",
},
},
args: { ...DEFAULT_ARGS },
globals: {
backgrounds: { default: "storybookLight" },
},
decorators: [
(Story, context) => {
const showMultipleStyles = [
"with sidepeek",
"without image",
"always stack buttons",
].some((substring) => context.name.toLowerCase().includes(substring))
if (showMultipleStyles) {
return (
<div
style={{
display: "grid",
gap: "1em",
gridTemplateColumns: `repeat(${Object.keys(config.variants.style).length}, 400px)`,
}}
>
{Object.keys(config.variants.style).map((style, ix) => {
return (
<TeaserCard
key={ix}
{...context.args}
style={style as keyof typeof config.variants.style}
/>
)
})}
</div>
)
}
return (
<div style={{ maxWidth: "400px" }}>
<Story />
</div>
)
},
],
}
export default meta
type Story = StoryObj<typeof TeaserCard>
export const Default: Story = {
args: {
...meta.args,
},
}
export const Featured: Story = {
args: {
...meta.args,
style: "featured",
},
}
export const WithSidepeek: Story = {
args: {
...meta.args,
sidePeekButton: {
call_to_action_text: "Side peek action",
},
sidePeekContent: SIDEPEEK_CONTENT,
style: "featured",
},
}
export const WithoutImage: Story = {
args: {
...meta.args,
image: undefined,
},
}
export const AlwaysStackButtons: Story = {
args: {
...meta.args,
alwaysStack: true,
},
}