UNPKG

@kitn.ai/chat

Version:

Framework-agnostic, Shadow-DOM web components for building AI chat interfaces — works in React, Vue, Angular, Svelte, or plain HTML. Authored in SolidJS.

145 lines (127 loc) 5.33 kB
import type { ExampleUsage, StoryUsage } from './types'; /** New Chat — a centered greeting (icon + title + description), starter suggestion chips, and a composer. */ const newChat: StoryUsage = { intro: "The new-chat zero state. `<kc-empty>` renders the centered greeting from two scalar props — `emptyTitle` (DOM attribute `empty-title`, since `title` is a global HTML attribute) and `description`. The icon, the starter suggestion chips, and the composer below aren't part of `<kc-empty>` — compose those with the SolidJS `Empty` + `PromptSuggestion` + `PromptInput` primitives (see the Solid tab).", snippets: { html: `<!-- Register the elements once (CDN or bundler) --> <script type="module"> import 'https://cdn.jsdelivr.net/npm/@kitn.ai/chat/dist/kitn-chat.es.js'; </script> <!-- Scalars are plain attributes. Note the kebab-case empty-title. --> <kc-empty empty-title="How can I help today?" description="Ask anything, or start from one of these." ></kc-empty> <!-- The icon, suggestion chips, and composer are not part of <kc-empty>; compose them yourself (see the Solid tab). -->`, react: `import { Empty } from '@kitn.ai/chat/react'; export function NewChat() { // Icon, suggestion chips, and composer aren't props on <Empty> — // compose them yourself (see the Solid tab). return ( <Empty emptyTitle="How can I help today?" description="Ask anything, or start from one of these." /> ); }`, vue: `<script setup> import '@kitn.ai/chat/elements'; // register once (e.g. in main.ts) </script> <template> <!-- Scalars as plain attributes; empty-title is kebab-case. --> <kc-empty empty-title="How can I help today?" description="Ask anything, or start from one of these." /> <!-- Icon, suggestions, and composer are composed separately. --> </template>`, svelte: `<script> import '@kitn.ai/chat/elements'; // register once </script> <!-- Scalars as attributes; empty-title is kebab-case. --> <kc-empty empty-title="How can I help today?" description="Ask anything, or start from one of these." ></kc-empty> <!-- Icon, suggestions, and composer are composed separately. -->`, angular: `// main.ts: import '@kitn.ai/chat/elements' before bootstrapApplication, // and add CUSTOM_ELEMENTS_SCHEMA to the component. import { Component, CUSTOM_ELEMENTS_SCHEMA } from '@angular/core'; @Component({ selector: 'app-new-chat', standalone: true, schemas: [CUSTOM_ELEMENTS_SCHEMA], // empty-title is kebab-case; both props are scalar strings. template: \` <kc-empty empty-title="How can I help today?" description="Ask anything, or start from one of these." ></kc-empty> \`, }) export class NewChatComponent {}`, solid: `import { createSignal } from 'solid-js'; import { ChatConfig, Empty, EmptyHeader, EmptyMedia, EmptyTitle, EmptyDescription, EmptyContent, PromptSuggestion, PromptInput, PromptInputTextarea, PromptInputActions, Button, } from '@kitn.ai/chat'; import { Sparkles, Plus, Globe, ArrowUp } from 'lucide-solid'; const SUGGESTIONS = [ 'Summarize a document', 'Draft a product update', 'Explain a code snippet', 'Plan my week', ]; export function NewChat() { const [input, setInput] = createSignal(''); return ( <ChatConfig proseSize="base"> <Empty class="flex-1"> <EmptyHeader> <EmptyMedia variant="icon"><Sparkles class="size-6" /></EmptyMedia> <EmptyTitle>How can I help today?</EmptyTitle> <EmptyDescription>Ask anything, or start from one of these.</EmptyDescription> </EmptyHeader> <EmptyContent> <div class="flex max-w-md flex-wrap justify-center gap-2"> {SUGGESTIONS.map((s) => ( <PromptSuggestion onClick={() => setInput(s)}>{s}</PromptSuggestion> ))} </div> </EmptyContent> </Empty> {/* Composer fills from a clicked suggestion. */} <PromptInput value={input()} onValueChange={setInput} onSubmit={() => setInput('')}> <PromptInputTextarea placeholder="Ask anything…" /> <PromptInputActions class="flex items-center justify-between gap-2"> <div class="flex items-center gap-2"> <Button variant="outline" size="icon-sm" class="rounded-full" aria-label="Add"><Plus class="size-4" /></Button> <Button variant="outline" size="sm" class="rounded-full gap-1" aria-label="Search the web"><Globe class="size-4" />Search</Button> </div> <Button size="icon-sm" class="rounded-full" disabled={!input().trim()} aria-label="Send message"> <ArrowUp class="size-4" /> </Button> </PromptInputActions> </PromptInput> </ChatConfig> ); }`, }, }; /** * Pattern: Empty State — the new-chat zero state. `<kc-empty>` covers the * centered greeting (`emptyTitle` + `description`); the icon, starter * suggestion chips, and composer are SolidJS primitive composition. Per-story: * the Usage tab shows the snippet for the story you're on; the example-level * fields below are the fallback. */ const emptyState: ExampleUsage = { title: 'Patterns/Empty State', ...newChat, // example-level fallback = the primary "New Chat" story stories: { 'New Chat': newChat, }, }; export default emptyState;