import type { GapProp, PadProp, PadRawProp } from "../../props/vocabulary/index.js"; import * as React from "react"; import type { LucideIcon } from "lucide-react"; import type { HeadingLevelProp } from "../../props/vocabulary/index.js"; import type { CardTabItemProp } from "../../props/components/data-display.prop.js"; import { type TabsExtraProp, type TabsProps } from "../navigation/tabs.js"; export type { CardTabItemProp, CardTabItemProp as CardTabItemProps, } from "../../props/components/data-display.prop.js"; /** Semantic accent tone. `accentPlacement` decides WHERE it is drawn — a leading-edge * stripe (default) or the full perimeter. */ type CardAccent = "primary" | "success" | "warning" | "info" | "attention" | "destructive"; /** * Where the semantic `accent` tone is drawn. - `"edge"` (default) — the leading-edge stripe on * `border-inline-start` only, at the `--card-accent-rail-width` measure (6px). This is what * `variant="featured"` does, except the tone is yours instead of `--primary`, so a card can shout * "action required" (`accent="attention"`) or "this failed" (`accent="destructive"`) without * borrowing the brand colour. */ type CardAccentPlacement = "edge" | "perimeter"; /** * Surface fill and edge. `outline` is antd's `outlined` — it drops the FILL and keeps the * hairline; `borderless` is antd's `variant="borderless"` (its deprecated `bordered={false}`) — * it drops the HAIRLINE and keeps the fill. They are two different cards, which is why both * values exist: neither one substitutes for the other. */ type CardVariant = "default" | "muted" | "outline" | "borderless" | "featured"; /** Padding density — base 16px · tight 12px · cozy 20px. */ type CardDensity = "tight" | "cozy"; export type CardProps = React.HTMLAttributes & { accent?: CardAccent; /** * Where `accent` is drawn — `"edge"` (default, the leading-edge stripe) or `"perimeter"` * (a full attention border in the accent tone). Inert without `accent`. */ accentPlacement?: CardAccentPlacement; variant?: CardVariant; density?: CardDensity; /** * Lift the card on hover (antd `hoverable`) — the resting elevation steps up to * `--card-hover-shadow` and the pointer becomes a `pointer`. * * This is a PRESENTATION flag, not an interaction: it announces nothing and binds no handler. * A card that looks clickable has to BE clickable for everyone, so pair it with a real control * — a `Link`/`Button` in the header or footer, or the whole card rendered as one via * {@link CardProps.asChild} — never with a bare `onClick` on this div, which a keyboard or * screen-reader user cannot reach. */ hoverable?: boolean; /** * Borrow the child's element for the card box instead of rendering a `div` — the package's * standard Slot passthrough (`Button`, `AspectRatio`, `ListRow`). The card's chrome and every * `data-*` flag move onto that element, so a card rendered as an `` or a `