-
Notifications
You must be signed in to change notification settings - Fork 241
/
Copy pathindex.tsx
83 lines (75 loc) · 2.15 KB
/
index.tsx
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
"use client";
import clsx from "clsx";
import {
type ComponentProps,
type ElementType,
type ReactNode,
use,
} from "react";
import { OverlayTriggerStateContext } from "react-aria-components";
import styles from "./index.module.scss";
import { Button } from "../unstyled/Button/index.js";
import { Link } from "../unstyled/Link/index.js";
export const VARIANTS = ["primary", "secondary", "tertiary"] as const;
type OwnProps = {
variant?: (typeof VARIANTS)[number] | undefined;
icon?: ReactNode | undefined;
title?: ReactNode | undefined;
toolbar?: ReactNode | ReactNode[] | undefined;
action?: ReactNode | undefined;
footer?: ReactNode | undefined;
nonInteractive?: boolean | undefined;
};
export type Props<T extends ElementType> = Omit<
ComponentProps<T>,
keyof OwnProps
> &
OwnProps;
export const Card = (
props:
| (Props<"div"> & { nonInteractive?: true })
| Props<typeof Link>
| Props<typeof Button>,
) => {
const overlayState = use(OverlayTriggerStateContext);
if (props.nonInteractive) {
// eslint-disable-next-line @typescript-eslint/no-unused-vars
const { nonInteractive, ...otherProps } = props;
return <div {...cardProps(otherProps)} />;
} else if ("href" in props) {
return <Link {...cardProps(props)} />;
} else if (overlayState !== null || "onPress" in props) {
return <Button {...cardProps(props)} />;
} else {
return <div {...cardProps(props)} />;
}
};
const cardProps = <T extends ElementType>({
className,
variant = "secondary",
children,
icon,
title,
toolbar,
footer,
action,
...props
}: Props<T>) => ({
...props,
"data-variant": variant,
className: clsx(styles.card, className),
children: (
<>
<div className={styles.cardHoverBackground} />
{(Boolean(icon) || Boolean(title) || Boolean(toolbar)) && (
<div className={styles.header}>
<div className={styles.title}>{title}</div>
{toolbar && <div className={styles.toolbar}>{toolbar}</div>}
{action && <div className={styles.action}>{action}</div>}
</div>
)}
{children}
{footer && <div className={styles.footer}>{footer}</div>}
</>
),
});