@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.
79 lines (78 loc) • 3.94 kB
TypeScript
import { JSX } from 'solid-js';
/** The work state of the pane's agent/process. Drives a tone-colored status dot
* (and optional label) in the header. */
export type PaneStatusTone = 'working' | 'idle' | 'done' | 'error' | 'blocked';
export interface PaneStatus {
/** The tone — maps to a semantic status hue (see {@link PANE_STATUS_BG}). */
tone: PaneStatusTone;
/** Optional text beside the dot (e.g. "Running tests…"). Without it the dot is
* decorative and only the color carries meaning. */
label?: string;
/** Animate a ping ring on the dot — for the live `working` state. Respects
* prefers-reduced-motion. */
pulse?: boolean;
}
/** tone → status-dot color utility, backed by the kit's tool-* / muted tokens so
* it reads correctly in BOTH light and dark without hardcoded colors.
* - `working` → blue (in-flight)
* - `idle` → neutral muted (waiting)
* - `done` → green (complete)
* - `error` → red (failed)
* - `blocked` → amber (needs input / stalled) */
export declare const PANE_STATUS_BG: Record<PaneStatusTone, string>;
export interface PaneProps {
/** A glyph/avatar shown before the title (an agent icon, a model avatar). */
leading?: JSX.Element;
/** The pane title — the agent / window name. */
title: string;
/** A role / label shown under the title (e.g. "Reviewer", "claude-sonnet"). */
subtitle?: string;
/** A tone-colored status dot (+ optional label) in the header. */
status?: PaneStatus;
/** Extra header controls, placed BEFORE the built-in window controls. */
actions?: JSX.Element;
/** The pane body — scrolls inside a `min-h-0 flex-1 overflow-y-auto` region. */
children?: JSX.Element;
/** A pinned row below the body (e.g. a composer). Stays put while the body scrolls. */
footer?: JSX.Element;
/** Highlight the frame with a ring/border to signal the ACTIVE pane. */
focused?: boolean;
/** Show the restore glyph (Minimize2) instead of maximize (Maximize2). */
maximized?: boolean;
/** Maximize/restore window control. */
onMaximize?: () => void;
/** Close window control. */
onClose?: () => void;
/** Optional split control — the button only renders when this is provided. */
onSplit?: () => void;
/** Optional dock-to-side control — the button only renders when this is provided. */
onDock?: () => void;
/** Extra classes for the outer frame. */
class?: string;
}
/**
* Pane — a reusable framed panel for a multi-agent workspace: a header (leading
* glyph + title/subtitle + status dot + actions + window controls), a scrolling
* body, and an optional pinned footer (e.g. a composer). It is the "pane frame"
* every agent tile otherwise re-hand-rolls.
*
* Layout: the outer frame is a column flexbox; the header and footer hold their
* height (`shrink-0`) while the body takes the rest (`min-h-0 flex-1
* overflow-y-auto`) so content scrolls INSIDE the pane. Give the pane a bounded
* height (a fixed parent, or `h-full` inside a grid/flex track) for the scroll to
* engage; the body imposes no padding so content controls its own.
*
* Window controls (right side of the header): maximize/restore (Maximize2 ↔
* Minimize2, toggled by `maximized`) and close (X) are always present; split
* (Columns2) and dock (PanelRight) only render when `onSplit` / `onDock` are
* passed. Each fires its callback prop.
*
* States: `focused` paints a ring + accent border to mark the active pane;
* `maximized` swaps the maximize glyph for restore.
*
* Colors come entirely from design tokens (surface / border / ring / tool-*),
* so it reads correctly in light and dark with no hardcoded values. The header,
* body, footer, and window-control cluster are exposed via
* `::part(header|body|footer|controls)` for the `kai-pane` facade.
*/
export declare function Pane(props: PaneProps): JSX.Element;