feat(BOOK-768): Added UspCard component with stories and implemented it in blocks
Approved-by: Bianca Widstam
This commit is contained in:
@@ -20,7 +20,7 @@ const DEFAULT_ARGS = {
|
||||
}
|
||||
|
||||
const meta: Meta<typeof InfoCard> = {
|
||||
title: "Product Components/InfoCard",
|
||||
title: "Core Components/Cards/InfoCard",
|
||||
component: InfoCard,
|
||||
argTypes: {
|
||||
topTitle: {
|
||||
|
||||
@@ -0,0 +1,132 @@
|
||||
import type { Meta, StoryObj } from "@storybook/nextjs-vite"
|
||||
|
||||
import { RTETypeEnum } from "../JsonToHtml/types/rte/enums"
|
||||
import type { RTENode } from "../JsonToHtml/types/rte/node"
|
||||
import { UspCard } from "./UspCard"
|
||||
import { USP_ICON_NAMES } from "./utils"
|
||||
|
||||
const DEFAULT_ARGS = {
|
||||
nodes: [
|
||||
{
|
||||
uid: "paragraph",
|
||||
attrs: { type: "asset" },
|
||||
type: RTETypeEnum.p,
|
||||
children: [
|
||||
{
|
||||
text: "Lorem ipsum dolor sit amet, consectetur adipiscing elit. Curabitur vitae neque non ipsum efficitur hendrerit at ut nulla.",
|
||||
},
|
||||
],
|
||||
},
|
||||
] satisfies RTENode[],
|
||||
embeds: [],
|
||||
}
|
||||
|
||||
const meta: Meta<typeof UspCard> = {
|
||||
title: "Core Components/Cards/UspCard",
|
||||
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 should be used together with other usp cards. It is recommended to use the UspCard inside a grid or a container with a set maximum width for best results.",
|
||||
},
|
||||
},
|
||||
},
|
||||
component: UspCard,
|
||||
argTypes: {
|
||||
iconName: {
|
||||
control: "select",
|
||||
options: USP_ICON_NAMES,
|
||||
table: {
|
||||
type: {
|
||||
summary: USP_ICON_NAMES.join(" | "),
|
||||
},
|
||||
defaultValue: { summary: "Snowflake" },
|
||||
},
|
||||
},
|
||||
embeds: {
|
||||
control: "object",
|
||||
description:
|
||||
"The embeds used by the JsonToHtml component to render rich text content. This data comes from the RTE field in the CMS.",
|
||||
table: {
|
||||
type: { summary: "Node<Embeds>[]" },
|
||||
},
|
||||
},
|
||||
nodes: {
|
||||
control: "object",
|
||||
description:
|
||||
"The nodes used by the JsonToHtml component to render rich text content. This data comes from the RTE field in the CMS.",
|
||||
table: {
|
||||
type: { summary: "RTENode[]" },
|
||||
},
|
||||
},
|
||||
},
|
||||
args: { ...DEFAULT_ARGS },
|
||||
decorators: [
|
||||
(Story, context) => {
|
||||
const showMultipleStyles = ["multiple cards", "different icons"].some(
|
||||
(substring) => context.name.toLowerCase().includes(substring)
|
||||
)
|
||||
if (showMultipleStyles) {
|
||||
return <Story />
|
||||
}
|
||||
|
||||
return (
|
||||
<div style={{ maxWidth: "400px" }}>
|
||||
<Story />
|
||||
</div>
|
||||
)
|
||||
},
|
||||
],
|
||||
}
|
||||
|
||||
export default meta
|
||||
|
||||
type Story = StoryObj<typeof UspCard>
|
||||
|
||||
export const Default: Story = {
|
||||
args: {
|
||||
...meta.args,
|
||||
},
|
||||
}
|
||||
|
||||
export const MultipleCards: Story = {
|
||||
args: {
|
||||
...meta.args,
|
||||
},
|
||||
render: (args) => (
|
||||
<div
|
||||
style={{
|
||||
display: "grid",
|
||||
gridTemplateColumns: "repeat(3, 1fr)",
|
||||
gap: "16px",
|
||||
width: "min(800px, 100%)",
|
||||
margin: "0 auto",
|
||||
}}
|
||||
>
|
||||
<UspCard {...args} />
|
||||
<UspCard {...args} />
|
||||
<UspCard {...args} />
|
||||
</div>
|
||||
),
|
||||
}
|
||||
|
||||
export const DifferentIcons: Story = {
|
||||
args: {
|
||||
...meta.args,
|
||||
},
|
||||
render: (args) => (
|
||||
<div
|
||||
style={{
|
||||
display: "grid",
|
||||
gridTemplateColumns: "repeat(3, 1fr)",
|
||||
gap: "16px",
|
||||
width: "min(800px, 100%)",
|
||||
margin: "0 auto",
|
||||
}}
|
||||
>
|
||||
<UspCard {...args} iconName={USP_ICON_NAMES[0]} />
|
||||
<UspCard {...args} iconName={USP_ICON_NAMES[1]} />
|
||||
<UspCard {...args} iconName={USP_ICON_NAMES[2]} />
|
||||
</div>
|
||||
),
|
||||
}
|
||||
36
packages/design-system/lib/components/UspCard/UspCard.tsx
Normal file
36
packages/design-system/lib/components/UspCard/UspCard.tsx
Normal file
@@ -0,0 +1,36 @@
|
||||
import { cx } from "class-variance-authority"
|
||||
|
||||
import { IconByIconName } from "../Icons/IconByIconName"
|
||||
import { type Embeds, JsonToHtml, type Node } from "../JsonToHtml/JsonToHtml"
|
||||
import type { RTENode } from "../JsonToHtml/types/rte/node"
|
||||
import { getUspIconName, UspIconName } from "./utils"
|
||||
|
||||
import styles from "./uspCard.module.css"
|
||||
|
||||
interface UspCardProps extends React.HTMLAttributes<HTMLDivElement> {
|
||||
iconName?: UspIconName | null
|
||||
embeds: Node<Embeds>[]
|
||||
nodes: RTENode[]
|
||||
}
|
||||
|
||||
export function UspCard({
|
||||
className,
|
||||
iconName,
|
||||
embeds,
|
||||
nodes,
|
||||
...props
|
||||
}: UspCardProps) {
|
||||
const resolvedIconName = getUspIconName(iconName)
|
||||
|
||||
return (
|
||||
<div className={cx(styles.uspCard, className)} {...props}>
|
||||
<IconByIconName
|
||||
className={styles.icon}
|
||||
iconName={resolvedIconName}
|
||||
color="Icon/Interactive/Accent"
|
||||
size={48}
|
||||
/>
|
||||
<JsonToHtml embeds={embeds} nodes={nodes} />
|
||||
</div>
|
||||
)
|
||||
}
|
||||
1
packages/design-system/lib/components/UspCard/index.tsx
Normal file
1
packages/design-system/lib/components/UspCard/index.tsx
Normal file
@@ -0,0 +1 @@
|
||||
export { UspCard } from "./UspCard"
|
||||
@@ -0,0 +1,9 @@
|
||||
.uspCard {
|
||||
display: grid;
|
||||
gap: var(--Space-x3);
|
||||
align-content: start;
|
||||
}
|
||||
|
||||
.icon {
|
||||
justify-self: start;
|
||||
}
|
||||
82
packages/design-system/lib/components/UspCard/utils.ts
Normal file
82
packages/design-system/lib/components/UspCard/utils.ts
Normal file
@@ -0,0 +1,82 @@
|
||||
import { IconName } from "../Icons/iconName"
|
||||
|
||||
export const USP_ICON_NAMES = [
|
||||
"Snowflake",
|
||||
"Information",
|
||||
"Heart",
|
||||
"WiFi",
|
||||
"Breakfast",
|
||||
"Checkbox",
|
||||
"Ticket",
|
||||
"Hotel",
|
||||
"Bed",
|
||||
"Train",
|
||||
"Airplane",
|
||||
"Sun",
|
||||
"Star",
|
||||
"Sports",
|
||||
"Gym",
|
||||
"Hiking",
|
||||
"Skiing",
|
||||
"City",
|
||||
"Pool",
|
||||
"Spa",
|
||||
"Bar",
|
||||
"Restaurant",
|
||||
"Child",
|
||||
] as const
|
||||
|
||||
export type UspIconName = (typeof USP_ICON_NAMES)[number]
|
||||
|
||||
export function getUspIconName(iconName?: UspIconName | null) {
|
||||
switch (iconName) {
|
||||
case "Snowflake":
|
||||
return IconName.Snowflake
|
||||
case "Information":
|
||||
return IconName.InfoCircle
|
||||
case "Heart":
|
||||
return IconName.Heart
|
||||
case "WiFi":
|
||||
return IconName.Wifi
|
||||
case "Breakfast":
|
||||
return IconName.Breakfast
|
||||
case "Checkbox":
|
||||
return IconName.Check
|
||||
case "Ticket":
|
||||
return IconName.Ticket
|
||||
case "Hotel":
|
||||
return IconName.City
|
||||
case "Bed":
|
||||
return IconName.NightShelter
|
||||
case "Train":
|
||||
return IconName.Ticket
|
||||
case "Airplane":
|
||||
return IconName.Airplane
|
||||
case "Sun":
|
||||
return IconName.Beach
|
||||
case "Star":
|
||||
return IconName.AwardStar
|
||||
case "Sports":
|
||||
return IconName.Sports
|
||||
case "Gym":
|
||||
return IconName.Fitness
|
||||
case "Hiking":
|
||||
return IconName.Hiking
|
||||
case "Skiing":
|
||||
return IconName.Skiing
|
||||
case "City":
|
||||
return IconName.City
|
||||
case "Pool":
|
||||
return IconName.Swim
|
||||
case "Spa":
|
||||
return IconName.Spa
|
||||
case "Bar":
|
||||
return IconName.Nightlife
|
||||
case "Restaurant":
|
||||
return IconName.Restaurant
|
||||
case "Child":
|
||||
return IconName.ExtraFamilyFriendly
|
||||
default:
|
||||
return IconName.Snowflake
|
||||
}
|
||||
}
|
||||
@@ -188,6 +188,7 @@
|
||||
"./Tooltip": "./lib/components/Tooltip/index.tsx",
|
||||
"./TripAdvisorChip": "./lib/components/TripAdvisorChip/index.tsx",
|
||||
"./Typography": "./lib/components/Typography/index.tsx",
|
||||
"./UspCard": "./lib/components/UspCard/index.tsx",
|
||||
"./VideoPlayer": "./lib/components/VideoPlayer/index.tsx",
|
||||
"./VideoWithCard": "./lib/components/VideoPlayer/VideoWithCard/index.tsx",
|
||||
"./design-system-new-deprecated.css": "./lib/design-system-new-deprecated.css",
|
||||
|
||||
Reference in New Issue
Block a user