kai-prompt-input
Handles the input, the attachments, and the send, so a host only listens for the submitted text.
- Shadow DOM
- Uncontrolled by default
- Starter suggestions
- Entity pills (/ skills, @ agents)
- Custom toolbar buttons
- Pre-seeded attachments
Preview
Section titled “Preview”Register web components once, then wire up JS properties and DOM events:
<kai-prompt-input id="input" style="display:block; width:100%;"></kai-prompt-input>
<script type="module"> import '@kitn.ai/ui/web-components';
await customElements.whenDefined('kai-prompt-input');
const input = document.getElementById('input');
input.suggestions = ['Summarize this thread', 'Draft a reply']; // `/` inserts skill pills, `@` opens an agent/plugin menu. input.triggers = [ { char: '/', kind: 'skill', items: [{ id: 'summarize', label: 'Summarize', description: 'Summarize the thread' }] }, { char: '@', kind: 'agent', items: [{ id: 'code-reviewer', label: 'Code Reviewer', group: 'Agents' }] }, ];
input.addEventListener('kai-submit', (e) => console.log('send:', e.detail.value, e.detail.entities, e.detail.attachments)); input.addEventListener('kai-value-change', (e) => console.log('typing:', e.detail.value));</script>- Array props:
suggestions,triggers,kindIcons,attachments: set them in JavaScript, not as attributes. - Scalars:
placeholder,disabled,loading,webSearch(web-search),voice,stoppable,suggestionMode: attributes or properties. - Loading + stoppable:
loadingblocks submit while a response streams;stoppableswaps send for a Stop button that fireskai-stop. - Custom toolbar buttons:
<kai-action id icon tooltip>children inside the element firekai-toolbar-actionwithdetail.action. - Entity pills:
triggersmakes/and@insert atomic skill/agent/plugin pills, andkai-submit/kai-value-changecarry the structureddoc+entities. - Pre-populate pills: set
valueto an array of segments ({ type: 'text', text },{ type: 'entity', entity }) instead of a string to seed pills programmatically. The prop tables call that shape a ComposerDoc; it is a structural type, not something you import.
| Child element | Attributes | Text content | Notes |
|---|---|---|---|
| <kai-action> | actioniconidlabeltooltip | Yes | — |
Examples
Section titled “Examples”Default
Section titled “Default”Type and press Enter, or click a chip, to fire kai-submit.
With Voice and Web Search
Section titled “With Voice and Web Search”webSearch and voice add Globe and Mic buttons, firing kai-web-search and kai-voice. Renamed from search / kai-search, with no alias.
Entity Pills
Section titled “Entity Pills”Pre-Populated Pills
Section titled “Pre-Populated Pills”A ComposerDoc value seeds pills on mount and stays editable; submit still emits the flattened value plus doc + entities.
Pre-Seeded Attachments
Section titled “Pre-Seeded Attachments”attachments pre-populates staged files; the paperclip adds more, each chip has a remove button.
Loading State
Section titled “Loading State”Disabled
Section titled “Disabled”Project controls into the shadow: a status strip above the textarea, or leading/trailing toolbar clusters for a + menu or a model switcher.
| Slot | Mode | Purpose |
|---|---|---|
| input-top | inject | Inside the card, above the textarea (e.g. an inline status strip). For content above/below the whole card, use your own layout; that is light DOM you control. |
| toolbar-start | inject | Leading controls in the input toolbar, where a + menu goes. |
| toolbar-end | inject | Trailing controls in the toolbar, before the Send button. |
Styling
Section titled “Styling”Restyle the send button via ::part(send), or hide it for an Enter-only composer.
| Part | Purpose | Example |
|---|---|---|
| send | The send button. Restyle from outside, or hide it entirely (Enter-only). Hiding is pure CSS, which is why there is no `submit="never"`. | |
| Property | Type | Default | Notes |
|---|---|---|---|
| theme | "light" | "dark" | "auto" | 'auto' | Color mode (`auto` follows prefers-color-scheme). |
| value | — | Value of the input: a **string** is the controlled text mirror, a **ComposerDoc** is a one-time pill seed. | |
| placeholder | string | 'Send a message...' | Placeholder text shown in the empty input. |
| disabled | boolean | false | Disable the input and submit button entirely (non-interactive). |
| loading | boolean | false | Show the loading/streaming state and block submit (use while awaiting a reply). |
| suggestions | string[] | — | Starter prompts shown above the input. Clicking one follows `suggestionMode`. Set as a JS property. |
| suggestionMode | "submit" | "fill" | 'submit' | What clicking a suggestion does. Defaults to `'submit'`. |
| webSearch | boolean | false | Show a web-search (Globe) button in the left toolbar; clicking it fires a `kai-web-search` event. Attribute: `web-search`. |
| voice | boolean | false | Show a Voice (Mic) button in the left toolbar; clicking it fires a `voice` event. |
| stoppable | boolean | false | When set and `loading` is true, the send button is replaced by a Stop button (square icon, "Stop" aria-label). Clicking it fires `kai-stop`. |
| submit | "always" | "auto" | 'always' | Send-button visibility. Defaults to `'always'`. |
| attach | boolean | true | Show the built-in paperclip attach button. Default `true`. |
| attachments | — | Attachments to seed the input with. Each `url` must be a `data:` URI or https URL, never `blob:`. | |
| triggers | — | Rich entity triggers. Each `{ char, kind, items }` opens a caret-anchored menu that inserts an atomic pill. JS property. | |
| kindIcons | Record<string, string> | — | Default icon per entity kind (kind → image URL/data-URI) for pills/menu items without their own `icon`. Overrides the built-in agent/plugin glyphs. JS property. |
Events
Section titled “Events”| Event | Detail | Notes |
|---|---|---|
| kai-attachments-change | | The staged attachments changed (file added or removed). Carries the full current list so a consumer can react in real time. |
| kai-stop | Record<string, never> | The Stop button was clicked while `stoppable` and `loading` are both true. |
| kai-submit | | The user submitted the prompt (Enter or send button). `value` is the flattened text. |
| kai-suggestion-click | | A suggestion was clicked while `suggestion-mode="fill"`. |
| kai-toolbar-action | | A custom `<kai-action>` toolbar button was clicked. `action` is the `id` of the `<kai-action>` element that was clicked. |
| kai-value-change | | The input changed (fires on every edit). Carries the flattened `value` plus the structured `doc` + `entities`. |
| kai-voice | Record<string, never> | The Voice (Mic) toolbar button was clicked. |
| kai-web-search | Record<string, never> | The web-search (Globe) toolbar button was clicked. |
Methods
Section titled “Methods”| Method | Signature | Notes |
|---|---|---|
| focus | (options?: FocusOptions): void | Focus the text editor inside the shadow root (not the hidden file input). |
| blur | (): void | Blur the focused input control. |
| clear | (): void | Clear the text and any staged attachments (fires kai-value-change / kai-attachments-change so a controlled consumer can react). |
| send | (): void | Send the current value programmatically, on the same path as Enter / the send button (fires kai-submit, then clears staged attachments). Named `send`, not `submit`, to avoid colliding with the `submit` prop. |