@kitn.ai/ui 0.18.1 → 0.19.0

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 (203) hide show
  1. package/dist/components/thread.d.ts +54 -0
  2. package/dist/custom-elements.json +195 -0
  3. package/dist/elements/agent-card.js +1 -1
  4. package/dist/elements/artifact.js +1 -1
  5. package/dist/elements/attachments.js +1 -1
  6. package/dist/elements/autoloader.js +1 -1
  7. package/dist/elements/avatar.js +1 -1
  8. package/dist/elements/badge.js +1 -1
  9. package/dist/elements/button.js +1 -1
  10. package/dist/elements/card.js +1 -1
  11. package/dist/elements/cards.js +1 -1
  12. package/dist/elements/chain-of-thought.js +1 -1
  13. package/dist/elements/chat-scope-picker.js +1 -1
  14. package/dist/elements/chat-workspace.js +1 -1
  15. package/dist/elements/chat.js +1 -1
  16. package/dist/elements/checkpoint.js +1 -1
  17. package/dist/elements/choice.js +1 -1
  18. package/dist/elements/chunks/{Icon-C2LTALdM.js → Icon-11SRdjJ4.js} +1 -1
  19. package/dist/elements/chunks/action-icons-CtRg17uX.js +1 -0
  20. package/dist/elements/chunks/arrow-left-CifsGq8x.js +1 -0
  21. package/dist/elements/chunks/{attachments-DLJcWCDV.js → attachments-CBqQRh60.js} +1 -1
  22. package/dist/elements/chunks/{badge-BTNZTODL.js → badge-CxklEXQm.js} +1 -1
  23. package/dist/elements/chunks/{button-DBDZebGr.js → button-BD7lUvVB.js} +1 -1
  24. package/dist/elements/chunks/{card-YfCyI4fH.js → card-B-PRGXdj.js} +1 -1
  25. package/dist/elements/chunks/chat-thread-DIZbRIKG.js +1 -0
  26. package/dist/elements/chunks/check-CUKS495w.js +1 -0
  27. package/dist/elements/chunks/chevron-down-AELmYT1j.js +1 -0
  28. package/dist/elements/chunks/chevron-right-C8g26oKh.js +1 -0
  29. package/dist/elements/chunks/circle-DGcI8Cft.js +1 -0
  30. package/dist/elements/chunks/circle-check-DuU0IcBQ.js +1 -0
  31. package/dist/elements/chunks/{circle-x-pDtzlghQ.js → circle-x-mtjCO_Ok.js} +1 -1
  32. package/dist/elements/chunks/{code-block-DZ6mz6vs.js → code-block-BeWVttmU.js} +1 -1
  33. package/dist/elements/chunks/{collapsible-CWUAShMC.js → collapsible-DGjADCN6.js} +1 -1
  34. package/dist/elements/chunks/{composer-BZyPU6gD.js → composer-CavJww3d.js} +7 -3
  35. package/dist/elements/chunks/{context-Cx6eQA_G.js → context-CnlsNJSJ.js} +1 -1
  36. package/dist/elements/chunks/{conversation-list-C4xTQSpT.js → conversation-list-5O_KdI_I.js} +1 -1
  37. package/dist/elements/chunks/{default-input-BZcwyKcP.js → default-input-CB46cJJ1.js} +1 -1
  38. package/dist/elements/chunks/{define-CNSKFZCd.js → define-DfTe4zwZ.js} +1 -1
  39. package/dist/elements/chunks/{disclosure-BcBs--Jf.js → disclosure-BtFK3a-M.js} +1 -1
  40. package/dist/elements/chunks/{download-BDQwcFav.js → download-qJv1dS3M.js} +1 -1
  41. package/dist/elements/chunks/{dropdown-wgs8xCJZ.js → dropdown-UhtAueYR.js} +1 -1
  42. package/dist/elements/chunks/{ellipsis-CUiEJ6R1.js → ellipsis-B1sOOqiJ.js} +1 -1
  43. package/dist/elements/chunks/{external-link-DJUmC7g2.js → external-link-DToP_VKE.js} +1 -1
  44. package/dist/elements/chunks/{file-text-DOYfYvrh.js → file-text-BwUs_Pj4.js} +1 -1
  45. package/dist/elements/chunks/{file-tree-DQzNQrbr.js → file-tree-C6RhmSnX.js} +1 -1
  46. package/dist/elements/chunks/{folder-DBDUBANz.js → folder-H_Xp0GYP.js} +1 -1
  47. package/dist/elements/chunks/hover-card-Dn3yrk1l.js +1 -0
  48. package/dist/elements/chunks/icon-BrxJQXzC.js +1 -0
  49. package/dist/elements/chunks/{info-DBQl-m6e.js → info-11eT2q5H.js} +1 -1
  50. package/dist/elements/chunks/{input-DZD67EvW.js → input-B9oZKDfb.js} +1 -1
  51. package/dist/elements/chunks/{kbd-DbyVrlnU.js → kbd-D2fx3rWh.js} +1 -1
  52. package/dist/elements/chunks/{link-vko7AttA.js → link-B-RNYWNw.js} +1 -1
  53. package/dist/elements/chunks/{loader-Cg6rO8tQ.js → loader-BJh_aRlp.js} +1 -1
  54. package/dist/elements/chunks/{markdown-n3Xbj3PR.js → markdown-BIpjrDFv.js} +1 -1
  55. package/dist/elements/chunks/{message-CgKytiSB.js → message-CPfqj8Gi.js} +1 -1
  56. package/dist/elements/chunks/{message-feedback-Ds3-US0e.js → message-feedback-8uj0aVYh.js} +1 -1
  57. package/dist/elements/chunks/message-square-CCSQ4M9g.js +1 -0
  58. package/dist/elements/chunks/{minimize-2-3kCdE0q3.js → minimize-2-C9qkiTJg.js} +1 -1
  59. package/dist/elements/chunks/{model-switcher-BMtXGwLU.js → model-switcher-DRrMcRXH.js} +1 -1
  60. package/dist/elements/chunks/{overlay-B1-MBI6h.js → overlay-C8_FUL8q.js} +1 -1
  61. package/dist/elements/chunks/{paperclip-DDEfmkHc.js → paperclip-MA9hxLhW.js} +1 -1
  62. package/dist/elements/chunks/{progress-bar-Dwbiyv3s.js → progress-bar-y5G6HDjg.js} +1 -1
  63. package/dist/elements/chunks/{prompt-suggestion-9lvgFcEa.js → prompt-suggestion-LalWvCJy.js} +1 -1
  64. package/dist/elements/chunks/reasoning-CW3SDdb4.js +1 -0
  65. package/dist/elements/chunks/resizable-xhYF5lCQ.js +1 -0
  66. package/dist/elements/chunks/{rotate-cw-jpisOdOV.js → rotate-cw-2ndEXjgS.js} +1 -1
  67. package/dist/elements/chunks/{scroll-area-g5Ze3K6f.js → scroll-area-BzOPDXrZ.js} +1 -1
  68. package/dist/elements/chunks/scroll-button-B1x4cYqM.js +1 -0
  69. package/dist/elements/chunks/{separator-Bmjc5XyX.js → separator-CPvL5Xdl.js} +1 -1
  70. package/dist/elements/chunks/{settings-group-9imY3kRA.js → settings-group-BiIym17O.js} +1 -1
  71. package/dist/elements/chunks/{settings-Cz1bMJP9.js → settings-hmzIuNXD.js} +1 -1
  72. package/dist/elements/chunks/{share-BdenF0wQ.js → share-BbziTAzn.js} +1 -1
  73. package/dist/elements/chunks/skeleton-Bxhs1thL.js +1 -0
  74. package/dist/elements/chunks/{slots-DkZ-Cmha.js → slots--V19HwUb.js} +1 -1
  75. package/dist/elements/chunks/{star-DY6z1UUH.js → star-BHL3Va5p.js} +1 -1
  76. package/dist/elements/chunks/{store-th4VyJXM.js → store-tpnnWlxY.js} +1 -1
  77. package/dist/elements/chunks/{text-shimmer-CEi-tlXr.js → text-shimmer-1DCKivKx.js} +1 -1
  78. package/dist/elements/chunks/textarea-Czaowo9F.js +1 -0
  79. package/dist/elements/chunks/{thumbs-up-BR33KLfA.js → thumbs-up-CdLqA13R.js} +1 -1
  80. package/dist/elements/chunks/{toast-store-BEMda0fv.js → toast-store-BvBquUFA.js} +1 -1
  81. package/dist/elements/chunks/{tool-TMued3WO.js → tool-4P_ne8Go.js} +1 -1
  82. package/dist/elements/chunks/{tooltip-Cft_Rxiw.js → tooltip-CBeFqJKk.js} +1 -1
  83. package/dist/elements/chunks/{triangle-alert-B07fX3Q8.js → triangle-alert-BllqxXq8.js} +1 -1
  84. package/dist/elements/chunks/{use-card-resolution-M36zVciB.js → use-card-resolution-73xiddIW.js} +1 -1
  85. package/dist/elements/chunks/{video-MKp3LmNT.js → video-O9rA6k7S.js} +1 -1
  86. package/dist/elements/chunks/x-DeS3rQhx.js +1 -0
  87. package/dist/elements/coachmark.js +1 -1
  88. package/dist/elements/code-block.js +1 -1
  89. package/dist/elements/command.js +1 -1
  90. package/dist/elements/compare.js +1 -1
  91. package/dist/elements/composer.js +1 -1
  92. package/dist/elements/confirm-card.js +1 -1
  93. package/dist/elements/context-meter.js +1 -1
  94. package/dist/elements/conversation-list.js +1 -1
  95. package/dist/elements/dialog.js +1 -1
  96. package/dist/elements/editable-label.js +1 -1
  97. package/dist/elements/embed.js +1 -1
  98. package/dist/elements/empty.js +1 -1
  99. package/dist/elements/feedback-bar.js +1 -1
  100. package/dist/elements/file-tree.js +1 -1
  101. package/dist/elements/file-upload.js +1 -1
  102. package/dist/elements/form.js +1 -1
  103. package/dist/elements/hover-card.js +1 -1
  104. package/dist/elements/icon.js +1 -1
  105. package/dist/elements/image.js +1 -1
  106. package/dist/elements/input.js +1 -1
  107. package/dist/elements/kbd.js +1 -1
  108. package/dist/elements/link-preview.js +1 -1
  109. package/dist/elements/loader.js +1 -1
  110. package/dist/elements/markdown.js +1 -1
  111. package/dist/elements/menu.js +1 -1
  112. package/dist/elements/message-skills.js +1 -1
  113. package/dist/elements/message.js +1 -1
  114. package/dist/elements/model-switcher.js +1 -1
  115. package/dist/elements/nav.js +1 -1
  116. package/dist/elements/notice.js +1 -1
  117. package/dist/elements/pane-group.js +1 -1
  118. package/dist/elements/pane.js +1 -1
  119. package/dist/elements/popover.js +1 -1
  120. package/dist/elements/progress-bar.js +1 -1
  121. package/dist/elements/prompt-dock.js +1 -1
  122. package/dist/elements/prompt-input.js +1 -1
  123. package/dist/elements/prompt-suggestions.js +1 -1
  124. package/dist/elements/reasoning.js +1 -1
  125. package/dist/elements/remote.js +1 -1
  126. package/dist/elements/resizable.js +1 -1
  127. package/dist/elements/response-stream.js +1 -1
  128. package/dist/elements/screen.js +1 -1
  129. package/dist/elements/scroll-area.js +1 -1
  130. package/dist/elements/scroll-button.js +1 -1
  131. package/dist/elements/search.js +1 -1
  132. package/dist/elements/segmented.js +1 -1
  133. package/dist/elements/separator.js +1 -1
  134. package/dist/elements/setting-item.js +1 -1
  135. package/dist/elements/settings-group.js +1 -1
  136. package/dist/elements/skeleton.js +1 -1
  137. package/dist/elements/slots.d.ts +3 -0
  138. package/dist/elements/source.js +1 -1
  139. package/dist/elements/status.js +1 -1
  140. package/dist/elements/switch.js +1 -1
  141. package/dist/elements/tabs.js +1 -1
  142. package/dist/elements/tasks.js +1 -1
  143. package/dist/elements/text-shimmer.js +1 -1
  144. package/dist/elements/thinking-bar.js +1 -1
  145. package/dist/elements/thread.d.ts +1 -0
  146. package/dist/elements/thread.js +1 -0
  147. package/dist/elements/toast.js +1 -1
  148. package/dist/elements/tool.js +1 -1
  149. package/dist/elements/tooltip.js +1 -1
  150. package/dist/elements/voice-input.js +1 -1
  151. package/dist/elements/voice-output.js +1 -1
  152. package/dist/elements.d.ts +24 -0
  153. package/dist/index.js +3393 -3311
  154. package/dist/kai.es.js +1 -1
  155. package/dist/llms/llms-full.txt +34 -4
  156. package/dist/llms/llms.txt +3 -3
  157. package/dist/react/index.d.ts +64 -0
  158. package/dist/react/use-voice-input.d.ts +15 -0
  159. package/dist/react.js +263 -240
  160. package/dist/register-impl-CaaHJcea.js +145 -0
  161. package/dist/ui/resizable.d.ts +9 -3
  162. package/frameworks/react/index.tsx +32 -1
  163. package/frameworks/react/use-voice-input.tsx +59 -0
  164. package/llms-full.txt +34 -4
  165. package/llms.txt +3 -3
  166. package/package.json +27 -5
  167. package/src/components/component-meta.json +30 -28
  168. package/src/components/composer.tsx +5 -0
  169. package/src/components/thread.tsx +177 -0
  170. package/src/elements/chat-workspace.tsx +1 -1
  171. package/src/elements/compiled.css +1 -1
  172. package/src/elements/element-manifest.json +4 -0
  173. package/src/elements/element-meta.json +117 -0
  174. package/src/elements/element-types.d.ts +24 -0
  175. package/src/elements/icon-names.json +2 -0
  176. package/src/elements/menu.tsx +7 -4
  177. package/src/elements/register-impl.ts +2 -0
  178. package/src/elements/resizable.tsx +78 -2
  179. package/src/elements/search.tsx +1 -1
  180. package/src/elements/slots.ts +7 -0
  181. package/src/elements/thread.tsx +105 -0
  182. package/src/ui/action-icons.ts +2 -1
  183. package/src/ui/command.tsx +5 -1
  184. package/src/ui/icon.tsx +4 -0
  185. package/src/ui/overlay.tsx +8 -1
  186. package/src/ui/resizable.tsx +47 -9
  187. package/dist/elements/chunks/action-icons-Dtl8Ox5D.js +0 -1
  188. package/dist/elements/chunks/arrow-left-GbBceGBE.js +0 -1
  189. package/dist/elements/chunks/chat-thread-Dz2qbzvI.js +0 -1
  190. package/dist/elements/chunks/check-fhmRksq_.js +0 -1
  191. package/dist/elements/chunks/chevron-down-DcRg1aRU.js +0 -1
  192. package/dist/elements/chunks/chevron-right-ChzBcNJ-.js +0 -1
  193. package/dist/elements/chunks/circle-B4fTe9v6.js +0 -1
  194. package/dist/elements/chunks/circle-check-CJV-3Rem.js +0 -1
  195. package/dist/elements/chunks/hover-card-BQGdGAQ3.js +0 -1
  196. package/dist/elements/chunks/icon-CAyRqVrg.js +0 -1
  197. package/dist/elements/chunks/message-square-MmRkvc-M.js +0 -1
  198. package/dist/elements/chunks/reasoning-DzHWsdAJ.js +0 -1
  199. package/dist/elements/chunks/resizable-Bq_eHxUm.js +0 -1
  200. package/dist/elements/chunks/skeleton-Pjc5jiaY.js +0 -1
  201. package/dist/elements/chunks/textarea-CboigarR.js +0 -1
  202. package/dist/elements/chunks/x-Ckwicf6g.js +0 -1
  203. package/dist/register-impl-cKscku5m.js +0 -141
