diff --git a/apps/scandic-web/components/Blocks/UspGrid/index.tsx b/apps/scandic-web/components/Blocks/UspGrid/index.tsx
index 54c7b674b..85f15d3d0 100644
--- a/apps/scandic-web/components/Blocks/UspGrid/index.tsx
+++ b/apps/scandic-web/components/Blocks/UspGrid/index.tsx
@@ -1,18 +1,10 @@
-import { IconByIconName } from "@scandic-hotels/design-system/Icons/IconByIconName"
-import { JsonToHtml } from "@scandic-hotels/design-system/JsonToHtml"
-
-import { getUspIconName } from "./utils"
+import { UspCard } from "@scandic-hotels/design-system/UspCard"
import styles from "./uspgrid.module.css"
-import type { UspGridProps, UspIcon } from "@/types/components/blocks/uspGrid"
+import type { UspGrid as UspGridType } from "@scandic-hotels/trpc/types/blocks"
-function UspIcon({ icon }: { icon: UspIcon }) {
- const iconName = getUspIconName(icon)
- return iconName ? (
-
- ) : null
-}
+interface UspGridProps extends Pick {}
export default function UspGrid({ usp_grid }: UspGridProps) {
return (
@@ -20,13 +12,13 @@ export default function UspGrid({ usp_grid }: UspGridProps) {
{usp_grid.usp_card.map(
(usp) =>
usp.text.json && (
-
-
-
-
+
)
)}
diff --git a/apps/scandic-web/components/Blocks/UspGrid/uspgrid.module.css b/apps/scandic-web/components/Blocks/UspGrid/uspgrid.module.css
index 7eeb99e19..71682ea13 100644
--- a/apps/scandic-web/components/Blocks/UspGrid/uspgrid.module.css
+++ b/apps/scandic-web/components/Blocks/UspGrid/uspgrid.module.css
@@ -3,17 +3,12 @@
gap: var(--Space-x3);
}
-.usp {
- display: grid;
- gap: var(--Space-x3);
- align-content: start;
-}
-
@media screen and (min-width: 768px) {
.grid {
grid-template-columns: repeat(2, 1fr);
}
- .grid:has(.usp:nth-child(3)):not(:has(.usp:nth-child(4))) {
+
+ .grid:has(.uspCard:nth-child(3)):not(:has(.uspCard:nth-child(4))) {
grid-template-columns: repeat(3, 1fr);
}
}
diff --git a/apps/scandic-web/types/components/blocks/uspGrid.ts b/apps/scandic-web/types/components/blocks/uspGrid.ts
deleted file mode 100644
index 4db708283..000000000
--- a/apps/scandic-web/types/components/blocks/uspGrid.ts
+++ /dev/null
@@ -1,4 +0,0 @@
-import type { UspGrid } from "@scandic-hotels/trpc/types/blocks"
-
-export interface UspGridProps extends Pick {}
-export type UspIcon = UspGrid["usp_grid"]["usp_card"][number]["icon"]
diff --git a/packages/design-system/lib/components/InfoCard/InfoCard.stories.tsx b/packages/design-system/lib/components/InfoCard/InfoCard.stories.tsx
index 1efe32dcd..e04d1c8f0 100644
--- a/packages/design-system/lib/components/InfoCard/InfoCard.stories.tsx
+++ b/packages/design-system/lib/components/InfoCard/InfoCard.stories.tsx
@@ -20,7 +20,7 @@ const DEFAULT_ARGS = {
}
const meta: Meta = {
- title: "Product Components/InfoCard",
+ title: "Core Components/Cards/InfoCard",
component: InfoCard,
argTypes: {
topTitle: {
diff --git a/packages/design-system/lib/components/UspCard/UspCard.stories.tsx b/packages/design-system/lib/components/UspCard/UspCard.stories.tsx
new file mode 100644
index 000000000..3c7fc8dab
--- /dev/null
+++ b/packages/design-system/lib/components/UspCard/UspCard.stories.tsx
@@ -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 = {
+ 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[]" },
+ },
+ },
+ 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
+ }
+
+ return (
+
+
+
+ )
+ },
+ ],
+}
+
+export default meta
+
+type Story = StoryObj
+
+export const Default: Story = {
+ args: {
+ ...meta.args,
+ },
+}
+
+export const MultipleCards: Story = {
+ args: {
+ ...meta.args,
+ },
+ render: (args) => (
+
+
+
+
+
+ ),
+}
+
+export const DifferentIcons: Story = {
+ args: {
+ ...meta.args,
+ },
+ render: (args) => (
+
+
+
+
+
+ ),
+}
diff --git a/packages/design-system/lib/components/UspCard/UspCard.tsx b/packages/design-system/lib/components/UspCard/UspCard.tsx
new file mode 100644
index 000000000..1e85fcd3f
--- /dev/null
+++ b/packages/design-system/lib/components/UspCard/UspCard.tsx
@@ -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 {
+ iconName?: UspIconName | null
+ embeds: Node[]
+ nodes: RTENode[]
+}
+
+export function UspCard({
+ className,
+ iconName,
+ embeds,
+ nodes,
+ ...props
+}: UspCardProps) {
+ const resolvedIconName = getUspIconName(iconName)
+
+ return (
+
+
+
+
+ )
+}
diff --git a/packages/design-system/lib/components/UspCard/index.tsx b/packages/design-system/lib/components/UspCard/index.tsx
new file mode 100644
index 000000000..7e38231e6
--- /dev/null
+++ b/packages/design-system/lib/components/UspCard/index.tsx
@@ -0,0 +1 @@
+export { UspCard } from "./UspCard"
diff --git a/packages/design-system/lib/components/UspCard/uspCard.module.css b/packages/design-system/lib/components/UspCard/uspCard.module.css
new file mode 100644
index 000000000..441414559
--- /dev/null
+++ b/packages/design-system/lib/components/UspCard/uspCard.module.css
@@ -0,0 +1,9 @@
+.uspCard {
+ display: grid;
+ gap: var(--Space-x3);
+ align-content: start;
+}
+
+.icon {
+ justify-self: start;
+}
diff --git a/apps/scandic-web/components/Blocks/UspGrid/utils.ts b/packages/design-system/lib/components/UspCard/utils.ts
similarity index 70%
rename from apps/scandic-web/components/Blocks/UspGrid/utils.ts
rename to packages/design-system/lib/components/UspCard/utils.ts
index a880107d6..1df1ec49c 100644
--- a/apps/scandic-web/components/Blocks/UspGrid/utils.ts
+++ b/packages/design-system/lib/components/UspCard/utils.ts
@@ -1,9 +1,35 @@
-import { IconName } from "@scandic-hotels/design-system/Icons/iconName"
+import { IconName } from "../Icons/iconName"
-import type { UspIcon } from "@/types/components/blocks/uspGrid"
+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 function getUspIconName(icon?: UspIcon | null) {
- switch (icon) {
+export type UspIconName = (typeof USP_ICON_NAMES)[number]
+
+export function getUspIconName(iconName?: UspIconName | null) {
+ switch (iconName) {
case "Snowflake":
return IconName.Snowflake
case "Information":
diff --git a/packages/design-system/package.json b/packages/design-system/package.json
index 251dd3f8e..9d69e1e7c 100644
--- a/packages/design-system/package.json
+++ b/packages/design-system/package.json
@@ -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",