Skip to content
kitn AI/UI

Working with the components directly

The kai-* elements are the fast path. When you want full control over markup and layout — and you’re in a Solid app — skip the wrapper and import the underlying pieces from @kitn.ai/ui. You compose them in JSX, and your bundler tree-shakes away whatever you don’t use.

This page is the catalog, organized by the four layers. For a full streaming chat built this way, see the Solid guide.

Terminal window
npm install @kitn.ai/ui solid-js
import '@kitn.ai/ui/theme.css'; // design tokens, once near your entry

Behavior with no markup — the logic you’d otherwise rewrite per app. These are the layer the kai-* elements don’t expose, so importing them directly is the main reason to drop down here.

import {
useTextStream,
useStickToBottom,
useAutoResize,
useVoiceRecorder,
} from '@kitn.ai/ui';
  • useTextStream — drive token-by-token streaming into your own UI.
  • useStickToBottom — keep a scroll container pinned to the latest message, yielding when the reader scrolls up.
  • useAutoResize — grow a textarea with its content.
  • useVoiceRecorder — microphone capture state for a voice composer.

ChatConfig (and its useChatConfig hook) sets shared options like prose size for everything rendered inside it.

The kit’s own accessible building blocks. Useful on their own, well outside a chat.

import { Button, Switch, Avatar, Badge, Separator } from '@kitn.ai/ui';
import { Tooltip, HoverCard, Dropdown } from '@kitn.ai/ui';
import { Resizable, ResizablePanel, ScrollArea } from '@kitn.ai/ui';
<Switch label="Temporary chat" onChange={(on) => setTemporary(on)} />
<Button variant="ghost" size="icon" aria-label="Add"><PlusIcon /></Button> {/* your icon */}

Resizable + ResizablePanel build a draggable split — handles drop in automatically between visible panels. See the Solid guide for a full sidebar-plus-chat layout.

The AI surface. Compose a thread, or drop a single component anywhere.

import {
ChatContainer,
ChatContainerContent,
Message,
MessageContent,
PromptInput,
PromptInputTextarea,
PromptInputActions,
} from '@kitn.ai/ui';

Each one also works standalone — render just the part you need:

import {
Markdown, Reasoning, ReasoningTrigger, ReasoningContent, Tool, Artifact,
} from '@kitn.ai/ui';
<Markdown content={assistantReply} />
<Reasoning isStreaming={isStreaming}>
<ReasoningTrigger>View reasoning</ReasoningTrigger>
<ReasoningContent markdown>{thinkingText}</ReasoningContent>
</Reasoning>
<Tool toolPart={toolCall} defaultOpen />
<Artifact files={artifactFiles} />

Reasoning is a compound: pair it with ReasoningTrigger and ReasoningContent. Prose size for Markdown comes from the surrounding ChatConfig, not a prop.

ChatContainer is transport-agnostic: it owns the conversation UI, you own the request. Render messages inside ChatContainerContent and stream the reply into your signal from PromptInput’s onSubmit.

Native components and kai-* elements ship in the same package and coexist. Compose primitives where you want control, and drop a <kai-chat> shell where you want batteries included — even on different screens of the same app.