@kitnai/chat 0.3.1 → 0.5.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 (119) hide show
  1. package/README.md +35 -5
  2. package/dist/custom-elements.json +2969 -0
  3. package/dist/kitn-chat.es.js +52 -39
  4. package/dist/llms/llms-full.txt +718 -0
  5. package/dist/llms/llms.txt +104 -0
  6. package/dist/theme.tokens.css +137 -0
  7. package/frameworks/react/index.tsx +584 -0
  8. package/frameworks/react/runtime.tsx +94 -0
  9. package/llms-full.txt +718 -0
  10. package/llms.txt +104 -0
  11. package/package.json +53 -6
  12. package/src/components/attachments.tsx +4 -2
  13. package/src/components/chain-of-thought.tsx +1 -1
  14. package/src/components/chat-scope-picker.tsx +2 -2
  15. package/src/components/chat-thread.tsx +217 -0
  16. package/src/components/checkpoint.tsx +7 -3
  17. package/src/components/context.tsx +14 -18
  18. package/src/components/conversation-item.tsx +1 -1
  19. package/src/components/conversation-list.tsx +5 -4
  20. package/src/components/message-skills.tsx +1 -1
  21. package/src/components/message.tsx +1 -0
  22. package/src/components/model-switcher.tsx +3 -3
  23. package/src/components/prompt-input.tsx +20 -2
  24. package/src/components/reasoning.tsx +2 -2
  25. package/src/components/scroll-button.tsx +1 -0
  26. package/src/components/slash-command.tsx +17 -8
  27. package/src/components/source.tsx +2 -2
  28. package/src/components/thinking-bar.tsx +2 -2
  29. package/src/components/tool.tsx +17 -6
  30. package/src/components/voice-input.tsx +5 -1
  31. package/src/elements/attachments.tsx +132 -0
  32. package/src/elements/chain-of-thought.tsx +45 -0
  33. package/src/elements/chat-scope-picker.tsx +36 -0
  34. package/src/elements/chat-workspace.tsx +122 -0
  35. package/src/elements/chat.tsx +31 -228
  36. package/src/elements/checkpoint.tsx +43 -0
  37. package/src/elements/code-block.tsx +42 -0
  38. package/src/elements/compiled.css +1 -1
  39. package/src/elements/context-meter.tsx +71 -0
  40. package/src/elements/conversation-list.tsx +6 -0
  41. package/src/elements/default-input.tsx +22 -1
  42. package/src/elements/define.tsx +98 -12
  43. package/src/elements/element-types.d.ts +444 -0
  44. package/src/elements/empty.tsx +29 -0
  45. package/src/elements/feedback-bar.tsx +33 -0
  46. package/src/elements/file-upload.tsx +44 -0
  47. package/src/elements/image.tsx +32 -0
  48. package/src/elements/kitn-attachments.stories.tsx +181 -0
  49. package/src/elements/kitn-chain-of-thought.stories.tsx +75 -0
  50. package/src/elements/kitn-chat-scope-picker.stories.tsx +72 -0
  51. package/src/elements/kitn-chat-workspace.stories.tsx +195 -0
  52. package/src/elements/kitn-checkpoint.stories.tsx +71 -0
  53. package/src/elements/kitn-code-block.stories.tsx +82 -0
  54. package/src/elements/kitn-context-meter.stories.tsx +85 -0
  55. package/src/elements/kitn-empty.stories.tsx +110 -0
  56. package/src/elements/kitn-feedback-bar.stories.tsx +73 -0
  57. package/src/elements/kitn-file-upload.stories.tsx +81 -0
  58. package/src/elements/kitn-image.stories.tsx +70 -0
  59. package/src/elements/kitn-loader.stories.tsx +87 -0
  60. package/src/elements/kitn-markdown.stories.tsx +75 -0
  61. package/src/elements/kitn-message-skills.stories.tsx +74 -0
  62. package/src/elements/kitn-message.stories.tsx +105 -0
  63. package/src/elements/kitn-model-switcher.stories.tsx +80 -0
  64. package/src/elements/kitn-prompt-input.stories.tsx +74 -16
  65. package/src/elements/kitn-prompt-suggestions.stories.tsx +157 -0
  66. package/src/elements/kitn-reasoning.stories.tsx +76 -0
  67. package/src/elements/kitn-response-stream.stories.tsx +79 -0
  68. package/src/elements/kitn-source-list.stories.tsx +77 -0
  69. package/src/elements/kitn-source.stories.tsx +87 -0
  70. package/src/elements/kitn-text-shimmer.stories.tsx +63 -0
  71. package/src/elements/kitn-thinking-bar.stories.tsx +72 -0
  72. package/src/elements/kitn-tool.stories.tsx +88 -0
  73. package/src/elements/kitn-voice-input.stories.tsx +87 -0
  74. package/src/elements/loader.tsx +25 -0
  75. package/src/elements/markdown.tsx +38 -0
  76. package/src/elements/message-skills.tsx +22 -0
  77. package/src/elements/message.tsx +125 -0
  78. package/src/elements/model-switcher.tsx +35 -0
  79. package/src/elements/prompt-input.tsx +83 -7
  80. package/src/elements/prompt-suggestions.tsx +58 -0
  81. package/src/elements/reasoning.tsx +50 -0
  82. package/src/elements/register.ts +32 -0
  83. package/src/elements/response-stream.tsx +40 -0
  84. package/src/elements/source.tsx +67 -0
  85. package/src/elements/styles.css +14 -0
  86. package/src/elements/text-shimmer.tsx +28 -0
  87. package/src/elements/thinking-bar.tsx +34 -0
  88. package/src/elements/tool.tsx +23 -0
  89. package/src/elements/voice-input.tsx +41 -0
  90. package/src/index.ts +0 -1
  91. package/src/primitives/chat-config.tsx +3 -3
  92. package/src/stories/docs/Accessibility.mdx +119 -0
  93. package/src/stories/docs/ForAIAgents.mdx +93 -0
  94. package/src/stories/docs/GettingStarted.mdx +2 -2
  95. package/src/stories/docs/Installation.mdx +29 -2
  96. package/src/stories/docs/Integrations.mdx +417 -15
  97. package/src/stories/docs/Introduction.mdx +17 -8
  98. package/src/stories/docs/Theming.mdx +1 -1
  99. package/src/stories/pattern-centered-conversation.stories.tsx +93 -0
  100. package/src/stories/pattern-docked-widget.stories.tsx +93 -0
  101. package/src/stories/pattern-empty-state.stories.tsx +76 -0
  102. package/src/stories/typography.stories.tsx +78 -0
  103. package/src/ui/button.tsx +1 -1
  104. package/src/ui/collapsible.stories.tsx +70 -0
  105. package/src/ui/collapsible.tsx +119 -8
  106. package/src/ui/dropdown.stories.tsx +60 -0
  107. package/src/ui/dropdown.tsx +177 -12
  108. package/src/ui/hover-card.stories.tsx +78 -0
  109. package/src/ui/hover-card.tsx +147 -26
  110. package/src/ui/overlay.stories.tsx +115 -0
  111. package/src/ui/overlay.tsx +151 -0
  112. package/src/ui/scroll-area.stories.tsx +51 -0
  113. package/src/ui/textarea.stories.tsx +77 -0
  114. package/src/ui/textarea.tsx +1 -1
  115. package/src/ui/tooltip.stories.tsx +1 -1
  116. package/src/ui/tooltip.tsx +59 -13
  117. package/src/utils/cn.ts +19 -1
  118. package/theme.css +76 -43
  119. package/src/ui/dialog.tsx +0 -21
