feat(BOOK-757): Moved TeaserCard to design system and added stories
Approved-by: Bianca Widstam
This commit is contained in:
@@ -9,13 +9,3 @@ export const AlertVisibleOnEnum = {
|
||||
WEB: "WEB",
|
||||
APP: "APP",
|
||||
} as const
|
||||
|
||||
export type SidepeekContent = {
|
||||
heading: string
|
||||
content: {
|
||||
json?: any
|
||||
embedded_itemsConnection: {
|
||||
edges: any
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -30,6 +30,7 @@
|
||||
"./constants/rateType": "./constants/rateType.ts",
|
||||
"./constants/routes/*": "./constants/routes/*.ts",
|
||||
"./constants/sessionKeys": "./constants/sessionKeys.ts",
|
||||
"./constants/sidepeekContent": "./constants/sidepeekContent.ts",
|
||||
"./constants/signatureHotels": "./constants/signatureHotels.ts",
|
||||
"./constants/transactionType": "./constants/transactionType.ts",
|
||||
"./dataCache": "./dataCache/index.ts",
|
||||
|
||||
@@ -42,8 +42,8 @@ export default function AlertSidepeek({
|
||||
})}
|
||||
>
|
||||
<JsonToHtml
|
||||
nodes={content.json.children}
|
||||
embeds={content.embedded_itemsConnection.edges}
|
||||
nodes={content?.json.children}
|
||||
embeds={content?.embedded_itemsConnection.edges}
|
||||
/>
|
||||
</SidePeek>
|
||||
</div>
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import type { SidepeekContent } from "@scandic-hotels/common/constants/alert"
|
||||
import { AlertSidepeekContent } from "../../../types/sidepeekContent"
|
||||
|
||||
export interface AlertSidepeekProps {
|
||||
ctaText: string
|
||||
sidePeekContent: NonNullable<SidepeekContent>
|
||||
sidePeekContent: NonNullable<AlertSidepeekContent>
|
||||
}
|
||||
|
||||
@@ -1,10 +1,8 @@
|
||||
import type {
|
||||
AlertTypeEnum,
|
||||
SidepeekContent,
|
||||
} from "@scandic-hotels/common/constants/alert"
|
||||
import type { AlertTypeEnum } from "@scandic-hotels/common/constants/alert"
|
||||
import type { VariantProps } from "class-variance-authority"
|
||||
import type { AriaRole, ReactNode } from "react"
|
||||
|
||||
import { AlertSidepeekContent } from "../../types/sidepeekContent"
|
||||
import type { alertVariants } from "./variants"
|
||||
|
||||
export interface AlertProps extends VariantProps<typeof alertVariants> {
|
||||
@@ -17,7 +15,7 @@ export interface AlertProps extends VariantProps<typeof alertVariants> {
|
||||
phoneNumber?: string
|
||||
footnote?: string | null
|
||||
} | null
|
||||
sidepeekContent?: SidepeekContent | null
|
||||
sidepeekContent?: AlertSidepeekContent | null
|
||||
sidepeekCtaText?: string | null
|
||||
link?: {
|
||||
url: string
|
||||
|
||||
@@ -0,0 +1,83 @@
|
||||
"use client"
|
||||
|
||||
import { useState } from "react"
|
||||
import { useIntl } from "react-intl"
|
||||
|
||||
import { TeaserCardSidepeekContent } from "../../../types/sidepeekContent"
|
||||
import { Button } from "../../Button"
|
||||
import ButtonLink from "../../ButtonLink"
|
||||
import { MaterialIcon } from "../../Icons/MaterialIcon"
|
||||
import { JsonToHtml } from "../../JsonToHtml/JsonToHtml"
|
||||
import SidePeek from "../../SidePeek"
|
||||
import styles from "./sidepeek.module.css"
|
||||
|
||||
interface TeaserCardSidepeekProps {
|
||||
button: {
|
||||
call_to_action_text: string
|
||||
}
|
||||
sidePeekContent: TeaserCardSidepeekContent
|
||||
}
|
||||
|
||||
export default function TeaserCardSidepeek({
|
||||
button,
|
||||
sidePeekContent,
|
||||
}: TeaserCardSidepeekProps) {
|
||||
const intl = useIntl()
|
||||
const [sidePeekIsOpen, setSidePeekIsOpen] = useState(false)
|
||||
const { heading, content, primary_button, secondary_button } = sidePeekContent
|
||||
|
||||
return (
|
||||
<div className={styles.teaserCardSidepeek}>
|
||||
<Button
|
||||
onPress={() => setSidePeekIsOpen(true)}
|
||||
variant="Secondary"
|
||||
color="Primary"
|
||||
size="sm"
|
||||
>
|
||||
{button.call_to_action_text}
|
||||
<MaterialIcon icon="chevron_right" size={20} color="CurrentColor" />
|
||||
</Button>
|
||||
<SidePeek
|
||||
title={heading}
|
||||
isOpen={sidePeekIsOpen}
|
||||
handleClose={() => setSidePeekIsOpen(false)}
|
||||
openInRoot
|
||||
closeLabel={intl.formatMessage({
|
||||
id: "common.close",
|
||||
defaultMessage: "Close",
|
||||
})}
|
||||
>
|
||||
{content ? (
|
||||
<JsonToHtml
|
||||
nodes={content.json.children}
|
||||
embeds={content.embedded_itemsConnection.edges}
|
||||
/>
|
||||
) : null}
|
||||
<div className={styles.ctaContainer}>
|
||||
{primary_button && (
|
||||
<ButtonLink
|
||||
variant="Primary"
|
||||
color="Primary"
|
||||
size="sm"
|
||||
href={primary_button.href}
|
||||
target={primary_button.openInNewTab ? "_blank" : undefined}
|
||||
>
|
||||
{primary_button.title}
|
||||
</ButtonLink>
|
||||
)}
|
||||
{secondary_button && (
|
||||
<ButtonLink
|
||||
variant="Secondary"
|
||||
color="Primary"
|
||||
size="sm"
|
||||
href={secondary_button.href}
|
||||
target={secondary_button.openInNewTab ? "_blank" : undefined}
|
||||
>
|
||||
{secondary_button.title}
|
||||
</ButtonLink>
|
||||
)}
|
||||
</div>
|
||||
</SidePeek>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
@@ -0,0 +1,8 @@
|
||||
.teaserCardSidepeek {
|
||||
display: grid;
|
||||
}
|
||||
|
||||
.ctaContainer {
|
||||
display: grid;
|
||||
gap: var(--Space-x2);
|
||||
}
|
||||
@@ -0,0 +1,343 @@
|
||||
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,
|
||||
},
|
||||
}
|
||||
103
packages/design-system/lib/components/TeaserCard/TeaserCard.tsx
Normal file
103
packages/design-system/lib/components/TeaserCard/TeaserCard.tsx
Normal file
@@ -0,0 +1,103 @@
|
||||
import { ImageVaultAsset } from "@scandic-hotels/common/utils/imageVault"
|
||||
import { VariantProps } from "class-variance-authority"
|
||||
import { TeaserCardSidepeekContent } from "../../types/sidepeekContent"
|
||||
import { type ButtonProps } from "../Button"
|
||||
import ButtonLink from "../ButtonLink"
|
||||
import Image from "../Image"
|
||||
import { Typography } from "../Typography"
|
||||
import TeaserCardSidepeek from "./Sidepeek"
|
||||
import styles from "./teaserCard.module.css"
|
||||
import { teaserCardVariants } from "./variants"
|
||||
|
||||
interface SidePeekButton {
|
||||
call_to_action_text: string
|
||||
}
|
||||
|
||||
interface TeaserCardButton extends Pick<ButtonProps, "onPress"> {
|
||||
title: string
|
||||
href: string
|
||||
openInNewTab?: boolean
|
||||
}
|
||||
interface TeaserCardProps extends VariantProps<typeof teaserCardVariants> {
|
||||
heading: string
|
||||
bodyText: string
|
||||
primaryButton?: TeaserCardButton
|
||||
secondaryButton?: TeaserCardButton
|
||||
sidePeekButton?: SidePeekButton
|
||||
sidePeekContent?: TeaserCardSidepeekContent
|
||||
image?: ImageVaultAsset
|
||||
className?: string
|
||||
}
|
||||
|
||||
export function TeaserCard({
|
||||
heading,
|
||||
bodyText,
|
||||
primaryButton,
|
||||
secondaryButton,
|
||||
sidePeekButton,
|
||||
sidePeekContent,
|
||||
image,
|
||||
style,
|
||||
alwaysStack = false,
|
||||
className,
|
||||
}: TeaserCardProps) {
|
||||
const classNames = teaserCardVariants({ style, alwaysStack, className })
|
||||
|
||||
return (
|
||||
<article className={classNames}>
|
||||
{image && (
|
||||
<div className={styles.imageContainer}>
|
||||
<Image
|
||||
src={image.url}
|
||||
alt={image.meta?.alt || ""}
|
||||
focalPoint={image.focalPoint}
|
||||
dimensions={image.dimensions}
|
||||
fill
|
||||
/>
|
||||
</div>
|
||||
)}
|
||||
<div className={styles.content}>
|
||||
<Typography variant="Title/Subtitle/md">
|
||||
<p>{heading}</p>
|
||||
</Typography>
|
||||
<Typography variant="Body/Paragraph/mdRegular">
|
||||
<p>{bodyText}</p>
|
||||
</Typography>
|
||||
|
||||
{sidePeekButton && sidePeekContent ? (
|
||||
<TeaserCardSidepeek
|
||||
button={sidePeekButton}
|
||||
sidePeekContent={sidePeekContent}
|
||||
/>
|
||||
) : (
|
||||
<div className={styles.ctaContainer}>
|
||||
{primaryButton && (
|
||||
<ButtonLink
|
||||
variant="Tertiary"
|
||||
color="Primary"
|
||||
size="sm"
|
||||
className={styles.ctaButton}
|
||||
href={primaryButton.href}
|
||||
target={primaryButton.openInNewTab ? "_blank" : undefined}
|
||||
>
|
||||
{primaryButton.title}
|
||||
</ButtonLink>
|
||||
)}
|
||||
{secondaryButton && (
|
||||
<ButtonLink
|
||||
variant="Secondary"
|
||||
color="Primary"
|
||||
size="sm"
|
||||
className={styles.ctaButton}
|
||||
href={secondaryButton.href}
|
||||
target={secondaryButton.openInNewTab ? "_blank" : undefined}
|
||||
>
|
||||
{secondaryButton.title}
|
||||
</ButtonLink>
|
||||
)}
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
</article>
|
||||
)
|
||||
}
|
||||
@@ -0,0 +1 @@
|
||||
export { TeaserCard } from "./TeaserCard"
|
||||
@@ -0,0 +1,47 @@
|
||||
.teaserCard {
|
||||
border-radius: var(--Corner-radius-md);
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
overflow: hidden;
|
||||
border: 1px solid var(--Border-Default);
|
||||
color: var(--Text-Default);
|
||||
|
||||
&.default {
|
||||
background-color: var(--Surface-Secondary-Default);
|
||||
}
|
||||
|
||||
&.featured {
|
||||
background-color: var(--Surface-Primary-Default);
|
||||
}
|
||||
}
|
||||
|
||||
.imageContainer {
|
||||
width: 100%;
|
||||
height: 200px;
|
||||
position: relative;
|
||||
}
|
||||
|
||||
.content {
|
||||
display: grid;
|
||||
gap: var(--Space-x15);
|
||||
padding: var(--Space-x2) var(--Space-x3);
|
||||
grid-template-rows: auto 1fr auto;
|
||||
flex-grow: 1;
|
||||
}
|
||||
|
||||
.ctaContainer {
|
||||
display: grid;
|
||||
grid-template-columns: 1fr;
|
||||
gap: var(--Space-x1);
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
@media (min-width: 1367px) {
|
||||
.teaserCard:not(.alwaysStack) .ctaContainer {
|
||||
grid-template-columns: repeat(auto-fit, minmax(0, 1fr));
|
||||
|
||||
&:has(:only-child) {
|
||||
grid-template-columns: 1fr;
|
||||
}
|
||||
}
|
||||
}
|
||||
22
packages/design-system/lib/components/TeaserCard/variants.ts
Normal file
22
packages/design-system/lib/components/TeaserCard/variants.ts
Normal file
@@ -0,0 +1,22 @@
|
||||
import { cva } from "class-variance-authority"
|
||||
|
||||
import styles from "./teaserCard.module.css"
|
||||
|
||||
export const config = {
|
||||
variants: {
|
||||
style: {
|
||||
default: styles.default,
|
||||
featured: styles.featured,
|
||||
},
|
||||
alwaysStack: {
|
||||
true: styles.alwaysStack,
|
||||
false: "",
|
||||
},
|
||||
},
|
||||
defaultVariants: {
|
||||
style: "default",
|
||||
alwaysStack: false,
|
||||
},
|
||||
} as const
|
||||
|
||||
export const teaserCardVariants = cva(styles.teaserCard, config)
|
||||
13
packages/design-system/lib/normalize.css
vendored
13
packages/design-system/lib/normalize.css
vendored
@@ -24,3 +24,16 @@ ul {
|
||||
outline-color: var(--Border-Interactive-Focus);
|
||||
outline-offset: 2px;
|
||||
}
|
||||
|
||||
/* From Tailwind */
|
||||
.sr-only {
|
||||
position: absolute;
|
||||
width: 1px;
|
||||
height: 1px;
|
||||
padding: 0;
|
||||
margin: -1px;
|
||||
overflow: hidden;
|
||||
clip: rect(0, 0, 0, 0);
|
||||
white-space: nowrap;
|
||||
border-width: 0;
|
||||
}
|
||||
|
||||
26
packages/design-system/lib/types/sidepeekContent.ts
Normal file
26
packages/design-system/lib/types/sidepeekContent.ts
Normal file
@@ -0,0 +1,26 @@
|
||||
/* eslint-disable @typescript-eslint/no-explicit-any */
|
||||
type SidepeekContentBase = {
|
||||
heading: string
|
||||
content?: {
|
||||
json?: any
|
||||
embedded_itemsConnection: {
|
||||
edges: any
|
||||
}
|
||||
} | null
|
||||
}
|
||||
|
||||
export type AlertSidepeekContent = SidepeekContentBase
|
||||
export type TeaserCardSidepeekContent = SidepeekContentBase & {
|
||||
primary_button?: {
|
||||
href: string
|
||||
title: string
|
||||
openInNewTab?: boolean
|
||||
isExternal?: boolean
|
||||
}
|
||||
secondary_button?: {
|
||||
href: string
|
||||
title: string
|
||||
openInNewTab?: boolean
|
||||
isExternal?: boolean
|
||||
}
|
||||
}
|
||||
@@ -179,6 +179,7 @@
|
||||
"./Switch": "./lib/components/Switch/index.tsx",
|
||||
"./Table": "./lib/components/Table/index.tsx",
|
||||
"./TermModal": "./lib/components/RateCard/TermModal/index.tsx",
|
||||
"./TeaserCard": "./lib/components/TeaserCard/index.tsx",
|
||||
"./TextArea": "./lib/components/TextArea/index.tsx",
|
||||
"./TextLink": "./lib/components/TextLink/index.tsx",
|
||||
"./TextLinkButton": "./lib/components/TextLinkButton/index.tsx",
|
||||
|
||||
Reference in New Issue
Block a user