90 lines
1.9 KiB
TypeScript
90 lines
1.9 KiB
TypeScript
import type { FC, ReactNode } from "react";
|
|
|
|
import { Avatar, Paper, Stack, Text } from "@mantine/core";
|
|
|
|
import classes from "./EntryCard.module.css";
|
|
|
|
type EntryCardProps = {
|
|
actions?: ReactNode;
|
|
color?: string;
|
|
details?: ReactNode;
|
|
icon?: ReactNode;
|
|
imageSrc?: null | string;
|
|
initial: string;
|
|
metadata: string;
|
|
title: string;
|
|
tone: "negative"
|
|
| "neutral"
|
|
| "positive";
|
|
value: ReactNode;
|
|
valueLabel: string;
|
|
wrap?: boolean;
|
|
};
|
|
|
|
const EntryCard: FC<EntryCardProps> = (props) => {
|
|
const surfaceStyle = props.color
|
|
? {
|
|
background: `color-mix(in srgb, var(--mantine-color-${props.color}-0) 45%, var(--wl-color-surface))`,
|
|
}
|
|
: undefined;
|
|
|
|
const titleLineClamp = props.wrap ? undefined : 1;
|
|
|
|
const valueContainerClass = props.actions ? classes.valueFooter : undefined;
|
|
const valueLabelClass = `${classes[props.tone]} ${props.actions ? classes.valueLabel : ""}`;
|
|
const valueComponent = typeof props.value === "string" ? undefined : "div";
|
|
|
|
return (
|
|
<Paper
|
|
className={classes.row}
|
|
data-wrap={props.wrap || undefined}
|
|
style={surfaceStyle}
|
|
withBorder
|
|
>
|
|
<Avatar
|
|
alt=""
|
|
aria-hidden="true"
|
|
radius="md"
|
|
size={40}
|
|
src={props.imageSrc}
|
|
>
|
|
{props.icon ?? props.initial}
|
|
</Avatar>
|
|
|
|
<Stack className={classes.identity} gap={2}>
|
|
<Text fw={700} lineClamp={titleLineClamp}>
|
|
{props.title}
|
|
</Text>
|
|
|
|
<Text c="dimmed" size="sm">
|
|
{props.metadata}
|
|
</Text>
|
|
|
|
{props.details}
|
|
</Stack>
|
|
|
|
<Stack className={classes.value} gap={2}>
|
|
<Text
|
|
className={classes[props.tone]}
|
|
component={valueComponent}
|
|
fw={700}
|
|
>
|
|
{props.value}
|
|
</Text>
|
|
|
|
<div className={valueContainerClass}>
|
|
<Text className={valueLabelClass} size="sm">
|
|
{props.valueLabel}
|
|
</Text>
|
|
|
|
{Boolean(props.actions) && (
|
|
<div className={classes.actions}>{props.actions}</div>
|
|
)}
|
|
</div>
|
|
</Stack>
|
|
</Paper>
|
|
);
|
|
};
|
|
|
|
export { EntryCard };
|