@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.
- package/README.md +35 -5
- package/dist/custom-elements.json +2969 -0
- package/dist/kitn-chat.es.js +52 -39
- package/dist/llms/llms-full.txt +718 -0
- package/dist/llms/llms.txt +104 -0
- package/dist/theme.tokens.css +137 -0
- package/frameworks/react/index.tsx +584 -0
- package/frameworks/react/runtime.tsx +94 -0
- package/llms-full.txt +718 -0
- package/llms.txt +104 -0
- package/package.json +53 -6
- package/src/components/attachments.tsx +4 -2
- package/src/components/chain-of-thought.tsx +1 -1
- package/src/components/chat-scope-picker.tsx +2 -2
- package/src/components/chat-thread.tsx +217 -0
- package/src/components/checkpoint.tsx +7 -3
- package/src/components/context.tsx +14 -18
- package/src/components/conversation-item.tsx +1 -1
- package/src/components/conversation-list.tsx +5 -4
- package/src/components/message-skills.tsx +1 -1
- package/src/components/message.tsx +1 -0
- package/src/components/model-switcher.tsx +3 -3
- package/src/components/prompt-input.tsx +20 -2
- package/src/components/reasoning.tsx +2 -2
- package/src/components/scroll-button.tsx +1 -0
- package/src/components/slash-command.tsx +17 -8
- package/src/components/source.tsx +2 -2
- package/src/components/thinking-bar.tsx +2 -2
- package/src/components/tool.tsx +17 -6
- package/src/components/voice-input.tsx +5 -1
- package/src/elements/attachments.tsx +132 -0
- package/src/elements/chain-of-thought.tsx +45 -0
- package/src/elements/chat-scope-picker.tsx +36 -0
- package/src/elements/chat-workspace.tsx +122 -0
- package/src/elements/chat.tsx +31 -228
- package/src/elements/checkpoint.tsx +43 -0
- package/src/elements/code-block.tsx +42 -0
- package/src/elements/compiled.css +1 -1
- package/src/elements/context-meter.tsx +71 -0
- package/src/elements/conversation-list.tsx +6 -0
- package/src/elements/default-input.tsx +22 -1
- package/src/elements/define.tsx +98 -12
- package/src/elements/element-types.d.ts +444 -0
- package/src/elements/empty.tsx +29 -0
- package/src/elements/feedback-bar.tsx +33 -0
- package/src/elements/file-upload.tsx +44 -0
- package/src/elements/image.tsx +32 -0
- package/src/elements/kitn-attachments.stories.tsx +181 -0
- package/src/elements/kitn-chain-of-thought.stories.tsx +75 -0
- package/src/elements/kitn-chat-scope-picker.stories.tsx +72 -0
- package/src/elements/kitn-chat-workspace.stories.tsx +195 -0
- package/src/elements/kitn-checkpoint.stories.tsx +71 -0
- package/src/elements/kitn-code-block.stories.tsx +82 -0
- package/src/elements/kitn-context-meter.stories.tsx +85 -0
- package/src/elements/kitn-empty.stories.tsx +110 -0
- package/src/elements/kitn-feedback-bar.stories.tsx +73 -0
- package/src/elements/kitn-file-upload.stories.tsx +81 -0
- package/src/elements/kitn-image.stories.tsx +70 -0
- package/src/elements/kitn-loader.stories.tsx +87 -0
- package/src/elements/kitn-markdown.stories.tsx +75 -0
- package/src/elements/kitn-message-skills.stories.tsx +74 -0
- package/src/elements/kitn-message.stories.tsx +105 -0
- package/src/elements/kitn-model-switcher.stories.tsx +80 -0
- package/src/elements/kitn-prompt-input.stories.tsx +74 -16
- package/src/elements/kitn-prompt-suggestions.stories.tsx +157 -0
- package/src/elements/kitn-reasoning.stories.tsx +76 -0
- package/src/elements/kitn-response-stream.stories.tsx +79 -0
- package/src/elements/kitn-source-list.stories.tsx +77 -0
- package/src/elements/kitn-source.stories.tsx +87 -0
- package/src/elements/kitn-text-shimmer.stories.tsx +63 -0
- package/src/elements/kitn-thinking-bar.stories.tsx +72 -0
- package/src/elements/kitn-tool.stories.tsx +88 -0
- package/src/elements/kitn-voice-input.stories.tsx +87 -0
- package/src/elements/loader.tsx +25 -0
- package/src/elements/markdown.tsx +38 -0
- package/src/elements/message-skills.tsx +22 -0
- package/src/elements/message.tsx +125 -0
- package/src/elements/model-switcher.tsx +35 -0
- package/src/elements/prompt-input.tsx +83 -7
- package/src/elements/prompt-suggestions.tsx +58 -0
- package/src/elements/reasoning.tsx +50 -0
- package/src/elements/register.ts +32 -0
- package/src/elements/response-stream.tsx +40 -0
- package/src/elements/source.tsx +67 -0
- package/src/elements/styles.css +14 -0
- package/src/elements/text-shimmer.tsx +28 -0
- package/src/elements/thinking-bar.tsx +34 -0
- package/src/elements/tool.tsx +23 -0
- package/src/elements/voice-input.tsx +41 -0
- package/src/index.ts +0 -1
- package/src/primitives/chat-config.tsx +3 -3
- package/src/stories/docs/Accessibility.mdx +119 -0
- package/src/stories/docs/ForAIAgents.mdx +93 -0
- package/src/stories/docs/GettingStarted.mdx +2 -2
- package/src/stories/docs/Installation.mdx +29 -2
- package/src/stories/docs/Integrations.mdx +417 -15
- package/src/stories/docs/Introduction.mdx +17 -8
- package/src/stories/docs/Theming.mdx +1 -1
- package/src/stories/pattern-centered-conversation.stories.tsx +93 -0
- package/src/stories/pattern-docked-widget.stories.tsx +93 -0
- package/src/stories/pattern-empty-state.stories.tsx +76 -0
- package/src/stories/typography.stories.tsx +78 -0
- package/src/ui/button.tsx +1 -1
- package/src/ui/collapsible.stories.tsx +70 -0
- package/src/ui/collapsible.tsx +119 -8
- package/src/ui/dropdown.stories.tsx +60 -0
- package/src/ui/dropdown.tsx +177 -12
- package/src/ui/hover-card.stories.tsx +78 -0
- package/src/ui/hover-card.tsx +147 -26
- package/src/ui/overlay.stories.tsx +115 -0
- package/src/ui/overlay.tsx +151 -0
- package/src/ui/scroll-area.stories.tsx +51 -0
- package/src/ui/textarea.stories.tsx +77 -0
- package/src/ui/textarea.tsx +1 -1
- package/src/ui/tooltip.stories.tsx +1 -1
- package/src/ui/tooltip.tsx +59 -13
- package/src/utils/cn.ts +19 -1
- package/theme.css +76 -43
- package/src/ui/dialog.tsx +0 -21
|
@@ -0,0 +1,104 @@
|
|
|
1
|
+
<!-- AUTO-GENERATED by scripts/gen-llms.mjs — do not edit by hand. Run `npm run build`. -->
|
|
2
|
+
# @kitnai/chat
|
|
3
|
+
|
|
4
|
+
> Framework-agnostic, Shadow-DOM web components for building AI chat interfaces — works in React, Vue, Angular, Svelte, or plain HTML. 28 `kitn-*` custom elements: streaming responses, markdown + code rendering, reasoning/tool panels, attachments, conversation sidebar, voice input. Zero framework dependency for consumers; the SolidJS runtime it is authored in is bundled in, so the host needs nothing.
|
|
5
|
+
|
|
6
|
+
## Install
|
|
7
|
+
|
|
8
|
+
```bash
|
|
9
|
+
npm install @kitnai/chat
|
|
10
|
+
# SolidJS consumers also need the peer dep:
|
|
11
|
+
npm install solid-js
|
|
12
|
+
```
|
|
13
|
+
|
|
14
|
+
## #1 rule: array/object data goes on JS PROPERTIES, not HTML attributes
|
|
15
|
+
|
|
16
|
+
This is the single most common mistake. Arrays and objects (`messages`, `models`, `context`, `suggestions`, `slashCommands`, …) MUST be assigned as JavaScript properties on the element. They CANNOT be passed as HTML attributes — an HTML attribute is always a string and will be ignored or mis-parsed.
|
|
17
|
+
|
|
18
|
+
```js
|
|
19
|
+
const chat = document.querySelector('kitn-chat');
|
|
20
|
+
chat.messages = [{ id: '1', role: 'assistant', content: 'Hi!' }]; // ✅ property
|
|
21
|
+
```
|
|
22
|
+
```html
|
|
23
|
+
<kitn-chat messages="[...]"></kitn-chat> <!-- ❌ never works -->
|
|
24
|
+
```
|
|
25
|
+
|
|
26
|
+
Only scalar values (string/number/boolean) work as attributes (e.g. `placeholder`, `loading`, `theme`).
|
|
27
|
+
|
|
28
|
+
## Two layers
|
|
29
|
+
|
|
30
|
+
**Layer 1 — batteries-included web components** (`import '@kitnai/chat/elements'`):
|
|
31
|
+
Drop an element into any framework (React, Vue, plain HTML). Data in via JS properties; interactions out via non-bubbling CustomEvents.
|
|
32
|
+
|
|
33
|
+
- `<kitn-chat>` — full chat UI (message list + prompt input). The primary starting point.
|
|
34
|
+
- `<kitn-conversation-list>` — sidebar conversation browser with group support.
|
|
35
|
+
- `<kitn-prompt-input>` — standalone composer with send button.
|
|
36
|
+
|
|
37
|
+
**Layer 2 — composable primitives** (`import { … } from '@kitnai/chat'`):
|
|
38
|
+
All 28 elements are also exported individually. Use them for custom layouts or features `<kitn-chat>` does not expose (ChainOfThought, FeedbackBar, ThinkingBar, VoiceInput, …). Your bundler tree-shakes the rest.
|
|
39
|
+
|
|
40
|
+
## Key rules for the web components
|
|
41
|
+
|
|
42
|
+
1. **Array/object data = JS properties** (see above). Scalars may be attributes.
|
|
43
|
+
2. **Events are non-bubbling `CustomEvent`s** — listen directly on the element:
|
|
44
|
+
`chat.addEventListener('submit', (e) => console.log(e.detail.value))`
|
|
45
|
+
3. **`theme` attribute** (`'light' | 'dark' | 'auto'`) works on every element. Default `auto` follows `prefers-color-scheme`.
|
|
46
|
+
4. **Theming via CSS custom properties** — override `--kitn-color-*` tokens on `:root`; they pierce Shadow DOM.
|
|
47
|
+
|
|
48
|
+
## ChatMessage schema (required for `<kitn-chat>`)
|
|
49
|
+
|
|
50
|
+
```ts
|
|
51
|
+
interface ChatMessage {
|
|
52
|
+
id: string;
|
|
53
|
+
role: 'user' | 'assistant';
|
|
54
|
+
content: string;
|
|
55
|
+
reasoning?: { text: string; label?: string };
|
|
56
|
+
tools?: ToolPart[];
|
|
57
|
+
attachments?: AttachmentData[];
|
|
58
|
+
actions?: ('copy' | 'like' | 'dislike' | 'regenerate' | 'edit')[];
|
|
59
|
+
}
|
|
60
|
+
```
|
|
61
|
+
|
|
62
|
+
## Framework wiring
|
|
63
|
+
|
|
64
|
+
**Plain HTML / CDN**
|
|
65
|
+
```html
|
|
66
|
+
<script type="module" src="https://unpkg.com/@kitnai/chat/elements"></script>
|
|
67
|
+
<kitn-chat style="display:block;height:100vh"></kitn-chat>
|
|
68
|
+
<script type="module">
|
|
69
|
+
const chat = document.querySelector('kitn-chat');
|
|
70
|
+
chat.messages = [];
|
|
71
|
+
</script>
|
|
72
|
+
```
|
|
73
|
+
|
|
74
|
+
**React** — typed wrappers auto-set properties and expose `on<Event>` props:
|
|
75
|
+
```tsx
|
|
76
|
+
import { KitnChat } from '@kitnai/chat/react';
|
|
77
|
+
<KitnChat messages={messages} onSubmit={(e) => send(e.detail.value)} />
|
|
78
|
+
```
|
|
79
|
+
|
|
80
|
+
**Vue** — use the element directly; pass arrays via `.prop`:
|
|
81
|
+
```vue
|
|
82
|
+
<kitn-chat :messages.prop="messages" @submit="send" />
|
|
83
|
+
```
|
|
84
|
+
|
|
85
|
+
## Theming
|
|
86
|
+
|
|
87
|
+
```css
|
|
88
|
+
:root {
|
|
89
|
+
--kitn-color-background: #0f0f0f;
|
|
90
|
+
--kitn-color-primary: #7c3aed;
|
|
91
|
+
--kitn-color-muted: #1e1e1e;
|
|
92
|
+
}
|
|
93
|
+
```
|
|
94
|
+
|
|
95
|
+
For plain HTML/CDN: `<link rel="stylesheet" href="…/@kitnai/chat/theme.tokens.css">`.
|
|
96
|
+
For Tailwind builds: `@import "@kitnai/chat/theme.css"` in your CSS.
|
|
97
|
+
|
|
98
|
+
## Docs
|
|
99
|
+
|
|
100
|
+
- Full element reference (all 28 elements, every prop/event): ./llms-full.txt — https://kitn.dev/llms-full.txt
|
|
101
|
+
- Machine-readable Custom Elements Manifest: https://unpkg.com/@kitnai/chat/dist/custom-elements.json
|
|
102
|
+
- Working examples: https://github.com/kitn-ai/chat/tree/main/examples
|
|
103
|
+
- Storybook: https://storybook.kitn.dev
|
|
104
|
+
- Repository: https://github.com/kitn-ai/chat
|
|
@@ -0,0 +1,137 @@
|
|
|
1
|
+
/* AUTO-GENERATED from theme.css by scripts/build-theme-tokens.mjs — do not edit.
|
|
2
|
+
Browser-ready token stylesheet for <link>/CDN consumers (the kit's ELEMENTS
|
|
3
|
+
are self-themed and don't need this; it themes host-page chrome / rebrands). */
|
|
4
|
+
|
|
5
|
+
:root {
|
|
6
|
+
--color-background: var(--kitn-color-background, hsl(0 0% 100%));
|
|
7
|
+
--color-foreground: var(--kitn-color-foreground, hsl(240 10% 3.9%));
|
|
8
|
+
--color-card: var(--kitn-color-card, hsl(0 0% 100%));
|
|
9
|
+
--color-card-foreground: var(--kitn-color-card-foreground, hsl(240 10% 3.9%));
|
|
10
|
+
--color-popover: var(--kitn-color-popover, hsl(0 0% 100%));
|
|
11
|
+
--color-popover-foreground: var(--kitn-color-popover-foreground, hsl(240 10% 3.9%));
|
|
12
|
+
--color-primary: var(--kitn-color-primary, hsl(240 5.9% 10%));
|
|
13
|
+
--color-primary-foreground: var(--kitn-color-primary-foreground, hsl(0 0% 98%));
|
|
14
|
+
--color-secondary: var(--kitn-color-secondary, hsl(240 4.8% 95.9%));
|
|
15
|
+
--color-secondary-foreground: var(--kitn-color-secondary-foreground, hsl(240 5.9% 10%));
|
|
16
|
+
--color-muted: var(--kitn-color-muted, hsl(240 4.8% 95.9%));
|
|
17
|
+
--color-muted-foreground: var(--kitn-color-muted-foreground, hsl(240 3.8% 43%));
|
|
18
|
+
--color-accent: var(--kitn-color-accent, hsl(240 4.8% 95.9%));
|
|
19
|
+
--color-accent-foreground: var(--kitn-color-accent-foreground, hsl(240 5.9% 10%));
|
|
20
|
+
--color-destructive: var(--kitn-color-destructive, hsl(0 84.2% 60.2%));
|
|
21
|
+
--color-destructive-foreground: var(--kitn-color-destructive-foreground, hsl(0 0% 98%));
|
|
22
|
+
--color-border: var(--kitn-color-border, hsl(240 5.9% 90%));
|
|
23
|
+
--color-input: var(--kitn-color-input, hsl(240 5.9% 90%));
|
|
24
|
+
/* Focus ring — a deliberate blue (not a neutral) so keyboard focus is always
|
|
25
|
+
obvious and on-brand in both modes. Light uses a strong blue; dark uses a
|
|
26
|
+
brighter one for contrast on dark surfaces. Both clear WCAG 2.1 non-text
|
|
27
|
+
contrast (≥3:1) against the kit's backgrounds. Override via --kitn-color-ring. */
|
|
28
|
+
--color-ring: var(--kitn-color-ring, hsl(217 91% 53%));
|
|
29
|
+
--color-sidebar: var(--kitn-color-sidebar, hsl(0 0% 100%));
|
|
30
|
+
/* Inline `code` accent. Blue text on a translucent blue chip. */
|
|
31
|
+
--color-code-foreground: var(--kitn-color-code-foreground, hsl(224.3 76.3% 48%));
|
|
32
|
+
/* Tool/status chip hues. Each chip is hue text over a 15% translucent fill of
|
|
33
|
+
the SAME hue (set in tool.tsx). The bare hue is too light to reach WCAG AA
|
|
34
|
+
(4.5:1) on the faint fill in LIGHT mode, so the light values are darkened;
|
|
35
|
+
dark mode keeps brighter hues for AA on the dark fill. Override via
|
|
36
|
+
--kitn-color-tool-* to retheme. */
|
|
37
|
+
--color-tool-blue: var(--kitn-color-tool-blue, hsl(217 91% 38%));
|
|
38
|
+
--color-tool-amber: var(--kitn-color-tool-amber, hsl(38 92% 28%));
|
|
39
|
+
--color-tool-green: var(--kitn-color-tool-green, hsl(142 71% 26%));
|
|
40
|
+
--color-tool-red: var(--kitn-color-tool-red, hsl(0 72% 42%));
|
|
41
|
+
--radius: var(--kitn-radius, 0.6rem);
|
|
42
|
+
--radius-sm: calc(var(--radius) - 4px);
|
|
43
|
+
--radius-md: calc(var(--radius) - 2px);
|
|
44
|
+
--radius-lg: var(--radius);
|
|
45
|
+
--radius-xl: calc(var(--radius) + 4px);
|
|
46
|
+
/* Typography scale — semantic sizes shared by all components. Each generates a
|
|
47
|
+
Tailwind utility (text-caption / text-meta / text-body / text-title). To
|
|
48
|
+
restyle the kit's typography, override the namespaced --kitn-text-* token on
|
|
49
|
+
:root (e.g. `--kitn-text-body: 0.9375rem`) — it pierces the Shadow DOM via the
|
|
50
|
+
var() fallback, exactly like the --kitn-color-* tokens. The bare --text-*
|
|
51
|
+
names stay internal so a host's own --text-* can't collide. (Message/markdown/
|
|
52
|
+
input reading size also scales with the `proseSize` prop; these tokens cover
|
|
53
|
+
the fixed chrome & controls.) */
|
|
54
|
+
--text-caption: var(--kitn-text-caption, 0.6875rem); --text-caption--line-height: 1rem; /* 11px — micro labels, badges, sub-counts */
|
|
55
|
+
--text-meta: var(--kitn-text-meta, 0.75rem); --text-meta--line-height: 1.1rem; /* 12px — controls, toggles, switchers, captions */
|
|
56
|
+
--text-body: var(--kitn-text-body, 0.875rem); --text-body--line-height: 1.45rem; /* 14px — primary reading text */
|
|
57
|
+
--text-title: var(--kitn-text-title, 1rem); --text-title--line-height: 1.5rem; /* 16px — emphasis / headers */
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
@keyframes typing { 0%,100% { transform: translateY(0); opacity: .5 } 50% { transform: translateY(-2px); opacity: 1 } }
|
|
61
|
+
@keyframes loading-dots { 0%,100% { opacity: 0 } 50% { opacity: 1 } }
|
|
62
|
+
@keyframes wave { 0%,100% { transform: scaleY(1) } 50% { transform: scaleY(.6) } }
|
|
63
|
+
@keyframes blink { 0%,100% { opacity: 1 } 50% { opacity: 0 } }
|
|
64
|
+
@keyframes text-blink { 0%,100% { color: var(--color-primary) } 50% { color: var(--color-muted-foreground) } }
|
|
65
|
+
@keyframes bounce-dots { 0%,100% { transform: scale(.8); opacity: .5 } 50% { transform: scale(1.2); opacity: 1 } }
|
|
66
|
+
@keyframes thin-pulse { 0%,100% { transform: scale(.95); opacity: .8 } 50% { transform: scale(1.05); opacity: .4 } }
|
|
67
|
+
@keyframes pulse-dot { 0%,100% { transform: scale(1); opacity: .8 } 50% { transform: scale(1.5); opacity: 1 } }
|
|
68
|
+
@keyframes shimmer-text { 0% { background-position: 150% center } 100% { background-position: -150% center } }
|
|
69
|
+
@keyframes wave-bars { 0%,100% { transform: scaleY(1); opacity: .5 } 50% { transform: scaleY(.6); opacity: 1 } }
|
|
70
|
+
@keyframes shimmer { 0% { background-position: 200% 50% } 100% { background-position: -200% 50% } }
|
|
71
|
+
@keyframes spinner-fade { 0% { opacity: 0 } 100% { opacity: 1 } }
|
|
72
|
+
@keyframes collapsible-down { from { height: 0; opacity: 0 } to { height: var(--kb-collapsible-content-height); opacity: 1 } }
|
|
73
|
+
@keyframes collapsible-up { from { height: var(--kb-collapsible-content-height); opacity: 1 } to { height: 0; opacity: 0 } }
|
|
74
|
+
.dark {
|
|
75
|
+
--color-background: var(--kitn-color-background, hsl(50 2% 9%));
|
|
76
|
+
--color-foreground: var(--kitn-color-foreground, hsl(0 0% 98%));
|
|
77
|
+
--color-card: var(--kitn-color-card, hsl(45 4% 12%));
|
|
78
|
+
--color-card-foreground: var(--kitn-color-card-foreground, hsl(0 0% 98%));
|
|
79
|
+
--color-popover: var(--kitn-color-popover, hsl(45 4% 12%));
|
|
80
|
+
--color-popover-foreground: var(--kitn-color-popover-foreground, hsl(0 0% 98%));
|
|
81
|
+
--color-primary: var(--kitn-color-primary, hsl(0 0% 98%));
|
|
82
|
+
--color-primary-foreground: var(--kitn-color-primary-foreground, hsl(45 4% 11%));
|
|
83
|
+
--color-secondary: var(--kitn-color-secondary, hsl(45 4% 17%));
|
|
84
|
+
--color-secondary-foreground: var(--kitn-color-secondary-foreground, hsl(0 0% 98%));
|
|
85
|
+
--color-muted: var(--kitn-color-muted, hsl(45 4% 17%));
|
|
86
|
+
--color-muted-foreground: var(--kitn-color-muted-foreground, hsl(45 4% 64%));
|
|
87
|
+
--color-accent: var(--kitn-color-accent, hsl(45 4% 17%));
|
|
88
|
+
--color-accent-foreground: var(--kitn-color-accent-foreground, hsl(0 0% 98%));
|
|
89
|
+
--color-destructive: var(--kitn-color-destructive, hsl(0 62.8% 30.6%));
|
|
90
|
+
--color-destructive-foreground: var(--kitn-color-destructive-foreground, hsl(0 0% 98%));
|
|
91
|
+
--color-border: var(--kitn-color-border, hsl(45 4% 17%));
|
|
92
|
+
--color-input: var(--kitn-color-input, hsl(45 4% 17%));
|
|
93
|
+
--color-ring: var(--kitn-color-ring, hsl(217 91% 68%));
|
|
94
|
+
--color-sidebar: var(--kitn-color-sidebar, hsl(50 2% 7%));
|
|
95
|
+
--color-code-foreground: var(--kitn-color-code-foreground, hsl(213 94% 78%));
|
|
96
|
+
|
|
97
|
+
/* Tool/status chip hues — dark mode. Brighter hues reach AA on the dark fill. */
|
|
98
|
+
--color-tool-blue: var(--kitn-color-tool-blue, hsl(217 91% 70%));
|
|
99
|
+
--color-tool-amber: var(--kitn-color-tool-amber, hsl(38 92% 50%));
|
|
100
|
+
--color-tool-green: var(--kitn-color-tool-green, hsl(142 71% 45%));
|
|
101
|
+
--color-tool-red: var(--kitn-color-tool-red, hsl(0 84% 70%));
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
/* Self-contained markdown styling — replaces the typography plugin's `prose`.
|
|
105
|
+
Keyed on --color-* tokens so it themes with the rest of the kit. */
|
|
106
|
+
.chat-markdown { color: var(--color-foreground); line-height: 1.6; }
|
|
107
|
+
.chat-markdown > div:first-child > :first-child { margin-top: 0; }
|
|
108
|
+
.chat-markdown > div:last-child > :last-child { margin-bottom: 0; }
|
|
109
|
+
.chat-markdown p { margin: 0 0 0.75em; }
|
|
110
|
+
.chat-markdown p:last-child { margin-bottom: 0; }
|
|
111
|
+
.chat-markdown h1, .chat-markdown h2, .chat-markdown h3, .chat-markdown h4 {
|
|
112
|
+
margin: 1.2em 0 0.5em; font-weight: 600; line-height: 1.3; color: var(--color-foreground);
|
|
113
|
+
}
|
|
114
|
+
.chat-markdown h1 { font-size: 1.4em; } .chat-markdown h2 { font-size: 1.25em; }
|
|
115
|
+
.chat-markdown h3 { font-size: 1.1em; } .chat-markdown h4 { font-size: 1em; }
|
|
116
|
+
.chat-markdown ul, .chat-markdown ol { margin: 0 0 0.75em; padding-left: 1.4em; }
|
|
117
|
+
.chat-markdown li { margin: 0.2em 0; }
|
|
118
|
+
.chat-markdown ul { list-style: disc; } .chat-markdown ol { list-style: decimal; }
|
|
119
|
+
.chat-markdown a { color: var(--color-primary); text-decoration: underline; text-underline-offset: 2px; }
|
|
120
|
+
.chat-markdown strong { font-weight: 600; color: var(--color-foreground); }
|
|
121
|
+
.chat-markdown em { font-style: italic; }
|
|
122
|
+
.chat-markdown blockquote {
|
|
123
|
+
margin: 0 0 0.75em; padding-left: 0.9em; border-left: 2px solid var(--color-border);
|
|
124
|
+
color: var(--color-muted-foreground);
|
|
125
|
+
}
|
|
126
|
+
.chat-markdown hr { margin: 1em 0; border: 0; border-top: 1px solid var(--color-border); }
|
|
127
|
+
.chat-markdown code:not(pre code) {
|
|
128
|
+
background: color-mix(in oklab, var(--color-code-foreground) 15%, transparent);
|
|
129
|
+
color: var(--color-code-foreground);
|
|
130
|
+
border-radius: 4px; padding: 0.1em 0.35em; font-size: 0.875em;
|
|
131
|
+
font-family: ui-monospace, "SF Mono", Menlo, monospace;
|
|
132
|
+
}
|
|
133
|
+
.chat-markdown table { width: 100%; border-collapse: collapse; margin: 0 0 0.75em; font-size: 0.9em; }
|
|
134
|
+
.chat-markdown th, .chat-markdown td { border: 1px solid var(--color-border); padding: 0.4em 0.6em; text-align: left; }
|
|
135
|
+
.chat-markdown th { font-weight: 600; background: color-mix(in oklab, var(--color-muted-foreground) 8%, transparent); }
|
|
136
|
+
|
|
137
|
+
.scrollbar-thin { scrollbar-width: thin; scrollbar-color: var(--color-muted) transparent; }
|