@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.
78 lines (77 loc) • 4.17 kB
TypeScript
import { JSX } from 'solid-js';
import { PaneStatusTone } from './pane';
/** The work state of a tab's agent/process, mapped to the kit's tool / status
* hues — the SAME vocabulary as {@link './pane'.PaneStatus} and the AgentCard:
* working = blue, idle = muted, done = green, error = red, blocked = amber. */
export interface PaneTabStatus {
/** Which hue the numbered badge takes. */
tone: PaneStatusTone;
/** Optional status word shown on the active tab, on hover, and always for a
* needs-attention / error tab. Without it only the badge color carries state. */
label?: string;
/** Animate a ping ring around the badge — for the live `working` state.
* Respects prefers-reduced-motion. */
pulse?: boolean;
}
/** One tab in a {@link PaneGroup}: an agent/window shown in the strip. */
export interface PaneTab {
/** Stable id, emitted as the selected value throughout. */
id: string;
/** The tab name (the agent / window title). */
name: string;
/** Run status — drives the numbered badge color + the status word. Defaults to
* an `idle` (muted) badge with no word. */
status?: PaneTabStatus;
/** Raise the attention treatment: an amber ring + the status word always shown.
* The "this one wants you" signal. */
needsAttention?: boolean;
/** The keyboard NUMBER shown inside the badge (the ⌥-jump hint). Defaults to the
* tab's 1-based position in the strip. */
number?: number;
}
export interface PaneGroupProps {
/** The tabs, left → right. Each is one agent/window in the group. */
tabs: PaneTab[];
/** The active tab id. Defaults to the first tab. Drive it from `onTabChange`. */
active?: string;
/** A tab was selected (click, Enter/Space, or arrow-key move). */
onTabChange?: (id: string) => void;
/** A tab's close (×) was clicked. The consumer drops the tab from `tabs`. */
onTabClose?: (id: string) => void;
/** A tab's "…" overflow was clicked. The consumer wires the actual menu; the
* group only surfaces the affordance. Omit to hide the "…" button. */
onTabMenu?: (id: string) => void;
/** Highlight the frame with a ring/border to mark this as the ACTIVE group in a
* multi-group layout. */
focused?: boolean;
/** The active pane's body — the consumer owns it and swaps it on `onTabChange`. */
children?: JSX.Element;
/** Extra classes for the outer frame. */
class?: string;
}
/**
* PaneGroup — an editor group: a TAB STRIP (numbered-status-badge tabs) over a
* single CONTENT area showing the active tab's pane body. The reusable "one column
* = a group of agents shown as tabs" primitive from the Multi-Agent Workspace,
* extracted from the hand-rolled group in the Split Workspace demo.
*
* Each tab leads with a small TONE-COLORED NUMBERED BADGE — the color encodes the
* agent's run status, the digit is its keyboard (⌥-jump) number, unifying status +
* hint into one element — then the name, then the status WORD (shown on the active
* tab, on hover, and always for a needs-attention / error tab), an optional "…"
* overflow, and a close "×". The active tab is highlighted; a needs-attention tab
* carries an amber ring even when inactive.
*
* Composition: the group owns the tab UX; the CONSUMER owns the pane content. It
* renders `children` as the active pane's body and swaps it in response to
* `onTabChange`. Selection-only — it never routes content itself.
*
* Accessibility: a `role="group"` ("Open panes") strip of real `<button>` tab
* activators (NOT `role="tab"`, so the strip can legally own the per-tab menu/close
* buttons) with roving tabindex + Arrow/Home/End navigation; the active activator is
* marked `aria-current="true"`, and the body is the `role="tabpanel"`. Colors are all
* token-backed (surface / border / ring / tool-*), so it reads in light and dark.
* The strip, each tab, and the body are exposed via `::part(tabs|tab|body)` for
* the `kai-pane-group` facade. Give the group a bounded height for the body scroll.
*/
export declare function PaneGroup(props: PaneGroupProps): JSX.Element;