diff --git a/src/components/stat-card/StatCard.tsx b/src/components/stat-card/StatCard.tsx new file mode 100644 index 0000000..5736ae7 --- /dev/null +++ b/src/components/stat-card/StatCard.tsx @@ -0,0 +1,53 @@ +import { splitProps, type JSX } from "solid-js"; +import { twMerge } from "tailwind-merge"; +import Card from "../card/Card"; +import StatCardSection from "./StatCardSection"; +import Flex from "../flex/Flex"; + +export type StatCardProps = JSX.HTMLAttributes & { + dataTheme?: string; +}; + +const StatCard = (props: StatCardProps) => { + const [local, rest] = splitProps(props, [ + "class", + "children", + "dataTheme", + "style", + ]); + + const normalizedStyle = + typeof local.style === "object" || typeof local.style === "undefined" + ? local.style + : undefined; + + return ( + + + {local.children} + + + ); +}; + +const StatCardFigure = StatCardSection("figure"); +const StatCardTitle = StatCardSection("title"); +const StatCardValue = StatCardSection("value"); +const StatCardDesc = StatCardSection("desc"); +const StatCardActions = StatCardSection("actions"); + +export default Object.assign(StatCard, { + Figure: StatCardFigure, + Title: StatCardTitle, + Value: StatCardValue, + Desc: StatCardDesc, + Actions: StatCardActions, +}); diff --git a/src/components/stat-card/StatCardSection.tsx b/src/components/stat-card/StatCardSection.tsx new file mode 100644 index 0000000..16aba79 --- /dev/null +++ b/src/components/stat-card/StatCardSection.tsx @@ -0,0 +1,48 @@ +import { splitProps, type JSX } from "solid-js"; +import { twMerge } from "tailwind-merge"; +import CopyButton from "../copy-button/CopyButton"; + +export const StatCardSection = (section: string) => { + return ( + props: JSX.HTMLAttributes & { copyable?: boolean } + ) => { + const [local, rest] = splitProps(props, ["class", "children", "copyable"]); + + let content = local.children; + + if (section === "figure") { + content = ( +
+
+ {local.children} +
+
+ ); + } + + if (section === "value" && local.copyable) { + content = ( + {local.children} + ); + } + + const classes = + section === "title" + ? "text-sm text-base-content/60" + : section === "value" + ? "text-2xl font-bold text-base-content" + : section === "desc" + ? "text-sm text-base-content/50" + : section === "actions" + ? "flex items-center gap-2" + : ""; + + return ( +
+ {content} +
+ ); + }; +}; + +export default StatCardSection; diff --git a/src/components/stat-card/index.ts b/src/components/stat-card/index.ts new file mode 100644 index 0000000..cdd62a1 --- /dev/null +++ b/src/components/stat-card/index.ts @@ -0,0 +1 @@ +export { default } from "./StatCard"; diff --git a/src/index.ts b/src/index.ts index c2c964e..0c4a876 100644 --- a/src/index.ts +++ b/src/index.ts @@ -92,6 +92,7 @@ export { } from "./components/sidenav"; export { default as Skeleton } from "./components/skeleton"; export { default as Stack } from "./components/stack"; +export { default as StatCard } from "./components/stat-card"; export { default as Stats } from "./components/stats"; export { Status } from "./components/status"; export type { StatusProps } from "./components/status";