@@ -0,0 +1,34 @@
1
+ import { defineKitnElement } from './define';
2
+ import { ThinkingBar } from '../components/thinking-bar';
3
+
4
+ interface Props extends Record<string, unknown> {
5
+ /** The shimmering label, e.g. "Thinking…". */
6
+ text?: string;
7
+ /** When true, show a "stop" affordance that fires a `stop` event. */
8
+ stoppable?: boolean;
9
+ /** Label for the stop affordance. */
10
+ stopLabel?: string;
11
+ }
12
+
13
+ /** Events fired by `<kitn-thinking-bar>`. */
14
+ interface Events {
15
+ /** The "stop / answer now" affordance was clicked. */
16
+ stop: void;
17
+ }
18
+
19
+ /**
20
+ * `<kitn-thinking-bar>` — a pure leaf element: an animated "thinking" indicator
21
+ * (one of the primitives the batteries-included `<kitn-chat>` does NOT surface).
22
+ * Config via attributes, the only interaction (`stop`) comes back as an event.
23
+ */
24
+ defineKitnElement<Props, Events>('kitn-thinking-bar', {
25
+ text: 'Thinking',
26
+ stoppable: false,
27
+ stopLabel: 'Answer now',
28
+ }, (props, { dispatch, flag }) => (
29
+ <ThinkingBar
30
+ text={props.text}
31
+ stopLabel={props.stopLabel}
32
+ onStop={flag('stoppable') ? () => dispatch('stop') : undefined}
33
+ />
34
+ ));
@@ -0,0 +1,23 @@
1
+ import { Show } from 'solid-js';
2
+ import { defineKitnElement } from './define';
3
+ import { Tool, type ToolPart } from '../components/tool';
4
+
5
+ interface Props extends Record<string, unknown> {
6
+ /** The tool-call to display. Set as a JS property. */
7
+ tool?: ToolPart;
8
+ /** Start expanded. */
9
+ open?: boolean;
10
+ }
11
+
12
+ /**
13
+ * `<kitn-tool>` — a collapsible tool-call panel (input/output inspection with a
14
+ * state badge). Data via the `tool` property; `open` flag starts it expanded.
15
+ */
16
+ defineKitnElement<Props>('kitn-tool', {
17
+ tool: undefined,
18
+ open: false,
19
+ }, (props, { flag }) => (
20
+ <Show when={props.tool}>
21
+ <Tool toolPart={props.tool!} defaultOpen={flag('open')} />
22
+ </Show>
23
+ ));
@@ -0,0 +1,41 @@
1
+ import { defineKitnElement } from './define';
2
+ import { VoiceInput } from '../components/voice-input';
3
+
4
+ interface Props extends Record<string, unknown> {
5
+ /**
6
+ * Transcriber the host supplies — records audio, returns the text. This is a
7
+ * **function-valued property** (`el.transcribe = async blob => '...'`) because
8
+ * a value-returning callback can't be modelled as a fire-and-forget event.
9
+ */
10
+ transcribe?: (audio: Blob) => Promise<string>;
11
+ /** Disable the mic button (non-interactive). */
12
+ disabled?: boolean;
13
+ }
14
+
15
+ /** Events fired by `<kitn-voice-input>`. */
16
+ interface Events {
17
+ /** Raw audio captured (before transcription) — for hosts that prefer to
18
+ * handle transcription themselves instead of via the `transcribe` property. */
19
+ audiocaptured: { blob: Blob };
20
+ /** Transcription completed (the `transcribe` property resolved). */
21
+ transcription: { text: string };
22
+ }
23
+
24
+ /**
25
+ * `<kitn-voice-input>` — a mic button that records and transcribes. The
26
+ * canonical **function-property** element: set `el.transcribe` to your async
27
+ * transcriber. Also emits `audiocaptured` (raw blob) and `transcription` (text).
28
+ */
29
+ defineKitnElement<Props, Events>('kitn-voice-input', {
30
+ transcribe: undefined,
31
+ disabled: false,
32
+ }, (props, { dispatch, flag }) => (
33
+ <VoiceInput
34
+ disabled={flag('disabled')}
35
+ onTranscribe={async (blob) => {
36
+ dispatch('audiocaptured', { blob });
37
+ return props.transcribe ? props.transcribe(blob) : '';
38
+ }}
39
+ onTranscription={(text) => dispatch('transcription', { text })}
40
+ />
41
+ ));
package/src/index.ts CHANGED
@@ -34,7 +34,6 @@ export { Separator } from './ui/separator';
34
34
  export { ResizablePanelGroup, ResizablePanel, ResizableHandle } from './ui/resizable';