@@ -855,6 +855,10 @@ export function Composer(props: ComposerProps): JSX.Element {
855
855
  .kai-composer-pill-glyph svg { width: 1em; height: 1em; display: block; }
856
856
  /* The editable is the containing block for the placeholder pseudo-element. */
857
857
  [data-kai-composer-editable] { position: relative; }
858
+ /* While a pill is arrow-selected the pill IS the selection, so hide the text
859
+ caret so a blinking cursor doesn't sit beside the highlight box. Returns
860
+ the moment the pill selection clears (arrow off, type, click, backspace). */
861
+ [data-kai-composer-editable][data-pill-selected] { caret-color: transparent; }
858
862
  /* Placeholder via pseudo-element — exempt from axe color-contrast like a
859
863
  native <textarea> placeholder. position:absolute (with auto offsets =
860
864
  its static text-origin spot) takes it OUT of flow, so the caret sits at
@@ -874,6 +878,7 @@ export function Composer(props: ComposerProps): JSX.Element {
874
878
  <div
875
879
  ref={(el) => { editable = el; props.editableRef?.(el); }}
876
880
  data-kai-composer-editable
881
+ data-pill-selected={selectedPill() ? '' : undefined}
877
882
  data-placeholder={props.placeholder ?? ''}
878
883
  contentEditable={props.disabled ? false : ('plaintext-only' as unknown as boolean)}
879
884
  role="textbox"
@@ -0,0 +1,177 @@
1
+ import { For, Show, onMount, type JSX } from 'solid-js';
2
+ import { ChatConfig, useChatConfig } from '../primitives/chat-config';
3
+ import { ChatContainer, ChatContainerContent, ChatContainerScrollAnchor } from './chat-container';
4
+ import { Message, MessageAvatar, MessageBody } from './message';
5
+ import { createMessageFeedback, type MessageActionDetail } from '../primitives/message-feedback';
6
+ import { ScrollButton } from './scroll-button';
7
+ import { Loader } from './loader';
8
+ import type { ChatMessage } from '../elements/chat-types';
9
+ import type { ProseSize } from '../primitives/chat-config';
10
+
11
+ /** Imperative handle exposed via `controllerRef` — the thread's scroll control,
12
+ * forwarded onto `<kai-thread>` as the `scrollToBottom()` instance method. */
13
+ export interface ThreadController {
14
+ /** Scroll the message list to the bottom (default `'smooth'`). */
15
+ scrollToBottom(behavior?: ScrollBehavior): void;
16
+ }
17
+
18
+ export interface ThreadProps {
19
+ /** Extra classes for the thread root (e.g. `rounded-xl`). */
20
+ class?: string;
21
+ /** The full message thread to render, newest last. Each entry carries its role,
22
+ * content, and optional reasoning/tools/attachments/actions/avatar. A new array
23
+ * reference per streaming chunk re-renders (mutating in place does not). */
24
+ messages: ChatMessage[];
25
+ /** Show a typing indicator on the pending assistant turn — use while awaiting
26
+ * the assistant's reply. */
27
+ loading?: boolean;
28
+ /** Body/prose font scale for rendered markdown (`'xs' | 'sm' | 'base' | 'lg'`).
29
+ * Defaults to `'sm'`. */
30
+ proseSize?: ProseSize;
31
+ /** Shiki theme name for syntax-highlighted code blocks (e.g.
32
+ * `'github-dark-dimmed'`). */
33
+ codeTheme?: string;
34
+ /** Enable Shiki syntax highlighting in code blocks. Turn off to render plain
35
+ * `<pre>` blocks (lighter, no highlighter load). Default true. */
36
+ codeHighlight?: boolean;
37
+ /** Whether each message's action bar is always visible (`'always'`, default) or
38
+ * only revealed on hover of that message row (`'hover'`). */
39
+ actionsReveal?: 'always' | 'hover';
40
+ /** Show the scroll-to-bottom button inside the scroll area. Default true. */
41
+ scrollButton?: boolean;
42
+ /** Custom zero-state shown while the thread is empty. A sensible default renders
43
+ * when omitted (the `<kai-thread>` facade wires this to `slot="empty"`). */
44
+ empty?: JSX.Element;
45
+ /** Fired when a message's action button is clicked (copy / vote / regenerate /
46
+ * edit / custom). The facade re-dispatches this as `kai-message-action`. */
47
+ onMessageAction?: (detail: MessageActionDetail) => void;
48
+ /** Receive the imperative controller once mounted — the `<kai-thread>` facade
49
+ * forwards `scrollToBottom` onto the host. */
50
+ controllerRef?: (controller: ThreadController) => void;
51
+ }
52
+
53
+ /** Built-in zero-state, shown when the thread is empty and no `empty` is supplied. */
54
+ function DefaultEmpty() {
55
+ return (
56
+ <div class="flex min-h-[10rem] flex-1 flex-col items-center justify-center gap-1 py-12 text-center">
57
+ <p class="text-sm font-medium text-foreground">No messages yet</p>
58
+ <p class="text-xs text-muted-foreground">
59
+ Messages will appear here as the conversation starts.
60
+ </p>
61
+ </div>
62
+ );
63
+ }
64
+
65
+ /**
66
+ * `Thread` — the message-list slice of a chat, as a standalone composable: the
67
+ * scrolling list of messages + per-message rendering (markdown, code highlight,
68
+ * reasoning + tool panels, avatars, and the action row), stick-to-bottom scroll
69
+ * with a scroll-to-bottom button, an optional typing indicator, and an empty
70
+ * state. No composer, header, suggestions, or sidebar — those are sibling/preset
71
+ * concerns. This is the source of truth behind the `<kai-thread>` facade; it is
72
+ * composed from the same internal pieces `ChatThread` uses for its message list.
73
+ */
74
+ export function Thread(props: ThreadProps) {
75
+ const outer = useChatConfig();
76
+ const reveal = () => (props.actionsReveal === 'hover' ? 'hover' : 'always');
77
+ // Feedback (copy + vote) state lives ABOVE the per-message <For>, so streaming
78
+ // re-renders (a fresh `messages` array ref per chunk) don't wipe it. The
79
+ // copy/feedback toasts scope to this thread's root so they appear in-thread
80
+ // rather than at the page top.
81
+ let rootEl: HTMLElement | undefined;
82
+ const feedback = createMessageFeedback({
83
+ emit: (detail) => props.onMessageAction?.(detail),
84
+ target: () => rootEl,
85
+ });
86
+ const showScrollButton = () => props.scrollButton !== false;
87
+ const showEmpty = () => props.messages.length === 0 && !props.loading;
88
+
89
+ // Hand the imperative controller to the facade once mounted (rootEl is set).
90
+ onMount(() => {
91
+ props.controllerRef?.({
92
+ scrollToBottom: (behavior) => {
93
+ const vp = rootEl?.querySelector<HTMLElement>('.overflow-y-auto');
94
+ vp?.scrollTo({ top: vp.scrollHeight, behavior: behavior ?? 'smooth' });
95
+ },
96
+ });
97
+ });
98
+
99
+ return (
100
+ <ChatConfig
101
+ proseSize={props.proseSize}
102
+ codeTheme={props.codeTheme}
103
+ codeHighlight={props.codeHighlight !== false}
104
+ portalMount={outer.portalMount()}
105
+ >
106
+ <div
107
+ ref={(e) => (rootEl = e as HTMLElement)}
108
+ class={`relative flex h-full min-h-0 flex-col bg-background ${props.class ?? ''}`}
109
+ >
110
+ <ChatContainer class="h-full px-4 py-3">
111
+ <ChatContainerContent class="mx-auto w-full max-w-3xl space-y-4">
112
+ {/* Zero-state: the consumer owns WHAT it looks like (`empty`); the
113
+ component owns WHEN it shows (empty + not loading). */}
114
+ <Show when={showEmpty()}>
115
+ <Show when={props.empty} fallback={<DefaultEmpty />}>
116
+ {props.empty}
117
+ </Show>
118
+ </Show>
119
+ <For each={props.messages}>
120
+ {(m) => {
121
+ const body = (
122
+ <MessageBody
123
+ content={m.content}
124
+ reasoning={m.reasoning}
125
+ tools={m.tools}
126
+ attachments={m.attachments}
127
+ isUser={m.role === 'user'}
128
+ markdown={m.role === 'assistant'}
129
+ actions={m.actions}
130
+ actionsReveal={reveal()}
131
+ activeFeedback={feedback.resolveFeedback(m)}
132
+ copied={feedback.isCopied(m.id)}
133
+ onAction={(action) => feedback.handleAction(m, action)}
134
+ />
135
+ );
136
+ const rowGroup = reveal() === 'hover' ? 'group ' : '';
137
+ return (
138
+ <Show
139
+ when={m.avatar}
140
+ fallback={
141
+ <Message class={`${rowGroup}${m.role === 'user' ? 'flex-col items-end' : 'flex-col items-start'}`}>
142
+ {body}
143
+ </Message>
144
+ }
145
+ >
146
+ {(av) => (
147
+ <Message class={rowGroup}>
148
+ <MessageAvatar src={av().src ?? ''} alt={av().alt ?? ''} fallback={av().fallback} />
149
+ <div class={`flex min-w-0 flex-1 flex-col ${m.role === 'user' ? 'items-end' : 'items-start'}`}>
150
+ {body}
151
+ </div>
152
+ </Message>
153
+ )}
154
+ </Show>
155
+ );
156
+ }}
157
+ </For>
158
+ {/* Typing indicator on the pending assistant turn. */}
159
+ <Show when={props.loading}>
160
+ <Message class="flex-col items-start">
161
+ <div class="rounded-lg px-1 py-2">
162
+ <Loader variant="typing" />
163
+ </div>
164
+ </Message>
165
+ </Show>
166
+ <ChatContainerScrollAnchor />
167
+ </ChatContainerContent>
168
+ <Show when={showScrollButton()}>
169
+ <div class="absolute bottom-4 left-1/2 flex w-full max-w-3xl -translate-x-1/2 justify-center px-5">
170
+ <ScrollButton class="shadow-sm" />
171
+ </div>
172
+ </Show>
173
+ </ChatContainer>
174
+ </div>
175
+ </ChatConfig>
176
+ );
177
+ }
@@ -266,7 +266,7 @@ defineWebComponent<Props, Events>('kai-workspace', {
266
266
  </Show>
267
267
  </div>
268
268
  </ResizablePanel>
269
- <ResizableHandle withHandle />
269
+ <ResizableHandle />
270
270
  <ResizablePanel>{mainRegion}</ResizablePanel>
271
271
  </ResizablePanelGroup>
272
272
  </Show>