@kitn.ai/ui 0.14.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (370) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +394 -0
  3. package/dist/bash-InADTalH.js +1 -0
  4. package/dist/core-AYMC6_lb.js +12 -0
  5. package/dist/css-M7EaDHN_.js +1 -0
  6. package/dist/custom-elements.json +4739 -0
  7. package/dist/engine-javascript-vq0WuIJl.js +141 -0
  8. package/dist/github-dark-dimmed-DUshB20C.js +1 -0
  9. package/dist/github-light-JYsPkUQd.js +1 -0
  10. package/dist/host-embed.d.ts +33 -0
  11. package/dist/html-CPZ3oZQ7.js +1 -0
  12. package/dist/index.d.ts +2 -0
  13. package/dist/javascript-C25yR2R2.js +1 -0
  14. package/dist/json-DxJze_jm.js +1 -0
  15. package/dist/kitn-chat-provider.d.ts +2 -0
  16. package/dist/kitn-chat-provider.es.js +240 -0
  17. package/dist/kitn-chat.es.js +77 -0
  18. package/dist/llms/llms-full.txt +1018 -0
  19. package/dist/llms/llms.txt +104 -0
  20. package/dist/origin.d.ts +5 -0
  21. package/dist/provider-runtime.d.ts +27 -0
  22. package/dist/schemas/card-envelope.schema.json +14 -0
  23. package/dist/schemas/card-event.schema.json +12 -0
  24. package/dist/schemas/choice.schema.json +70 -0
  25. package/dist/schemas/confirm.schema.json +65 -0
  26. package/dist/schemas/embed.schema.json +65 -0
  27. package/dist/schemas/form.result.schema.json +7 -0
  28. package/dist/schemas/form.schema.json +33 -0
  29. package/dist/schemas/link.schema.json +56 -0
  30. package/dist/schemas/tasks.result.schema.json +16 -0
  31. package/dist/schemas/tasks.schema.json +78 -0
  32. package/dist/svelte--5p79yCD.js +1 -0
  33. package/dist/theme.tokens.css +176 -0
  34. package/dist/tsx-B8rCNbgL.js +1 -0
  35. package/dist/typescript-RycA9KXf.js +1 -0
  36. package/dist/validate.d.ts +4 -0
  37. package/dist/version.d.ts +4 -0
  38. package/dist/vue-BmIZj4XD.js +1 -0
  39. package/dist/wire.d.ts +53 -0
  40. package/frameworks/react/index.tsx +948 -0
  41. package/frameworks/react/runtime.tsx +94 -0
  42. package/llms-full.txt +1018 -0
  43. package/llms.txt +104 -0
  44. package/package.json +141 -0
  45. package/src/components/artifact.stories.tsx +138 -0
  46. package/src/components/artifact.tsx +743 -0
  47. package/src/components/attachments.stories.tsx +303 -0
  48. package/src/components/attachments.test.tsx +64 -0
  49. package/src/components/attachments.tsx +399 -0
  50. package/src/components/card-fallback.tsx +28 -0
  51. package/src/components/card-renderer.tsx +52 -0
  52. package/src/components/card.tsx +110 -0
  53. package/src/components/chain-of-thought.stories.tsx +211 -0
  54. package/src/components/chain-of-thought.tsx +139 -0
  55. package/src/components/chat-container.stories.tsx +187 -0
  56. package/src/components/chat-container.tsx +82 -0
  57. package/src/components/chat-scope-picker.tsx +47 -0
  58. package/src/components/chat-thread.test.tsx +58 -0
  59. package/src/components/chat-thread.tsx +249 -0
  60. package/src/components/checkpoint.stories.tsx +102 -0
  61. package/src/components/checkpoint.tsx +88 -0
  62. package/src/components/choice-card.tsx +569 -0
  63. package/src/components/code-block.stories.tsx +150 -0
  64. package/src/components/code-block.tsx +105 -0
  65. package/src/components/component-meta.json +3735 -0
  66. package/src/components/confirm-card.stories.tsx +74 -0
  67. package/src/components/confirm-card.tsx +315 -0
  68. package/src/components/context.stories.tsx +229 -0
  69. package/src/components/context.test.tsx +133 -0
  70. package/src/components/context.tsx +363 -0
  71. package/src/components/conversation-item.stories.tsx +125 -0
  72. package/src/components/conversation-item.tsx +16 -0
  73. package/src/components/conversation-list.stories.tsx +133 -0
  74. package/src/components/conversation-list.tsx +101 -0
  75. package/src/components/default-input.test.tsx +111 -0
  76. package/src/components/embed.tsx +196 -0
  77. package/src/components/empty.stories.tsx +434 -0
  78. package/src/components/empty.tsx +166 -0
  79. package/src/components/feedback-bar.stories.tsx +138 -0
  80. package/src/components/feedback-bar.test.tsx +103 -0
  81. package/src/components/feedback-bar.tsx +166 -0
  82. package/src/components/file-tree.stories.tsx +73 -0
  83. package/src/components/file-tree.tsx +383 -0
  84. package/src/components/file-upload.stories.tsx +156 -0
  85. package/src/components/file-upload.tsx +161 -0
  86. package/src/components/form-widgets.tsx +461 -0
  87. package/src/components/form.tsx +873 -0
  88. package/src/components/image.stories.tsx +89 -0
  89. package/src/components/image.tsx +67 -0
  90. package/src/components/link-preview.tsx +194 -0
  91. package/src/components/loader.stories.tsx +181 -0
  92. package/src/components/loader.tsx +333 -0
  93. package/src/components/markdown.stories.tsx +180 -0
  94. package/src/components/markdown.tsx +81 -0
  95. package/src/components/message-action-bar.test.tsx +128 -0
  96. package/src/components/message-narrow.stories.tsx +329 -0
  97. package/src/components/message-skills.stories.tsx +211 -0
  98. package/src/components/message-skills.tsx +36 -0
  99. package/src/components/message.stories.tsx +281 -0
  100. package/src/components/message.tsx +227 -0
  101. package/src/components/model-switcher.stories.tsx +123 -0
  102. package/src/components/model-switcher.test.tsx +65 -0
  103. package/src/components/model-switcher.tsx +87 -0
  104. package/src/components/prompt-input.stories.tsx +222 -0
  105. package/src/components/prompt-input.tsx +211 -0
  106. package/src/components/prompt-suggestion.stories.tsx +142 -0
  107. package/src/components/prompt-suggestion.tsx +115 -0
  108. package/src/components/reasoning.stories.tsx +140 -0
  109. package/src/components/reasoning.tsx +156 -0
  110. package/src/components/resizable.test.tsx +226 -0
  111. package/src/components/response-stream.tsx +103 -0
  112. package/src/components/scroll-button.stories.tsx +100 -0
  113. package/src/components/scroll-button.tsx +34 -0
  114. package/src/components/slash-command.stories.tsx +163 -0
  115. package/src/components/slash-command.tsx +232 -0
  116. package/src/components/source-list.test.tsx +152 -0
  117. package/src/components/source.stories.tsx +124 -0
  118. package/src/components/source.tsx +129 -0
  119. package/src/components/tasks-card.stories.tsx +78 -0
  120. package/src/components/tasks-card.tsx +432 -0
  121. package/src/components/text-shimmer.stories.tsx +87 -0
  122. package/src/components/text-shimmer.tsx +37 -0
  123. package/src/components/thinking-bar.stories.tsx +87 -0
  124. package/src/components/thinking-bar.tsx +50 -0
  125. package/src/components/tool.stories.tsx +153 -0
  126. package/src/components/tool.tsx +184 -0
  127. package/src/components/use-card-resolution.ts +28 -0
  128. package/src/components/voice-input.stories.tsx +83 -0
  129. package/src/components/voice-input.tsx +107 -0
  130. package/src/elements/artifact.stories.tsx +506 -0
  131. package/src/elements/artifact.tsx +137 -0
  132. package/src/elements/attachments.stories.tsx +190 -0
  133. package/src/elements/attachments.tsx +136 -0
  134. package/src/elements/card.stories.tsx +113 -0
  135. package/src/elements/card.tsx +40 -0
  136. package/src/elements/cards.stories.tsx +59 -0
  137. package/src/elements/cards.tsx +97 -0
  138. package/src/elements/catalog.stories.tsx +491 -0
  139. package/src/elements/chain-of-thought.declarative.test.tsx +153 -0
  140. package/src/elements/chain-of-thought.stories.tsx +113 -0
  141. package/src/elements/chain-of-thought.tsx +92 -0
  142. package/src/elements/chat-scope-picker.stories.tsx +73 -0
  143. package/src/elements/chat-scope-picker.tsx +36 -0
  144. package/src/elements/chat-types.ts +42 -0
  145. package/src/elements/chat-workspace.stories.tsx +288 -0
  146. package/src/elements/chat-workspace.tsx +161 -0
  147. package/src/elements/chat.stories.tsx +151 -0
  148. package/src/elements/chat.tsx +80 -0
  149. package/src/elements/checkpoint.stories.tsx +72 -0
  150. package/src/elements/checkpoint.tsx +47 -0
  151. package/src/elements/choice.stories.tsx +240 -0
  152. package/src/elements/choice.tsx +48 -0
  153. package/src/elements/code-block.stories.tsx +83 -0
  154. package/src/elements/code-block.tsx +42 -0
  155. package/src/elements/compiled.css +2 -0
  156. package/src/elements/composed-shell.stories.tsx +316 -0
  157. package/src/elements/confirm-card.stories.tsx +227 -0
  158. package/src/elements/confirm-card.tsx +51 -0
  159. package/src/elements/context-meter.stories.tsx +151 -0
  160. package/src/elements/context-meter.tsx +121 -0
  161. package/src/elements/conversation-list.declarative.test.tsx +137 -0
  162. package/src/elements/conversation-list.stories.tsx +243 -0
  163. package/src/elements/conversation-list.tsx +80 -0
  164. package/src/elements/css.ts +5 -0
  165. package/src/elements/default-input.tsx +247 -0
  166. package/src/elements/define.tsx +171 -0
  167. package/src/elements/element-meta.json +3314 -0
  168. package/src/elements/element-types.d.ts +710 -0
  169. package/src/elements/embed.stories.tsx +213 -0
  170. package/src/elements/embed.tsx +35 -0
  171. package/src/elements/empty.stories.tsx +111 -0
  172. package/src/elements/empty.tsx +29 -0
  173. package/src/elements/feedback-bar.stories.tsx +114 -0
  174. package/src/elements/feedback-bar.tsx +61 -0
  175. package/src/elements/file-tree.stories.tsx +134 -0
  176. package/src/elements/file-tree.tsx +52 -0
  177. package/src/elements/file-upload.stories.tsx +82 -0
  178. package/src/elements/file-upload.tsx +44 -0
  179. package/src/elements/form.stories.tsx +248 -0
  180. package/src/elements/form.tsx +43 -0
  181. package/src/elements/framework-usage.json +563 -0
  182. package/src/elements/image.stories.tsx +71 -0
  183. package/src/elements/image.tsx +32 -0
  184. package/src/elements/link-preview.stories.tsx +209 -0
  185. package/src/elements/link-preview.tsx +34 -0
  186. package/src/elements/loader.stories.tsx +88 -0
  187. package/src/elements/loader.tsx +25 -0
  188. package/src/elements/markdown.stories.tsx +76 -0
  189. package/src/elements/markdown.tsx +38 -0
  190. package/src/elements/message-skills.declarative.test.tsx +104 -0
  191. package/src/elements/message-skills.stories.tsx +114 -0
  192. package/src/elements/message-skills.tsx +85 -0
  193. package/src/elements/message.stories.tsx +218 -0
  194. package/src/elements/message.tsx +162 -0
  195. package/src/elements/model-switcher.declarative.test.tsx +130 -0
  196. package/src/elements/model-switcher.stories.tsx +198 -0
  197. package/src/elements/model-switcher.tsx +93 -0
  198. package/src/elements/popover.stories.tsx +80 -0
  199. package/src/elements/popover.tsx +59 -0
  200. package/src/elements/prompt-input-slash-command.test.tsx +128 -0
  201. package/src/elements/prompt-input-stoppable.test.tsx +88 -0
  202. package/src/elements/prompt-input-toolbar-actions.test.tsx +120 -0
  203. package/src/elements/prompt-input.stories.tsx +331 -0
  204. package/src/elements/prompt-input.tsx +185 -0
  205. package/src/elements/prompt-suggestions.declarative.test.tsx +164 -0
  206. package/src/elements/prompt-suggestions.stories.tsx +213 -0
  207. package/src/elements/prompt-suggestions.tsx +94 -0
  208. package/src/elements/reasoning.stories.tsx +77 -0
  209. package/src/elements/reasoning.tsx +50 -0
  210. package/src/elements/register.ts +56 -0
  211. package/src/elements/remote.stories.tsx +314 -0
  212. package/src/elements/remote.tsx +221 -0
  213. package/src/elements/resizable.d.ts +27 -0
  214. package/src/elements/resizable.stories.tsx +426 -0
  215. package/src/elements/resizable.tsx +553 -0
  216. package/src/elements/response-stream.stories.tsx +79 -0
  217. package/src/elements/response-stream.tsx +40 -0
  218. package/src/elements/scroll-button.stories.tsx +202 -0
  219. package/src/elements/scroll-button.test.tsx +148 -0
  220. package/src/elements/scroll-button.tsx +126 -0
  221. package/src/elements/source-list.stories.tsx +143 -0
  222. package/src/elements/source.stories.tsx +88 -0
  223. package/src/elements/source.tsx +120 -0
  224. package/src/elements/styles.css +199 -0
  225. package/src/elements/switch.stories.tsx +56 -0
  226. package/src/elements/switch.tsx +43 -0
  227. package/src/elements/tasks.stories.tsx +237 -0
  228. package/src/elements/tasks.tsx +46 -0
  229. package/src/elements/text-shimmer.stories.tsx +64 -0
  230. package/src/elements/text-shimmer.tsx +28 -0
  231. package/src/elements/thinking-bar.stories.tsx +72 -0
  232. package/src/elements/thinking-bar.tsx +34 -0
  233. package/src/elements/tool.stories.tsx +89 -0
  234. package/src/elements/tool.tsx +23 -0
  235. package/src/elements/voice-input.stories.tsx +88 -0
  236. package/src/elements/voice-input.tsx +41 -0
  237. package/src/index.ts +253 -0
  238. package/src/primitives/card-contract.ts +71 -0
  239. package/src/primitives/card-host.tsx +35 -0
  240. package/src/primitives/card-registry.tsx +67 -0
  241. package/src/primitives/card-resolution.ts +36 -0
  242. package/src/primitives/card-routing.ts +79 -0
  243. package/src/primitives/card-schemas/card-envelope.schema.json +14 -0
  244. package/src/primitives/card-schemas/card-event.schema.json +12 -0
  245. package/src/primitives/card-schemas/choice.schema.json +70 -0
  246. package/src/primitives/card-schemas/confirm.schema.json +65 -0
  247. package/src/primitives/card-schemas/embed.schema.json +65 -0
  248. package/src/primitives/card-schemas/form.result.schema.json +7 -0
  249. package/src/primitives/card-schemas/form.schema.json +33 -0
  250. package/src/primitives/card-schemas/link.schema.json +56 -0
  251. package/src/primitives/card-schemas/tasks.result.schema.json +16 -0
  252. package/src/primitives/card-schemas/tasks.schema.json +78 -0
  253. package/src/primitives/card-validate.ts +95 -0
  254. package/src/primitives/chat-config.tsx +76 -0
  255. package/src/primitives/controllable.test.ts +47 -0
  256. package/src/primitives/controllable.ts +21 -0
  257. package/src/primitives/embed-providers.ts +254 -0
  258. package/src/primitives/highlighter.ts +157 -0
  259. package/src/primitives/link-preview.ts +87 -0
  260. package/src/primitives/pdf-preview.ts +121 -0
  261. package/src/primitives/use-auto-resize.ts +31 -0
  262. package/src/primitives/use-resize-observer.ts +12 -0
  263. package/src/primitives/use-stick-to-bottom.ts +43 -0
  264. package/src/primitives/use-text-stream.ts +112 -0
  265. package/src/primitives/use-voice-recorder.ts +50 -0
  266. package/src/remote/host-embed.ts +345 -0
  267. package/src/remote/index.ts +2 -0
  268. package/src/remote/origin.ts +30 -0
  269. package/src/remote/provider-runtime.ts +259 -0
  270. package/src/remote/provider.ts +2 -0
  271. package/src/remote/validate.ts +22 -0
  272. package/src/remote/version.ts +12 -0
  273. package/src/remote/wire.ts +48 -0
  274. package/src/stories/chat-panel-layout.stories.tsx +145 -0
  275. package/src/stories/chat-scene.tsx +571 -0
  276. package/src/stories/checkpoint-restore.stories.tsx +256 -0
  277. package/src/stories/context-usage.stories.tsx +212 -0
  278. package/src/stories/conversation-with-reasoning.stories.tsx +182 -0
  279. package/src/stories/conversation-with-sources.stories.tsx +471 -0
  280. package/src/stories/docs/Accessibility.mdx +119 -0
  281. package/src/stories/docs/ChildElements.mdx +269 -0
  282. package/src/stories/docs/ForAIAgents.mdx +162 -0
  283. package/src/stories/docs/GettingStarted.mdx +65 -0
  284. package/src/stories/docs/Installation.mdx +83 -0
  285. package/src/stories/docs/Introduction.mdx +50 -0
  286. package/src/stories/docs/SolidJsAdvanced.mdx +17 -0
  287. package/src/stories/docs/Theming.mdx +85 -0
  288. package/src/stories/docs/element-controls.ts +121 -0
  289. package/src/stories/docs/frameworks/Angular.mdx +245 -0
  290. package/src/stories/docs/frameworks/Html.mdx +227 -0
  291. package/src/stories/docs/frameworks/Overview.mdx +47 -0
  292. package/src/stories/docs/frameworks/React.mdx +227 -0
  293. package/src/stories/docs/frameworks/Solid.mdx +173 -0
  294. package/src/stories/docs/frameworks/Svelte.mdx +194 -0
  295. package/src/stories/docs/frameworks/Vue.mdx +238 -0
  296. package/src/stories/docs/generative-ui-overview.mdx +186 -0
  297. package/src/stories/docs/recipes/SpeechToText.mdx +7 -0
  298. package/src/stories/docs/recipes/Streaming.mdx +68 -0
  299. package/src/stories/docs/recipes/TextToSpeech.mdx +35 -0
  300. package/src/stories/docs/theme-editor/canvas.tsx +32 -0
  301. package/src/stories/docs/theme-editor/inspector.tsx +66 -0
  302. package/src/stories/docs/theme-editor/presets.test.ts +32 -0
  303. package/src/stories/docs/theme-editor/presets.ts +64 -0
  304. package/src/stories/docs/theme-editor/theme-css.test.ts +19 -0
  305. package/src/stories/docs/theme-editor/theme-css.ts +15 -0
  306. package/src/stories/docs/theme-editor/theme-editor.tsx +146 -0
  307. package/src/stories/docs/theme-tokens.tsx +174 -0
  308. package/src/stories/examples/ChoosingComponents.mdx +106 -0
  309. package/src/stories/examples/sample-data.ts +79 -0
  310. package/src/stories/examples/usage/checkpoint-restore.ts +156 -0
  311. package/src/stories/examples/usage/context-usage.ts +591 -0
  312. package/src/stories/examples/usage/conversation-with-reasoning.ts +224 -0
  313. package/src/stories/examples/usage/conversation-with-sources.ts +589 -0
  314. package/src/stories/examples/usage/empty-state.ts +144 -0
  315. package/src/stories/examples/usage/full-chat-app.ts +277 -0
  316. package/src/stories/examples/usage/index.ts +63 -0
  317. package/src/stories/examples/usage/message-actions.ts +704 -0
  318. package/src/stories/examples/usage/pattern-centered-conversation.ts +446 -0
  319. package/src/stories/examples/usage/pattern-chat-panel-layout.ts +442 -0
  320. package/src/stories/examples/usage/pattern-docked-widget.ts +479 -0
  321. package/src/stories/examples/usage/prompt-input-variants.ts +1356 -0
  322. package/src/stories/examples/usage/streaming-response.ts +687 -0
  323. package/src/stories/examples/usage/types.ts +33 -0
  324. package/src/stories/full-chat.stories.tsx +18 -0
  325. package/src/stories/message-actions.stories.tsx +230 -0
  326. package/src/stories/pattern-centered-conversation.stories.tsx +93 -0
  327. package/src/stories/pattern-docked-widget.stories.tsx +93 -0
  328. package/src/stories/pattern-empty-state.stories.tsx +76 -0
  329. package/src/stories/prompt-input-variants.stories.tsx +456 -0
  330. package/src/stories/streaming-response.stories.tsx +438 -0
  331. package/src/stories/theme-editor.stories.tsx +16 -0
  332. package/src/stories/token-reference.stories.tsx +18 -0
  333. package/src/stories/typography.stories.tsx +78 -0
  334. package/src/types.ts +47 -0
  335. package/src/ui/action-icons.ts +52 -0
  336. package/src/ui/avatar.stories.tsx +103 -0
  337. package/src/ui/avatar.tsx +23 -0
  338. package/src/ui/badge.stories.tsx +86 -0
  339. package/src/ui/badge.tsx +21 -0
  340. package/src/ui/button.stories.tsx +145 -0
  341. package/src/ui/button.tsx +38 -0
  342. package/src/ui/collapsible.stories.tsx +69 -0
  343. package/src/ui/collapsible.tsx +125 -0
  344. package/src/ui/dropdown.stories.tsx +59 -0
  345. package/src/ui/dropdown.tsx +196 -0
  346. package/src/ui/hover-card.stories.tsx +77 -0
  347. package/src/ui/hover-card.test.tsx +30 -0
  348. package/src/ui/hover-card.tsx +172 -0
  349. package/src/ui/overlay.stories.tsx +115 -0
  350. package/src/ui/overlay.tsx +158 -0
  351. package/src/ui/popover.stories.tsx +81 -0
  352. package/src/ui/popover.test.tsx +99 -0
  353. package/src/ui/popover.tsx +92 -0
  354. package/src/ui/resizable.stories.tsx +236 -0
  355. package/src/ui/resizable.tsx +576 -0
  356. package/src/ui/scroll-area.stories.tsx +50 -0
  357. package/src/ui/scroll-area.tsx +15 -0
  358. package/src/ui/separator.stories.tsx +81 -0
  359. package/src/ui/separator.tsx +10 -0
  360. package/src/ui/skeleton.stories.tsx +337 -0
  361. package/src/ui/skeleton.tsx +16 -0
  362. package/src/ui/switch.stories.tsx +51 -0
  363. package/src/ui/switch.test.tsx +59 -0
  364. package/src/ui/switch.tsx +62 -0
  365. package/src/ui/textarea.stories.tsx +76 -0
  366. package/src/ui/textarea.tsx +21 -0
  367. package/src/ui/tooltip.stories.tsx +74 -0
  368. package/src/ui/tooltip.tsx +68 -0
  369. package/src/utils/cn.ts +24 -0
  370. package/theme.css +187 -0