35
35
  export type { ResizablePanelGroupProps, ResizablePanelProps, ResizableHandleProps } from './ui/resizable';
36
36
  export { Skeleton } from './ui/skeleton';
37
- export { Dialog, DialogTrigger, DialogContent } from './ui/dialog';
38
37
 
39
38
  // Layer 3: AI/Feature Components
40
39
  export {
@@ -7,14 +7,14 @@ export interface ChatConfigValue {
7
7
  proseSize: Accessor<ProseSize>;
8
8
  /** Shiki theme for code blocks */
9
9
  codeTheme: Accessor<string>;
10
- /** Node Kobalte overlays portal into; undefined → document.body */
10
+ /** Node the kit's overlays portal into; undefined → document.body */
11
11
  portalMount: Accessor<HTMLElement | undefined>;
12
12
  /** Whether code blocks are syntax-highlighted; false → plain text, no Shiki loaded */
13
13
  codeHighlight: Accessor<boolean>;
14
14
  }
15
15
 
16
16
  const defaultConfig: ChatConfigValue = {
17
- proseSize: () => 'base' as ProseSize,
17
+ proseSize: () => 'sm' as ProseSize,
18
18
  codeTheme: () => 'github-dark-dimmed',
19
19
  portalMount: () => undefined,
20
20
  codeHighlight: () => true,
@@ -37,7 +37,7 @@ export interface ChatConfigProps {
37
37
  */
38
38
  export function ChatConfig(props: ChatConfigProps) {
39
39
  const value: ChatConfigValue = {
40
- proseSize: () => props.proseSize ?? 'base',
40
+ proseSize: () => props.proseSize ?? 'sm',
41
41
  codeTheme: () => props.codeTheme ?? 'github-dark-dimmed',
42
42
  portalMount: () => props.portalMount,
43
43
  codeHighlight: () => props.codeHighlight ?? true,
@@ -0,0 +1,119 @@
1
+ import { Meta } from '@storybook/addon-docs/blocks';
2
+
3
+ <Meta title="Docs/Accessibility" />
4
+
5
+ # Accessibility
6
+
7
+ `@kitnai/chat` targets **WCAG 2.1 Level AA**. The kit is audited with [axe-core](https://github.com/dequelabs/axe-core) (via `scripts/audit-a11y.mjs`) and ships with **0 axe violations** in both light and dark modes. Keyboard navigation is verified with a Playwright browser test suite.
8
+
9
+ This page describes the accessibility posture, the keyboard model, known limitations, and what you need to do as an integrator.
10
+
11
+ ---
12
+
13
+ ## Color contrast
14
+
15
+ All text and UI chrome meet WCAG 2.1 AA contrast requirements (4.5:1 for body text, 3:1 for large text and UI components) in the default light and dark palettes.
16
+
17
+ The `theme` attribute on every element (`light | dark | auto`) controls which token set loads. `auto` (the default) follows the OS `prefers-color-scheme` media query, so users who configure dark mode at the OS level get it automatically. Override either set with `--kitn-color-*` tokens — if you do, verify contrast yourself; the kit cannot audit tokens it does not control.
18
+
19
+ ---
20
+
21
+ ## Keyboard operability
22
+
23
+ Every interactive control is reachable and operable without a mouse.
24
+
25
+ ### Focus order
26
+
27
+ Tab moves through all focusable controls in DOM order. The prompt textarea, send button, attachment button, toolbar controls (search, mic), header controls (model switcher, context meter), message action buttons, suggestion chips, and conversation list items are all included. Focus rings are always visible — they are not hidden on `:focus`, only on `:focus-visible`.
28
+
29
+ ### Dropdowns and select menus (ModelSwitcher, ChatScopePicker, …)
30
+
31
+ | Key | Action |
32
+ |---|---|
33
+ | Enter / Space / ↓ | Open the menu |
34
+ | ↑ / ↓ | Move between items |
35
+ | Home / End | Jump to first / last item |
36
+ | Typeahead (letter keys) | Jump to the first item starting with that letter |
37
+ | Enter / Space | Select the focused item |
38
+ | Esc | Close without selecting; focus returns to the trigger |
39
+ | Tab | Close and move focus past the trigger |
40
+
41
+ Focus always returns to the trigger element after the menu closes, whether closed by Esc, selection, or a click outside.
42
+
43
+ ### Collapsible panels (Reasoning, Tool calls, …)
44
+
45
+ | Key | Action |
46
+ |---|---|
47
+ | Enter / Space | Toggle expanded / collapsed |
48
+ | Tab | Move into the expanded content |
49
+ | Esc | Collapse (if focused inside) |
50
+
51
+ ### Slash command palette
52
+
53
+ Typing `/` in the prompt input opens the command palette.
54
+
55
+ | Key | Action |
56
+ |---|---|
57
+ | ↑ / ↓ | Navigate items |
58
+ | Home / End | Jump to first / last item |
59
+ | Enter / Tab | Select the focused command (inserts `/label ` into the input with caret at end) |
60
+ | Esc | Close the palette; focus stays in the input |
61
+
62
+ ### Conversation list
63
+
64
+ | Key | Action |
65
+ |---|---|
66
+ | ↑ / ↓ | Move between conversations |
67
+ | Enter | Select the focused conversation |
68
+ | Tab | Move through action buttons (if any) |
69
+
70
+ ---
71
+
72
+ ## Accessible names on icon buttons
73
+
74
+ Every icon-only button (attach, send, mic, search, copy, like, dislike, regenerate, close) carries an accessible name via `aria-label`. Screen readers announce the button's purpose rather than "button" or nothing. Labels use plain language: "Send message", "Attach file", "Copy message", "Thumbs up", and so on.
75
+
76
+ ---
77
+
78
+ ## Tooltips and hover cards
79
+
80
+ Tooltips and hover cards (on sources, context meter, etc.) are dismissable and persistent per WCAG 2.1 SC 1.4.13 (Content on Hover or Focus):
81
+
82
+ - They appear on both hover and keyboard focus.
83
+ - Moving the pointer over the tooltip/card content keeps it visible (it does not vanish when the pointer leaves the trigger).
84
+ - They can be dismissed with **Esc** without moving focus.
85
+
86
+ ---
87
+
88
+ ## ARIA landmarks and live regions
89
+
90
+ - The message list is marked as a log region (`role="log"`, `aria-live="polite"`) so streaming tokens are announced to screen readers without being intrusive.
91
+ - The prompt area is labelled; the textarea carries its placeholder as an accessible name fallback.
92
+ - The conversation sidebar is a navigation landmark (`<nav>`).
93
+
94
+ ---
95
+
96
+ ## Shadow DOM and screen readers
97
+
98
+ All elements render inside Shadow DOM. Modern screen readers (NVDA + Chrome, JAWS + Chrome, VoiceOver + Safari/Chrome) pierce Shadow DOM correctly. Accessible names, roles, and live regions work as expected.
99
+
100
+ ---
101
+
102
+ ## Audit tooling
103
+
104
+ Accessibility is verified with:
105
+
106
+ - **axe-core** (`scripts/audit-a11y.mjs`) — automated rule checks in both light and dark themes. Zero violations at the time of build.
107
+ - **Playwright keyboard tests** — 21-scenario browser test suite covering focus order, dropdown/collapsible/palette keyboard nav, ArrowUp/Down/Home/End/typeahead/Enter/Escape/Tab, and focus-return after close.
108
+
109
+ The kit does not carry a "WCAG AA certified" certification — no automated tool can certify that. What it does carry is a targeted AA design, an axe-core clean bill, and a passing Playwright keyboard suite.
110
+
111
+ ---
112
+
113
+ ## What integrators need to do
114
+
115
+ 1. **Do not hide focus rings.** The kit renders visible focus rings via `:focus-visible`. Do not add `outline: none` or `outline: 0` in your host-page CSS targeting `*` or the element host.
116
+ 2. **Verify contrast if you override tokens.** Use a contrast checker after overriding any `--kitn-color-*` token.
117
+ 3. **Provide meaningful conversation titles.** The conversation list announces the `title` field to screen readers. "Chat 1" is less useful than "React integration help".
118
+ 4. **Set a meaningful `placeholder`.** The textarea placeholder doubles as an accessible name when no label is associated.
119
+ 5. **Check your theme choice.** Using `theme="light"` in a page the user has set to dark mode (or vice versa) can create contrast mismatches between kit components and host-page content. `theme="auto"` (the default) avoids this.
@@ -0,0 +1,93 @@
1
+ import { Meta } from '@storybook/addon-docs/blocks';
2
+
3
+ <Meta title="Docs/For AI Agents" />
4
+
5
+ # For AI Agents / LLMs
6
+
7
+ `@kitnai/chat` ships machine-readable orientation files that follow the
8
+ [llmstxt.org](https://llmstxt.org) convention, so coding agents (Claude Code,
9
+ Copilot, Cursor, Codex, …) can wire up the components correctly without guessing.
10
+
11
+ **View them now:** <a href="/llms.txt" target="_blank" rel="noreferrer">llms.txt</a> ·
12
+ <a href="/llms-full.txt" target="_blank" rel="noreferrer">llms-full.txt</a>
13
+ (open in a new tab)
14
+
15
+ ## The files
16
+
17
+ | File | Audience | Where to find it |
18
+ |---|---|---|
19
+ | <a href="/llms.txt" target="_blank" rel="noreferrer"><code>llms.txt</code></a> | Agents + humans | Repo root, the npm package root (`node_modules/@kitnai/chat/llms.txt`), and `https://kitn.dev/llms.txt` |
20
+ | <a href="/llms-full.txt" target="_blank" rel="noreferrer"><code>llms-full.txt</code></a> | Agents | Same locations; the per-element API reference for **every** `kitn-*` element |
21
+
22
+ Both files are **auto-generated** from `dist/custom-elements.json` by
23
+ `scripts/gen-llms.mjs` during `npm run build`, so they never drift from the
24
+ shipped API. Do not edit them by hand.
25
+
26
+ - **`llms.txt`** (~4 KB) — a dense orientation: install, the property-vs-attribute
27
+ rule, the two-layer architecture, theming, and framework wiring. Fast to read.
28
+ - **`llms-full.txt`** (~32 KB) — everything in `llms.txt` plus a generated props/events
29
+ table for each element, a streaming recipe, and a "build a chat app" runbook.
30
+
31
+ ## The #1 rule agents get wrong
32
+
33
+ **Array and object data must be set as JavaScript properties, not HTML attributes.**
34
+ An HTML attribute is always a string, so passing `messages`, `models`, `context`,
35
+ `suggestions`, or `slashCommands` as an attribute silently fails.
36
+
37
+ ```js
38
+ const chat = document.querySelector('kitn-chat');
39
+ chat.messages = [{ id: '1', role: 'assistant', content: 'Hi!' }]; // ✅ property
40
+ ```
41
+
42
+ ```html
43
+ <kitn-chat messages="[...]"></kitn-chat> <!-- ❌ never works -->
44
+ ```
45
+
46
+ Only scalar props (string / number / boolean) work as attributes — for example
47
+ `placeholder`, `loading`, and `theme`.
48
+
49
+ ## How agents consume these files
50
+
51
+ | Tool | How it finds them |
52
+ |---|---|
53
+ | Claude Code | Reference `@llms.txt` in `CLAUDE.md`, or read `node_modules/@kitnai/chat/llms-full.txt` |
54
+ | GitHub Copilot | Workspace indexing picks up the file in `node_modules`; reference it from `.github/copilot-instructions.md` |
55
+ | Cursor | Point `.cursorrules` at the installed `llms.txt` |
56
+ | Codex / ChatGPT | Fetch https://kitn.dev/llms.txt directly |
57
+ | Any agent | `npm install @kitnai/chat` → file is at `node_modules/@kitnai/chat/llms.txt` |
58
+
59
+ ## Build a chat app (the runbook agents follow)
60
+
61
+ ```js
62
+ import '@kitnai/chat/elements';
63
+ const chat = document.querySelector('kitn-chat');
64
+ chat.messages = [];
65
+
66
+ chat.addEventListener('submit', async (e) => {
67
+ const userText = e.detail.value;
68
+
69
+ // Append the user message (new array)
70
+ const history = [...chat.messages, { id: crypto.randomUUID(), role: 'user', content: userText }];
71
+ chat.messages = history;
72
+ chat.loading = true;
73
+
74
+ // Empty assistant placeholder to stream into
75
+ const aid = crypto.randomUUID();
76
+ chat.messages = [...history, { id: aid, role: 'assistant', content: '' }];
77
+
78
+ // Stream — reassign a NEW array with a NEW message object each chunk.
79
+ // Mutating in place will NOT re-render.
80
+ let answer = '';
81
+ for await (const token of streamFromYourAPI(history)) {
82
+ answer += token;
83
+ chat.messages = chat.messages.map((m) => (m.id === aid ? { ...m, content: answer } : m));
84
+ }
85
+ chat.loading = false;
86
+ });
87
+ ```
88
+
89
+ ## Links
90
+
91
+ - <a href="/llms.txt" target="_blank" rel="noreferrer"><code>llms.txt</code></a> — orientation (also published at `https://kitn.dev/llms.txt`)
92
+ - <a href="/llms-full.txt" target="_blank" rel="noreferrer"><code>llms-full.txt</code></a> — full per-element reference (also `https://kitn.dev/llms-full.txt`)
93
+ - Custom Elements Manifest — `dist/custom-elements.json` (published at `https://unpkg.com/@kitnai/chat/dist/custom-elements.json`)
@@ -1,7 +1,7 @@
1
1
  import { Meta, Canvas } from '@storybook/addon-docs/blocks';
2
2
  import * as FullChat from '../full-chat.stories';
3
3
 
4
- <Meta title="Getting Started" />
4
+ <Meta title="Docs/Getting Started" />
5
5
 
6
6
  # Getting Started
7
7
 
@@ -73,4 +73,4 @@ Everything assembled into a real app — a conversation sidebar, a message threa
73
73
 
74
74
  Open it full-screen under **Examples → Full Chat App**, then explore each building block on its own page in the sidebar.
75
75
 
76
- Ready to make it yours? See **[Theming](?path=/docs/theming--docs)**. Wiring a real model? See **[Integrations](?path=/docs/integrations--docs)**.
76
+ Ready to make it yours? See **[Theming](?path=/docs/docs-theming--docs)**. Wiring a real model? See **[Integrations](?path=/docs/docs-frameworks-integrations--docs)**.
@@ -1,6 +1,6 @@
1
1
  import { Meta } from '@storybook/addon-docs/blocks';
2
2
 
3
- <Meta title="Installation" />
3
+ <Meta title="Docs/Installation" />
4
4
 
5
5
  # Installation
6
6
 
@@ -45,4 +45,31 @@ npm run build # emits dist/kitn-chat.es.js
45
45
  - **SolidJS is bundled in** — the host page needs nothing else.
46
46
  - The kit's CSS is injected into each element's Shadow DOM automatically; importing `theme.css` is optional and only needed if you want to override design tokens.
47
47
 
48
- Head to **[Getting Started](?path=/docs/getting-started--docs)** to render your first chat.
48
+ ### Via CDN (no build step, no npm)
49
+
50
+ The element bundle is a self-contained ES module, so you can load it straight from a CDN — no install, no bundler, no import map. It's published on both <a href="https://www.jsdelivr.com/package/npm/@kitnai/chat" target="_blank" rel="noreferrer">jsDelivr</a> and <a href="https://unpkg.com/browse/@kitnai/chat/" target="_blank" rel="noreferrer">unpkg</a>:
51
+
52
+ ```html
53
+ <!-- jsDelivr -->
54
+ <script type="module">
55
+ import 'https://cdn.jsdelivr.net/npm/@kitnai/chat/dist/kitn-chat.es.js';
56
+ </script>
57
+
58
+ <!-- …or unpkg -->
59
+ <script type="module">
60
+ import 'https://unpkg.com/@kitnai/chat/dist/kitn-chat.es.js';
61
+ </script>
62
+
63
+ <kitn-chat></kitn-chat>
64
+ ```
65
+
66
+ - The URLs above track the **latest** release (no version) — they never go stale, so they're ideal for demos and quick starts.
67
+ - **For production, pin an exact version** — e.g. `.../npm/@kitnai/chat@0.4.0/dist/kitn-chat.es.js`. Pinned URLs are immutable and cached far more aggressively (floating "latest" tags get revalidated every few hours), and — since this package is **pre-1.0** — pinning shields you from breaking changes in a future minor release. A version *range* (`@0` / `@0.4`) won't: pre-1.0 it can still resolve to a breaking minor.
68
+ - SolidJS and the kit's CSS are bundled in, and the lazy syntax-highlighting chunks load from the **same CDN** automatically (they're relative to the bundle) — so nothing else is needed.
69
+ - To override design tokens, also pull in `theme.css`:
70
+
71
+ ```html
72
+ <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/@kitnai/chat/theme.css">
73
+ ```
74
+
75
+ Head to **[Getting Started](?path=/docs/docs-getting-started--docs)** to render your first chat.