72 lines
2.1 KiB
TypeScript
72 lines
2.1 KiB
TypeScript
import { BidiText } from '@/components/foundation/BidiText';
|
|
import { StatusBadge, type StatusTone } from '@/components/foundation/StatusBadge';
|
|
import { Card } from '@/components/surfaces/Card';
|
|
import { Heading, Text, type HeadingLevel } from '@/components/typography/Typography';
|
|
import styles from './ProductPreview.module.css';
|
|
|
|
export interface PreviewRow {
|
|
id: string;
|
|
primary: string;
|
|
secondary: string;
|
|
status: string;
|
|
statusTone?: StatusTone;
|
|
}
|
|
|
|
interface ProductPreviewProps {
|
|
title: string;
|
|
caption: string;
|
|
rows: PreviewRow[];
|
|
illustrativeLabel: string;
|
|
emptyLabel?: string;
|
|
headingLevel?: HeadingLevel;
|
|
}
|
|
|
|
export function ProductPreview({
|
|
title,
|
|
caption,
|
|
rows,
|
|
illustrativeLabel,
|
|
emptyLabel = 'No preview data',
|
|
headingLevel = 3,
|
|
}: ProductPreviewProps) {
|
|
return (
|
|
<figure className={styles.figure}>
|
|
<Card tone="elevated" padding="none" className={styles.preview}>
|
|
<header className={styles.header}>
|
|
<div>
|
|
<Heading level={headingLevel} appearance="subheading">
|
|
{title}
|
|
</Heading>
|
|
<Text variant="caption">{illustrativeLabel}</Text>
|
|
</div>
|
|
<span className={styles.dots} aria-hidden="true">
|
|
<i />
|
|
<i />
|
|
<i />
|
|
</span>
|
|
</header>
|
|
{rows.length > 0 ? (
|
|
<div className={styles.table} role="table" aria-label={title}>
|
|
{rows.map((row) => (
|
|
<div key={row.id} className={styles.row} role="row">
|
|
<div role="cell">
|
|
<strong>{row.primary}</strong>
|
|
<BidiText className={styles.secondary}>{row.secondary}</BidiText>
|
|
</div>
|
|
<div role="cell">
|
|
<StatusBadge {...(row.statusTone ? { tone: row.statusTone } : {})}>
|
|
{row.status}
|
|
</StatusBadge>
|
|
</div>
|
|
</div>
|
|
))}
|
|
</div>
|
|
) : (
|
|
<p className={styles.empty}>{emptyLabel}</p>
|
|
)}
|
|
</Card>
|
|
<figcaption>{caption}</figcaption>
|
|
</figure>
|
|
);
|
|
}
|