@kitn.ai/ui
Version:
Framework-agnostic, Shadow-DOM web components for building AI chat interfaces — works in React, Vue, Angular, Svelte, or plain HTML. Authored in SolidJS.
62 lines (61 loc) • 3.37 kB
TypeScript
import { JSX } from 'solid-js';
export type CardAppearance = 'outlined' | 'filled' | 'plain' | 'accent';
/** `vertical` (media on top), `horizontal` (media at the start), or `responsive`
* (horizontal when the card's container is at least ~28rem wide, else vertical —
* a CSS container query on the card's own width, NOT the viewport). */
export type CardOrientation = 'vertical' | 'horizontal' | 'responsive';
export interface CardProps extends JSX.HTMLAttributes<HTMLDivElement> {
/** Surface treatment: `outlined` | `filled` | `plain` | `accent`. */
appearance?: CardAppearance;
/** `vertical` (media on top) or `horizontal` (media at the start). */
orientation?: CardOrientation;
/** The card width below which a `responsive` card collapses to vertical and the
* footer action cluster stacks. A CSS length (e.g. `'24rem'`); default `'28rem'`.
* Container-query breakpoints can't be CSS variables, so this prop is baked into
* a per-card `@container` rule. */
collapse?: string;
/** Tighter spacing for dense lists (shrinks `--kai-card-spacing`). */
dense?: boolean;
/** Full-bleed media region (image/video/illustration) at the top (vertical) or
* start (horizontal). Clipped to the card's corners. */
media?: JSX.Element;
/** Header content (e.g. a title). Rendered above the body, padded. */
header?: JSX.Element;
/** An actions cluster pinned to the end of the header row. */
headerActions?: JSX.Element;
/** Footer content. Rendered below the body, padded. */
footer?: JSX.Element;
/** An actions cluster pinned to the end of the footer row. */
footerActions?: JSX.Element;
/** Whether the default slot (body) has content — the facade computes this so an
* empty body region isn't rendered (an empty `<slot>` is always truthy). */
hasBody?: boolean;
/** Render a dismiss (×) that hides the card and calls `onDismiss`. Off by default. */
dismissible?: boolean;
onDismiss?: () => void;
/** Render the whole card as a link (`<a>`). Wins over `clickable`. */
href?: string;
target?: string;
rel?: string;
/** Make the whole card a `role="button"` with Enter/Space activation. A
* clickable/href card must NOT also contain footer action buttons. */
clickable?: boolean;
onCardClick?: (event: MouseEvent | KeyboardEvent) => void;
}
/**
* `Card` — the kit's presentational card surface (the `<kai-card>` primitive),
* modeled on the WebAwesome card: ONE element whose flexibility comes from a few
* structural slots (`media`, `header` + actions, `footer` + actions; body is the
* default slot), `appearance` + `orientation` variants, `::part` styling, and a
* single `--kai-card-spacing` knob. The title/description are NOT slots — they are
* body/header content the consumer marks up, because a slot earns its place only
* where the shadow boundary blocks the consumer (a pinned media/footer region),
* not for a text node.
*
* Distinct from the generative-UI contract chrome in `../components/card.tsx`
* (which the Card Contract cards compose); this one is purely presentational.
*
* a11y: a `clickable`/`href` card MUST NOT also contain action buttons — that
* nests interactive controls inside a button/link.
*/
export declare function Card(props: CardProps): JSX.Element;