@dataworm/zero-shot
v0.1.0
Published
The AI-native React component library — Dual API components that LLMs generate correctly, every time
Maintainers
Readme
ZeroShot
The AI-native React component library. Every component works two ways:
- Compositional API — sub-components for humans writing JSX
- Config API — flat declarative props that LLMs generate correctly on the first try
Built on Radix UI primitives, Tailwind CSS, and TypeScript with strict: true.
Why ZeroShot?
| Problem | ZeroShot Solution |
|---|---|
| LLMs hallucinate component APIs | Machine-readable manifest — inject the schema into your system prompt |
| Config objects vs JSX composition tradeoff | Dual API — every component supports both |
| No first-class AI app components | ChatThread, StreamingText, PromptInput, SchemaForm, CodeBlock, MarkdownView |
| Loose TypeScript, any-heavy libs | Strict mode, no any, full inference |
Features
- Dual API — Compositional (sub-components) + Config (flat props) on every component
- 9 AI-Native Components — ChatThread, StreamingText, CodeBlock, MarkdownView, PromptInput, SchemaForm, CopyButton, EmptyState, LoadingOverlay
- ZeroShotManifest — JSON schema of all components/props/variants for LLM system prompts
- 40+ Foundation Components — Accordion, Dialog, Select, Tabs, and more
- TypeScript Strict —
strict: true,noImplicitAny: true,strictNullChecks: true - Accessible — Radix UI primitives, WAI-ARIA patterns
- Dark Mode — CSS variable-based theming with light/dark
- Tree-Shakeable — ESM + CJS, import only what you use
- Zero-Config Toast — React Context-based, SSR-safe, 6 positions
- React 18 + 19 — Works with both
Installation
npm install zero-shotnpm install react react-domQuick Start
import { Button, ChatThread, SchemaForm, ToastProvider, Toaster } from "zero-shot";
import "zero-shot/styles.css";
function App() {
return (
<ToastProvider>
{/* Config API — LLMs love this */}
<Button label="Click me" variant="default" loading={false} />
{/* Compositional API — humans love this */}
<Button variant="outline">
<Icon /> Click me
</Button>
{/* AI-native: full chat UI in one component */}
<ChatThread
messages={messages}
loading={isStreaming}
onSend={handleSend}
/>
{/* Schema-driven forms */}
<SchemaForm
schema={[
{ name: "email", type: "email", label: "Email", required: true },
{ name: "name", type: "text", label: "Name" },
]}
onSubmit={(values) => console.log(values)}
/>
<Toaster position="bottom-right" />
</ToastProvider>
);
}Dual API Examples
Every core component supports both APIs. Use whichever fits your workflow:
Button
{/* Config API (great for LLMs) */}
<Button label="Save" variant="default" loading={isSaving} icon={<Save />} />
{/* Compositional API (great for custom layouts) */}
<Button variant="outline" size="sm">
<Save className="mr-2 h-4 w-4" /> Save Draft
</Button>Dialog
{/* Config API */}
<Dialog
open={open}
onOpenChange={setOpen}
title="Confirm Delete"
description="This action cannot be undone."
actions={[
{ label: "Cancel", variant: "outline", closeOnClick: true },
{ label: "Delete", variant: "destructive", onClick: handleDelete },
]}
/>
{/* Compositional API */}
<Dialog>
<DialogTrigger asChild><Button>Open</Button></DialogTrigger>
<DialogContent>
<DialogHeader>
<DialogTitle>Custom Layout</DialogTitle>
</DialogHeader>
{/* full control */}
</DialogContent>
</Dialog>Tabs
{/* Config API */}
<Tabs
defaultValue="general"
items={[
{ value: "general", label: "General", content: <GeneralSettings /> },
{ value: "security", label: "Security", content: <SecuritySettings /> },
]}
/>AI-Native Components
ChatThread
<ChatThread
messages={[
{ role: "user", content: "Explain React hooks" },
{ role: "assistant", content: "React hooks are functions that..." },
]}
loading={isStreaming}
onSend={(msg) => sendMessage(msg)}
autoScroll
/>StreamingText
<StreamingText
text="Hello, I'm an AI assistant..."
speed="natural"
mode="word"
cursor
/>PromptInput
<PromptInput
onSubmit={handleSubmit}
onCancel={handleCancel}
loading={isGenerating}
showTokenCount
maxTokens={4096}
submitKey="enter"
/>SchemaForm
<SchemaForm
schema={[
{ name: "email", type: "email", label: "Email", required: true },
{ name: "role", type: "select", label: "Role", options: [
{ value: "admin", label: "Admin" },
{ value: "user", label: "User" },
]},
{ name: "bio", type: "textarea", label: "Bio", maxLength: 500 },
]}
columns={2}
onSubmit={async (values) => await createUser(values)}
submitLabel="Create Account"
/>CodeBlock
<CodeBlock
code={`const greeting = "Hello, world!";`}
language="typescript"
showLineNumbers
copyable
title="example.ts"
/>MarkdownView
<MarkdownView
content={assistantResponse}
copyable
/>ZeroShotManifest
Import the machine-readable manifest for LLM integration:
import manifest from "zero-shot/manifest";
// Inject into your LLM system prompt:
const systemPrompt = `You are a UI builder. Use these components:\n${JSON.stringify(manifest)}`;Styling Setup
Import styles in your entry file:
import "zero-shot/styles.css";Configure Tailwind CSS
/** @type {import('tailwindcss').Config} */
module.exports = {
content: [
"./src/**/*.{js,jsx,ts,tsx}",
"./node_modules/zero-shot/**/*.{js,mjs}",
],
theme: {
extend: {},
},
plugins: [],
};Component Catalog
AI-Native Components
| Component | Description |
|---|---|
| ChatThread | Full conversation UI with messages, typing indicator, auto-scroll, built-in input |
| ChatBubble | Individual message bubble (user/assistant/system) |
| StreamingText | Typewriter effect for LLM responses (char/word mode, cursor) |
| CodeBlock | Code display with copy, line numbers, language badge, line highlight |
| CopyButton | Clipboard copy with visual feedback |
| MarkdownView | Zero-dependency Markdown renderer (headings, lists, code blocks, links) |
| PromptInput | Auto-resize prompt textarea with token counter, Cmd+Enter, cancel button |
| SchemaForm | Declarative schema → full form with validation, grouped fields, 2-column layout |
| EmptyState | Empty data placeholder with icon, title, description, action |
| LoadingOverlay | Loading overlay with spinner or skeleton mode |
Core Components (Dual API)
| Component | Config Props |
|---|---|
| Button | label, loading, icon, iconPosition |
| Input | label, error, helperText, startAdornment, endAdornment |
| Textarea | label, error, helperText, showCount |
| Card | title, description, footer |
| Dialog | title, description, actions[] |
| Select | options[], label, error, placeholder |
| Alert | title, description, icon, closable, onClose |
| Badge | label, dot, removable, onRemove |
| Tabs | items[] with { value, label, content, disabled } |
| Accordion | items[] with { value, trigger, content, disabled } |
Foundation Components
Accordion, AlertDialog, Avatar, Breadcrumb, Checkbox, Command, DataTable, Dialog, Drawer, DropdownMenu, Form, HoverCard, Label, Pagination, Popover, Progress, RadioGroup, Resizable, ScrollArea, Select, Separator, Sheet, Sidebar, Skeleton, Slider, Switch, Table, Tabs, Toggle, ToggleGroup, Tooltip
Theming
ZeroShot uses CSS variables for theming. Override any token:
:root {
--primary: 220 70% 50%;
--radius: 0.75rem;
/* ZeroShot AI tokens */
--zero-shot-chat-user: 222.2 47.4% 11.2%;
--zero-shot-chat-assistant: 210 40% 96%;
--zero-shot-streaming-speed: 30ms;
}Dark mode via the dark class on <html>.
Development
npm run storybook # Interactive docs at http://localhost:6006
npm run build # ESM + CJS + types + styles
npm test # VitestLicense
MIT
Acknowledgments
ZeroShot is built on Radix UI, Tailwind CSS, Lucide, and inspired by shadcn/ui.
