metis-desk/.agents/skills/shadcn/assets/showcase/state-matrix.tsx
2026-10-21 11:51:44 +02:00

73 lines
1.6 KiB
TypeScript

import * as React from "react"
import { cn } from "@/lib/utils"
const defaultStates = [
"default",
"hover",
"focus",
"active",
"disabled",
] as const
export function StateMatrix<Row extends string>({
rows,
states = defaultStates,
render,
className,
}: {
rows: readonly Row[]
states?: readonly string[]
render: (row: Row, state: string) => React.ReactNode
className?: string
}) {
return (
<div className={cn("w-full overflow-x-auto", className)}>
<table className="w-full border-separate border-spacing-x-2 border-spacing-y-3">
<thead>
<tr>
<th />
{states.map((state) => (
<th
key={state}
scope="col"
className="text-left font-mono text-xs font-normal text-muted-foreground"
>
{state}
</th>
))}
</tr>
</thead>
<tbody>
{rows.map((row) => (
<tr key={row}>
<th
scope="row"
className="pr-4 text-left font-mono text-xs font-normal text-muted-foreground"
>
{row}
</th>
{states.map((state) => (
<td key={state}>{render(row, state)}</td>
))}
</tr>
))}
</tbody>
</table>
</div>
)
}
// Spread onto a component to pin a state without interaction.
export function previewState(state: string) {
if (state === "disabled") {
return { disabled: true }
}
if (["hover", "focus", "active"].includes(state)) {
return { "data-preview": state }
}
return {}
}