new-personal-site/components/lib/elements/Card.tsx

71 lines
2.0 KiB
TypeScript
Raw Normal View History

2024-12-09 15:36:17 +00:00
import React, { DetailedHTMLProps, HTMLAttributes } from "react";
import { twMerge } from "tailwind-merge";
/**
* # General Card
2025-01-05 06:25:38 +00:00
* @className twui-card
* @className twui-card-link
*
* @info use the classname `nested-link` to prevent the card from being clickable when
* a link (or the target element with this calss) inside the card is clicked.
2024-12-09 15:36:17 +00:00
*/
export default function Card({
href,
variant,
linkProps,
...props
}: DetailedHTMLProps<HTMLAttributes<HTMLDivElement>, HTMLDivElement> & {
variant?: "normal";
href?: string;
linkProps?: DetailedHTMLProps<
React.AnchorHTMLAttributes<HTMLAnchorElement>,
HTMLAnchorElement
>;
}) {
const component = (
<div
{...props}
className={twMerge(
"flex flex-row items-center p-4 rounded bg-white dark:bg-white/10",
"border border-slate-200 dark:border-white/10 border-solid",
2025-01-05 06:25:38 +00:00
href
? "hover:bg-slate-100 dark:hover:bg-white/30 hover:border-slate-400 dark:hover:border-white/20"
: "",
2024-12-09 15:36:17 +00:00
"twui-card",
props.className
)}
>
{props.children}
</div>
);
if (href) {
return (
2025-01-05 06:25:38 +00:00
<a
href={href}
{...linkProps}
onClick={(e) => {
const targetEl = e.target as HTMLElement;
if (targetEl.closest(".nested-link")) {
e.preventDefault();
} else if (e.ctrlKey) {
window.open(href, "_blank");
} else {
window.location.href = href;
}
linkProps?.onClick?.(e);
}}
className={twMerge(
"cursor-pointer",
"twui-card-link",
linkProps?.className
)}
>
2024-12-09 15:36:17 +00:00
{component}
</a>
);
}
return component;
}