@@ -0,0 +1,47 @@
1
+ import { Meta } from '@storybook/addon-docs/blocks';
2
+
3
+ <Meta title="Docs/Frameworks/Overview" />
4
+
5
+ # Frameworks
6
+
7
+ `@kitn.ai/ui` is **transport-agnostic**: every element renders a `messages` array and emits a
8
+ `submit` event. You bring the model; the kit owns the UI. It works in any framework — pick yours:
9
+ [HTML](?path=/docs/docs-frameworks-html--docs) · [React](?path=/docs/docs-frameworks-react--docs) · [Solid](?path=/docs/docs-frameworks-solid--docs) · [Vue](?path=/docs/docs-frameworks-vue--docs) · [Svelte](?path=/docs/docs-frameworks-svelte--docs) · [Angular](?path=/docs/docs-frameworks-angular--docs).
10
+ Recipes for streaming, text-to-speech, and speech-to-text live under **Docs/Recipes**.
11
+
12
+ ## Two ways to build
13
+
14
+ You can adopt the kit at whatever level you need — and mix the two freely:
15
+
16
+ 1. **`<kai-chat>` — the all-in-one shell.** One tag gives you a whole chat experience (message
17
+ thread, prompt input, model switcher, …). The fastest way to ship.
18
+ 2. **Compose the individual elements.** Assemble `<kai-conversations>`, `<kai-message>`,
19
+ `<kai-prompt-input>`, `<kai-markdown>`, `<kai-artifact>`, … into your own layout for full control —
20
+ or drop a single display element into an app you already have.
21
+
22
+ `<kai-chat>` is the quick start, **not** the only way in. Every framework page shows both paths,
23
+ and each element's **API** tab (under **Components**) lists its full props, events, and copy-paste
24
+ usage for every framework.
25
+
26
+ ## The #1 rule: properties vs. attributes
27
+
28
+ Arrays and objects **must** be set as JavaScript **properties** on the element — never as HTML
29
+ attributes. An HTML attribute is always a string, so passing `messages`, `models`, `context`,
30
+ `suggestions`, or `slashCommands` as an attribute silently fails.
31
+
32
+ ```js
33
+ const chat = document.querySelector('kai-chat');
34
+
35
+ // ✅ correct — set as a JS property
36
+ chat.messages = [{ id: '1', role: 'assistant', content: 'Hello!' }];
37
+
38
+ // ❌ wrong — an HTML attribute is always a string, never works
39
+ // <kai-chat messages="[...]"></kai-chat>
40
+ ```
41
+
42
+ Scalar values (strings, numbers, booleans) work fine as attributes: `placeholder`, `loading`,
43
+ `theme`, `prose-size`, and so on. Each framework's binding syntax (React props, Vue's `.prop`
44
+ modifier, Angular's `[prop]`, Svelte's `{prop}`) handles this for you — see your framework's page.
45
+
46
+ The kit ships **40+ elements**. SolidJS apps can also import the **native components** directly for
47
+ full compositional control — see the [Solid](?path=/docs/docs-frameworks-solid--docs) page and the **Solid (Advanced)** section.
@@ -0,0 +1,227 @@
1
+ import { Meta } from '@storybook/addon-docs/blocks';
2
+
3
+ <Meta title="Docs/Frameworks/React" />
4
+
5
+ # React
6
+
7
+ The kit ships auto-generated, **typed React wrappers** under `@kitn.ai/ui/react`. They hide the
8
+ custom-element plumbing — rich data goes in as React props (set as DOM **properties**, never
9
+ stringified) and CustomEvents come out as `on<Event>` handlers — so you write idiomatic JSX
10
+ without touching refs.
11
+
12
+ There are **two ways to build with the kit**, and you can mix them:
13
+
14
+ 1. **`<Chat>`** — the batteries-included shell: a whole chat experience in one tag. Fastest start.
15
+ 2. **Compose the individual elements** (`<Conversations>`, `<Markdown>`, `<Artifact>`, …) into
16
+ your own layout when you want full control.
17
+
18
+ Both are shown below.
19
+
20
+ ## Install & setup
21
+
22
+ ```bash
23
+ npm i @kitn.ai/ui
24
+ ```
25
+
26
+ Register the custom elements once (a side-effect import), then use the typed wrappers anywhere:
27
+
28
+ ```tsx
29
+ // Once, near your app entry — registers the <kai-*> elements globally.
30
+ import '@kitn.ai/ui/elements';
31
+
32
+ // Then import the wrappers you need (tree-shaken).
33
+ import { Chat, Conversations, Markdown } from '@kitn.ai/ui/react';
34
+ ```
35
+
36
+ - **`@kitn.ai/ui/react`** — the typed wrappers (recommended). Component names are the PascalCase
37
+ of the tag: `kai-chat → Chat`, `kai-prompt-input → PromptInput`.
38
+ - **`@kitn.ai/ui/elements`** — the raw custom elements, if you'd rather wire refs yourself
39
+ (see [Without the wrappers](#without-the-wrappers-raw-custom-element)).
40
+ - No CSS to import: each element is styled inside its own Shadow DOM. Only pull in
41
+ `@kitn.ai/ui/theme.css` if you want to override design tokens (see **Theming**).
42
+
43
+ > One name collides with a browser global: `kai-image → Image`. Alias it if you import it:
44
+ > `import { Image as KaiImage } from '@kitn.ai/ui/react'`.
45
+
46
+ ## Quick start — the all-in-one shell
47
+
48
+ `<Chat>` is **transport-agnostic**: give it a `messages` array, handle the `submit` event, and
49
+ stream your model's reply back into state. You own the request; the component owns the UI.
50
+
51
+ ```tsx
52
+ import '@kitn.ai/ui/elements';
53
+ import { Chat } from '@kitn.ai/ui/react';
54
+ import { useState } from 'react';
55
+
56
+ type Message = { id: string; role: 'user' | 'assistant'; content: string };
57
+
58
+ export function App() {
59
+ const [messages, setMessages] = useState<Message[]>([
60
+ { id: '1', role: 'assistant', content: 'Hello! How can I help?' },
61
+ ]);
62
+
63
+ const handleSubmit = async (e: CustomEvent<{ value: string }>) => {
64
+ const history = [...messages, { id: crypto.randomUUID(), role: 'user' as const, content: e.detail.value }];
65
+ setMessages(history);
66
+
67
+ const aid = crypto.randomUUID();
68
+ setMessages([...history, { id: aid, role: 'assistant', content: '' }]);
69
+
70
+ let answer = '';
71
+ for await (const token of streamFromYourAPI(history)) {
72
+ answer += token;
73
+ // Assign a NEW array (and a new object for the message you change) to trigger a re-render.
74
+ setMessages((prev) => prev.map((m) => (m.id === aid ? { ...m, content: answer } : m)));
75
+ }
76
+ };
77
+
78
+ // The elements are `display: block` and fill their container — lay them out with
79
+ // flex and let the element grow with `flex: 1` rather than hard-coding a height.
80
+ return (
81
+ <div style={{ display: 'flex', flexDirection: 'column', height: '100dvh' }}>
82
+ <Chat
83
+ messages={messages}
84
+ suggestions={['Summarize the chat', 'Start fresh']}
85
+ onSubmit={handleSubmit}
86
+ style={{ flex: 1, minHeight: 0 }}
87
+ />
88
+ </div>
89
+ );
90
+ }
91
+ ```
92
+
93
+ ## Go further — compose the pieces
94
+
95
+ `<Chat>` is one option, not the only one. Every element has its own wrapper, so you can assemble
96
+ your own layout. Here's a multi-conversation shell — a `<Conversations>` sidebar next to the
97
+ `<Chat>` thread:
98
+
99
+ ```tsx
100
+ import '@kitn.ai/ui/elements';
101
+ import { Chat, Conversations } from '@kitn.ai/ui/react';
102
+ import { useState } from 'react';
103
+
104
+ export function Workspace() {
105
+ const [conversations, setConversations] = useState(myConversations);
106
+ const [activeId, setActiveId] = useState(conversations[0]?.id);
107
+ const [messages, setMessages] = useState(loadMessages(activeId));
108
+
109
+ // Lay panels out with flex: the sidebar is fixed-width, the thread takes the rest
110
+ // with `flex: 1`. The elements fill whatever box you give them.
111
+ return (
112
+ <div style={{ display: 'flex', height: '100dvh' }}>
113
+ <Conversations
114
+ conversations={conversations}
115
+ activeId={activeId}
116
+ onConversationSelect={(e) => {
117
+ setActiveId(e.detail.id);
118
+ setMessages(loadMessages(e.detail.id));
119
+ }}
120
+ onNewChat={() => startNewConversation()}
121
+ style={{ width: 300, flexShrink: 0 }}
122
+ />
123
+
124
+ <Chat
125
+ messages={messages}
126
+ onSubmit={(e) => sendMessage(e.detail.value)}
127
+ style={{ flex: 1, minWidth: 0 }}
128
+ />
129
+ </div>
130
+ );
131
+ }
132
+ ```
133
+
134
+ ### Make the panels resizable
135
+
136
+ Want a draggable divider between the sidebar and the thread? Wrap the panels in `<Resizable>`
137
+ with one `<ResizableItem>` each — the handles are inserted for you (up to 3 panels). Each item
138
+ takes a `size` (px or `%`) plus optional `min`/`max`; listen for `onChange` (`detail.sizes`) to
139
+ persist the layout.
140
+
141
+ ```tsx
142
+ import { Chat, Conversations, Resizable, ResizableItem } from '@kitn.ai/ui/react';
143
+
144
+ <div style={{ display: 'flex', flexDirection: 'column', height: '100dvh' }}>
145
+ <Resizable orientation="horizontal" style={{ flex: 1, minHeight: 0 }}>
146
+ <ResizableItem size="25%" min="200px">
147
+ <Conversations conversations={conversations} activeId={activeId} onConversationSelect={handleSelect} />
148
+ </ResizableItem>
149
+ <ResizableItem>
150
+ <Chat messages={messages} onSubmit={handleSubmit} />
151
+ </ResizableItem>
152
+ </Resizable>
153
+ </div>
154
+ ```
155
+
156
+ You can also drop **standalone display elements** anywhere in your own UI — `<Markdown>`,
157
+ `<CodeBlock>`, `<Artifact>`, `<Reasoning>`, `<Tool>` — to render rich AI content without adopting
158
+ the whole chat. Each fills its container and is controlled via props and events.
159
+
160
+ > **See it all assembled:** **[Examples → Full Chat App](?path=/story/examples-full-chat-app--default)**
161
+ > wires a sidebar, threaded markdown, reasoning, a tool call, a model switcher, a context meter, and
162
+ > a rich prompt input into one screen — a working reference to crib from.
163
+
164
+ > **Find every element:** browse the **Components** section in the sidebar. Each element's **API**
165
+ > tab lists its props, events, and copy-paste usage for React (and every other framework).
166
+
167
+ ## Props & events
168
+
169
+ The rule for all elements: **rich data goes in as properties, interactions come out as events.**
170
+ The wrappers do this for you — pass arrays/objects as props and they're assigned as live DOM
171
+ properties (not stringified), while CustomEvents surface as `on<Event>` handlers.
172
+
173
+ Event props are `on` + the event name with the `kai-` prefix stripped and each
174
+ hyphen-segment PascalCased:
175
+
176
+ | DOM event | React prop |
177
+ |---|---|
178
+ | `kai-submit` | `onSubmit` |
179
+ | `kai-value-change` | `onValueChange` |
180
+ | `kai-message-action` | `onMessageAction` |
181
+ | `kai-model-change` | `onModelChange` |
182
+ | `kai-conversation-select` | `onConversationSelect` |
183
+ | `kai-suggestion-click` | `onSuggestionClick` |
184
+
185
+ All **40+ elements** have a typed wrapper:
186
+
187
+ ```tsx
188
+ import {
189
+ Chat, Conversations, PromptInput, Message, Markdown, CodeBlock,
190
+ Reasoning, Tool, Context, ModelSwitcher, Attachments, Loader,
191
+ // …every kai-* element
192
+ } from '@kitn.ai/ui/react';
193
+ ```
194
+
195
+ ## Without the wrappers (raw custom element)
196
+
197
+ Prefer the raw element (e.g. with React 19's improved custom-element support)? Use a `ref` to set
198
+ object props and wire events:
199
+
200
+ ```tsx
201
+ import { useEffect, useRef, useState } from 'react';
202
+ import '@kitn.ai/ui/elements';
203
+
204
+ export function RawChat() {
205
+ const ref = useRef<HTMLElement>(null);
206
+ const [messages, setMessages] = useState([{ id: '1', role: 'assistant', content: 'Hello!' }]);
207
+
208
+ useEffect(() => {
209
+ const el = ref.current;
210
+ if (!el) return;
211
+ (el as any).messages = messages; // object/array props can't go through attributes
212
+ }, [messages]);
213
+
214
+ useEffect(() => {
215
+ const el = ref.current;
216
+ if (!el) return;
217
+ const onSubmit = (e: Event) => {
218
+ const { value } = (e as CustomEvent<{ value: string }>).detail;
219
+ setMessages((prev) => [...prev, { id: crypto.randomUUID(), role: 'user', content: value }]);
220
+ };
221
+ el.addEventListener('kai-submit', onSubmit);
222
+ return () => el.removeEventListener('kai-submit', onSubmit);
223
+ }, []);
224
+
225
+ return <kai-chat ref={ref} style={{ display: 'block', height: '100vh' }} />;
226
+ }
227
+ ```
@@ -0,0 +1,173 @@
1
+ import { Meta } from '@storybook/addon-docs/blocks';
2
+
3
+ <Meta title="Docs/Frameworks/Solid" />
4
+
5
+ # Solid
6
+
7
+ The kit is **authored in SolidJS** — the `<kai-*>` web components are compiled from these very
8
+ components. So Solid devs get the richest path of any framework, with **two ways to build** that
9
+ you can freely mix:
10
+
11
+ 1. **Native SolidJS components** (`@kitn.ai/ui`) — `ChatContainer`, `Message`, `PromptInput`, and
12
+ the rest, composed in your own JSX. Full compositional control and the smallest output for a
13
+ Solid app. **This is the recommended Solid path.**
14
+ 2. The same framework-agnostic **`<kai-*>` web components** (`@kitn.ai/ui/elements`) — the
15
+ drop-in shells (`<kai-chat>`, …) when you just want batteries included.
16
+
17
+ Both work in the same app; reach for whichever fits the surface you're building.
18
+
19
+ ## Install & setup
20
+
21
+ ```bash
22
+ npm i @kitn.ai/ui
23
+ ```
24
+
25
+ `solid-js` is a peer dependency — install it if you haven't already:
26
+
27
+ ```bash
28
+ npm i solid-js
29
+ ```
30
+
31
+ Import the design tokens **once**, near your app entry:
32
+
33
+ ```ts
34
+ import '@kitn.ai/ui/theme.css';
35
+ ```
36
+
37
+ The `@kitn.ai/ui` entry ships as **source** (TSX), so your bundler compiles and tree-shakes it
38
+ alongside your own Solid code — you only pay for what you import.
39
+
40
+ ## Quick start — native components
41
+
42
+ Compose the native components directly in your JSX. Drive the prompt input with a `createSignal`,
43
+ and let the components fill their container — size them with flex / `class="h-full"` rather than a
44
+ hard-coded `height: 100vh`.
45
+
46
+ ```tsx
47
+ import {
48
+ ChatConfig, ChatContainer, ChatContainerContent,
49
+ Message, MessageContent,
50
+ PromptInput, PromptInputTextarea, PromptInputActions,
51
+ } from '@kitn.ai/ui';
52
+ import '@kitn.ai/ui/theme.css';
53
+ import { createSignal } from 'solid-js';
54
+
55
+ function Chat() {
56
+ const [input, setInput] = createSignal('');
57
+
58
+ // The components fill their box — give them a flex parent and let
59
+ // ChatContainer grow with `h-full`/flex rather than a fixed viewport height.
60
+ return (
61
+ <div class="flex flex-col h-full">
62
+ <ChatConfig proseSize="sm">
63
+ <ChatContainer class="h-full">
64
+ <ChatContainerContent class="space-y-4 p-4">
65
+ <Message>
66
+ <MessageContent markdown>{`Ask me anything.`}</MessageContent>
67
+ </Message>
68
+ </ChatContainerContent>
69
+ </ChatContainer>
70
+ <PromptInput value={input()} onValueChange={setInput} onSubmit={() => setInput('')}>
71
+ <PromptInputTextarea placeholder="Ask anything..." />
72
+ <PromptInputActions>{/* your buttons */}</PromptInputActions>
73
+ </PromptInput>
74
+ </ChatConfig>
75
+ </div>
76
+ );
77
+ }
78
+ ```
79
+
80
+ `<ChatContainer>` is **transport-agnostic**: it owns the conversation UI, you own the request.
81
+ Render your message list inside `<ChatContainerContent>` (a `<For>` over your signal of messages),
82
+ and append the user turn — then stream the assistant reply — in `onSubmit`.
83
+
84
+ ## Go further — compose & the web components
85
+
86
+ ### The native components *are* the granular composition
87
+
88
+ There's no separate "advanced" component set — the pieces above (`ChatContainer`, `Message`,
89
+ `PromptInput`) plus the feature components (`Markdown`, `CodeBlock`, `Reasoning`, `Tool`,
90
+ `Conversations`, `ModelSwitcher`, …) **are** the building blocks. Assemble them into any layout you
91
+ like: a sidebar next to a thread, a split view, a custom composer — it's all just Solid JSX.
92
+
93
+ For a resizable layout, use the native `Resizable` convenience component with one `ResizablePanel`
94
+ per pane (handles are auto-inserted between visible panels). Each panel takes `defaultSize`
95
+ (px or `%`) plus optional `minSize`/`maxSize`; listen for `onChange` (an array of percent sizes) to
96
+ persist the layout.
97
+
98
+ ```tsx
99
+ import { Resizable, ResizablePanel } from '@kitn.ai/ui';
100
+
101
+ function Workspace() {
102
+ return (
103
+ <div class="flex flex-col h-full">
104
+ <Resizable orientation="horizontal" withHandle onChange={(sizes) => persist(sizes)}>
105
+ <ResizablePanel defaultSize="25%" minSize="200px">
106
+ {/* your conversation sidebar */}
107
+ </ResizablePanel>
108
+ <ResizablePanel>
109
+ {/* the message thread + prompt input */}
110
+ </ResizablePanel>
111
+ </Resizable>
112
+ </div>
113
+ );
114
+ }
115
+ ```
116
+
117
+ > **Full reference:** the **[Solid (Advanced)](?path=/docs/solid-advanced-overview--docs)** sidebar
118
+ > tier documents every native building block — the composed **Elements** (message, tool, reasoning,
119
+ > …) and the low-level **Primitives** (button, tooltip, dropdown, …) they're built on.
120
+
121
+ ### Prefer the drop-in shell? Use the web component
122
+
123
+ When you just want a whole chat in one tag, register the `<kai-*>` elements and use `<kai-chat>`.
124
+ Solid sets rich data as DOM **properties** on custom elements (so arrays/objects pass through
125
+ without stringifying), and you listen for CustomEvents with Solid's `on:` namespace:
126
+
127
+ ```tsx
128
+ import '@kitn.ai/ui/elements'; // registers the <kai-*> elements once
129
+ import { createSignal } from 'solid-js';
130
+
131
+ function Shell() {
132
+ const [messages, setMessages] = createSignal([
133
+ { id: '1', role: 'assistant', content: 'Hello! How can I help?' },
134
+ ]);
135
+
136
+ const onSubmit = (e: CustomEvent<{ value: string }>) => {
137
+ setMessages((prev) => [
138
+ ...prev,
139
+ { id: crypto.randomUUID(), role: 'user', content: e.detail.value },
140
+ ]);
141
+ // ...call your model, then append an assistant message
142
+ };
143
+
144
+ return (
145
+ <div class="flex flex-col h-full">
146
+ <kai-chat
147
+ // `prop:` forces a property assignment (not an attribute) for rich data.
148
+ prop:messages={messages()}
149
+ on:kai-submit={onSubmit}
150
+ style={{ flex: 1, 'min-height': 0 }}
151
+ />
152
+ </div>
153
+ );
154
+ }
155
+ ```
156
+
157
+ For a resizable web-component layout, use `<kai-resizable>` the same way (set properties, listen
158
+ with `on:`) — though in a Solid app the native `Resizable` above gives you tighter control.
159
+
160
+ > **See it all assembled:** **[Examples → Full Chat App](?path=/story/examples-full-chat-app--default)**
161
+ > wires a sidebar, threaded markdown, reasoning, a tool call, a model switcher, a context meter, and
162
+ > a rich prompt input into one screen — a working reference to crib from.
163
+
164
+ ## When to use which
165
+
166
+ - **Native components** (`@kitn.ai/ui`) — full compositional control and the **smallest output**
167
+ for a Solid app, since they compile and tree-shake with your own code. The recommended path when
168
+ you're building in Solid.
169
+ - **Web components** (`@kitn.ai/ui/elements`) — the **fastest drop-in** and fully
170
+ framework-agnostic. Reach for `<kai-chat>` (or any `<kai-*>` shell) when you want batteries included
171
+ or you're sharing UI across frameworks.
172
+
173
+ Mix freely: a native composed thread on one screen, a drop-in `<kai-chat>` on another.
@@ -0,0 +1,194 @@
1
+ import { Meta } from '@storybook/addon-docs/blocks';
2
+
3
+ <Meta title="Docs/Frameworks/Svelte" />
4
+
5
+ # Svelte
6
+
7
+ Custom elements are **first-class citizens in Svelte**: the compiler sets DOM properties directly
8
+ when you pass non-primitive values, and `on:eventname` wires up CustomEvents with no extra
9
+ boilerplate. No wrappers, no refs, no workarounds needed.
10
+
11
+ There are **two ways to build with the kit**, and you can mix them:
12
+
13
+ 1. **`<kai-chat>`** — the batteries-included shell: a whole chat experience in one tag. Fastest start.
14
+ 2. **Compose the individual elements** (`<kai-conversations>`, `<kai-markdown>`, `<kai-artifact>`, …)
15
+ into your own layout when you want full control.
16
+
17
+ Both are shown below.
18
+
19
+ ## Install & setup
20
+
21
+ ```bash
22
+ npm i @kitn.ai/ui
23
+ ```
24
+
25
+ Register the custom elements once (a side-effect import) near your app entry:
26
+
27
+ ```js
28
+ // e.g. src/main.js or src/app.svelte <script>
29
+ import '@kitn.ai/ui/elements';
30
+ ```
31
+
32
+ - **`@kitn.ai/ui/elements`** — registers every `<kai-*>` element globally. One import is enough
33
+ for the whole app.
34
+ - **No special config needed**: Svelte sets object and array values as DOM **properties** (not
35
+ stringified attributes) when you use the `{prop}` shorthand or `prop={value}` syntax. Custom
36
+ events fire as standard DOM `CustomEvent`s, so `on:eventname` just works.
37
+ - **No CSS to import**: each element is styled inside its own Shadow DOM. Pull in
38
+ `@kitn.ai/ui/theme.css` only if you want to override design tokens (see **Theming**).
39
+
40
+ ## Quick start — the all-in-one shell
41
+
42
+ `<kai-chat>` is **transport-agnostic**: give it a `messages` array, handle the `submit` event, and
43
+ stream your model's reply back into state. You own the request; the element owns the UI.
44
+
45
+ ```html
46
+ <script>
47
+ import '@kitn.ai/ui/elements';
48
+
49
+ let messages = [
50
+ { id: '1', role: 'assistant', content: 'Hello! How can I help?' },
51
+ ];
52
+
53
+ async function handleSubmit(e) {
54
+ const userContent = e.detail.value;
55
+ const history = [...messages, { id: crypto.randomUUID(), role: 'user', content: userContent }];
56
+ messages = history;
57
+
58
+ const aid = crypto.randomUUID();
59
+ messages = [...history, { id: aid, role: 'assistant', content: '' }];
60
+
61
+ let answer = '';
62
+ for await (const token of streamFromYourAPI(history)) {
63
+ answer += token;
64
+ // Reassign the array (and the changed object) so Svelte detects the update.
65
+ messages = messages.map((m) => (m.id === aid ? { ...m, content: answer } : m));
66
+ }
67
+ }
68
+ </script>
69
+
70
+ <!--
71
+ The elements are `display: block` and fill their container — lay them out with
72
+ flex and let the element grow with `flex: 1` rather than hard-coding a height.
73
+ -->
74
+ <div style="display: flex; flex-direction: column; height: 100dvh;">
75
+ <kai-chat
76
+ {messages}
77
+ suggestions={['Summarize the chat', 'Start fresh']}
78
+ on:kai-submit={handleSubmit}
79
+ style="flex: 1; min-height: 0;"
80
+ />
81
+ </div>
82
+ ```
83
+
84
+ > **`{messages}`** is Svelte shorthand for `messages={messages}`. Because the value is an array,
85
+ > Svelte assigns it as a DOM **property** (not an attribute), so the element always receives a live
86
+ > JS array — never a stringified version. The same applies to any object prop.
87
+
88
+ ## Go further — compose the pieces
89
+
90
+ `<kai-chat>` is one option, not the only one. Every element can be used on its own, so you can
91
+ assemble your own layout. Here's a multi-conversation shell — a `<kai-conversations>` sidebar next
92
+ to the `<kai-chat>` thread:
93
+
94
+ ```html
95
+ <script>
96
+ import '@kitn.ai/ui/elements';
97
+
98
+ let conversations = myConversations;
99
+ let activeId = conversations[0]?.id;
100
+ let messages = loadMessages(activeId);
101
+
102
+ function handleConversationSelect(e) {
103
+ activeId = e.detail.id;
104
+ messages = loadMessages(activeId);
105
+ }
106
+ </script>
107
+
108
+ <!--
109
+ Lay panels out with flex: the sidebar is fixed-width, the thread takes the rest
110
+ with `flex: 1`. The elements fill whatever box you give them.
111
+ -->
112
+ <div style="display: flex; height: 100dvh;">
113
+ <kai-conversations
114
+ {conversations}
115
+ {activeId}
116
+ on:kai-conversation-select={handleConversationSelect}
117
+ on:kai-new-chat={() => startNewConversation()}
118
+ on:kai-toggle-sidebar={() => sidebarOpen = !sidebarOpen}
119
+ style="width: 300px; flex-shrink: 0;"
120
+ />
121
+
122
+ <kai-chat
123
+ {messages}
124
+ on:kai-submit={(e) => sendMessage(e.detail.value)}
125
+ style="flex: 1; min-width: 0;"
126
+ />
127
+ </div>
128
+ ```
129
+
130
+ ### Make the panels resizable
131
+
132
+ Want a draggable divider between the sidebar and the thread? Wrap the panels in `<kai-resizable>`
133
+ with one `<kai-resizable-item>` each — the handles are inserted for you (up to 3 panels). Each item
134
+ takes a `size` (px or `%`) plus optional `min`/`max`; listen for the `change` event
135
+ (`detail.sizes`) to persist the layout.
136
+
137
+ ```html
138
+ <script>
139
+ import '@kitn.ai/ui/elements';
140
+
141
+ function handleResize(e) {
142
+ // e.detail.sizes is an array of the current panel sizes
143
+ savePanelSizes(e.detail.sizes);
144
+ }
145
+ </script>
146
+
147
+ <div style="display: flex; flex-direction: column; height: 100dvh;">
148
+ <kai-resizable orientation="horizontal" on:kai-change={handleResize} style="flex: 1; min-height: 0;">
149
+ <kai-resizable-item size="25%" min="200px">
150
+ <kai-conversations {conversations} {activeId} on:kai-conversation-select={handleConversationSelect} />
151
+ </kai-resizable-item>
152
+ <kai-resizable-item>
153
+ <kai-chat {messages} on:kai-submit={handleSubmit} />
154
+ </kai-resizable-item>
155
+ </kai-resizable>
156
+ </div>
157
+ ```
158
+
159
+ You can also drop **standalone display elements** anywhere in your own UI — `<kai-markdown>`,
160
+ `<kai-code-block>`, `<kai-artifact>`, `<kai-reasoning>`, `<kai-tool>` — to render rich AI content
161
+ without adopting the whole chat shell. Each fills its container and is controlled via props and
162
+ events.
163
+
164
+ > **See it all assembled:** **[Examples → Full Chat App](?path=/story/examples-full-chat-app--default)**
165
+ > wires a sidebar, threaded markdown, reasoning, a tool call, a model switcher, a context meter, and
166
+ > a rich prompt input into one screen — a working reference to crib from.
167
+
168
+ > **Find every element:** browse the **Components** section in the sidebar. Each element's **API**
169
+ > tab lists its props, events, and copy-paste usage for Svelte (and every other framework).
170
+
171
+ ## Props & events
172
+
173
+ The rule for all elements: **rich data goes in as properties, interactions come out as events.**
174
+
175
+ In Svelte, this maps cleanly to the template syntax you already know:
176
+
177
+ | What | Svelte syntax | Notes |
178
+ |---|---|---|
179
+ | Pass a string | `prop="value"` or `{prop}` shorthand | Standard attribute or property |
180
+ | Pass an array / object | `{prop}` or `prop={value}` | Svelte assigns as DOM property — no stringification |
181
+ | Listen to a CustomEvent | `on:eventname={handler}` | `handler(e)` receives the `CustomEvent`; data is on `e.detail` |
182
+
183
+ Key events and their `detail` shapes:
184
+
185
+ | Element | Event | `e.detail` |
186
+ |---|---|---|
187
+ | `kai-chat` | `submit` | `{ value: string }` — the user's input text |
188
+ | `kai-conversations` | `conversationselect` | `{ id: string }` — the selected conversation id |
189
+ | `kai-conversations` | `newchat` | `{}` |
190
+ | `kai-conversations` | `togglesidebar` | `{}` |
191
+ | `kai-resizable` | `change` | `{ sizes: string[] }` — current panel sizes |
192
+
193
+ No adapters, no special directives: Svelte's compiler handles property assignment on custom elements
194
+ automatically, so `{messages}` always delivers a live JS array to the element.