@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.
47 lines (46 loc) • 2.32 kB
TypeScript
import { Accessor, JSX } from 'solid-js';
/** Imperative open controller, handed to a parent (the kai-screen facade) via
* `controllerRef` so it can drive/observe open state with `wireDisclosure`. */
export interface ScreenController {
open: Accessor<boolean>;
setOpen: (v: boolean) => void;
}
export interface ScreenProps {
/** The screen body. */
children?: JSX.Element;
/** Header title text. A projected `title` slot overrides this. */
title?: JSX.Element;
/** Header title slot content (the facade's `<slot name="title" />`). Overrides `title`. */
titleSlot?: JSX.Element;
/** Header trailing cluster (the facade's `<slot name="actions" />`). */
actions?: JSX.Element;
/** Controlled open state. When set, the component never changes it itself;
* drive it from `onOpenChange`. Omit for uncontrolled (internal) state. */
open?: boolean;
/** Initial open state when uncontrolled. */
defaultOpen?: boolean;
/** Show the back button (default true). */
back?: boolean;
/** Skip marking sibling elements inert/aria-hidden while open. */
noInert?: boolean;
/** The custom-element host, whose siblings get inert-ed while open. */
host?: () => HTMLElement | undefined;
/** Fires whenever open wants to change (back button / method). */
onOpenChange?: (open: boolean) => void;
/** Back navigation intent: the back button or Escape. */
onBack?: () => void;
/** Receive the open controller once mounted. */
controllerRef?: (api: ScreenController) => void;
/** Receive the focusable surface node so the facade's `focus()` can target it. */
surfaceRef?: (el: HTMLElement) => void;
}
/**
* Screen is the presentational full-bleed overlay surface. It owns the hard parts
* of being a takeover: it fills its mount point while open, marks sibling
* elements `inert` + `aria-hidden` (the standard modal pattern), moves focus into
* the surface on open and restores it on close, fires `onBack` on Escape, and
* runs an enter/exit transition that honors `prefers-reduced-motion`. When closed
* it is removed from layout (no space, not focusable). The developer owns the swap
* (their own routing flips `open`); this owns being the overlay.
*/
export declare function Screen(props: ScreenProps): JSX.Element;