import type { Meta, StoryObj } from 'storybook-solidjs-vite'; import { createSignal } from 'solid-js'; import { ChatContainer, ChatContainerContent, ChatContainerScrollAnchor, Message, MessageAvatar, MessageContent, MessageActions, PromptInput, PromptInputTextarea, PromptInputActions, Checkpoint, CheckpointIcon, CheckpointTrigger, Button, Separator, } from '../index'; import { Copy, ThumbsUp, ThumbsDown, ArrowUp, RotateCcw } from 'lucide-solid'; const meta: Meta = { title: 'Examples/Checkpoint & Restore', parameters: { layout: 'padded', docs: { description: { component: [ 'Mark named restore points in a conversation. `` (or the SolidJS `Checkpoint` primitive) renders a bookmark button that fires `kc-select` (no detail payload) when clicked.', '', '**"Restoring" is your responsibility — the element just emits an event.** When `kc-select` fires, slice your message array back to the messages that existed at that checkpoint. The element has no internal state management.', '', '**Where checkpoints come from:** create a checkpoint entry in your message list after each AI response you want to mark as a save point. The `label` / `tooltip` props are plain strings passed to the element.', '', '**`` WC props:** `label` (optional visible text), `tooltip` (hover text), `variant` (`ghost` | `default` | `outline`, default `ghost`), `size` (`sm` | `md` | `lg` | `icon` | `icon-sm`, default `sm`). The icon is always the built-in `CheckpointIcon` — there is no `icon` prop on the WC (planned gap in the capability-gaps spec).', '', '**Custom icon in the trigger:** compose the SolidJS `Checkpoint` + `CheckpointIcon` + `CheckpointTrigger` primitives. The demo places a `` icon inside `CheckpointTrigger` — that works because `CheckpointTrigger` accepts arbitrary children.', ].join('\n'), }, }, }, }; export default meta; type Story = StoryObj; export const Default: Story = { name: 'API Design Session with Restore Points', parameters: { docs: { description: { story: [ 'Three-exchange API design session with two checkpoints. Clicking a checkpoint updates the header label — in a real app you would also slice your message array back to the messages that existed at that point.', '', '**`kc-select` carries no detail payload** — you identify which checkpoint was clicked by which handler you wired up, not from the event itself. Confirmed in `src/elements/checkpoint.tsx`.', '', '**The `` icon in the trigger is a SolidJS-only touch** — the `` WC always uses the built-in `CheckpointIcon` (no `icon` prop). Compose `CheckpointTrigger` with custom children only when using the SolidJS primitives.', ].join('\n'), }, }, }, render: () => { const [restoredTo, setRestoredTo] = createSignal(null); return (

API Design Session

{restoredTo() && ( Restored to checkpoint: {restoredTo()} )}
{/* Initial exchange */} I'm designing a REST API for a task management app. What should the core endpoints look like?
{`Here's a clean REST resource design for task management: \`\`\` GET /api/tasks # List tasks (with filters) POST /api/tasks # Create task GET /api/tasks/:id # Get single task PATCH /api/tasks/:id # Update task DELETE /api/tasks/:id # Delete task GET /api/projects # List projects POST /api/projects # Create project GET /api/projects/:id/tasks # Tasks within a project \`\`\` Key design decisions: - Use **PATCH** over PUT for partial updates - Nest tasks under projects for scoped queries - Support filtering via query params: \`?status=active&assignee=me\``}
{/* First checkpoint */} setRestoredTo('API structure defined')} >
API structure defined
{/* Second exchange */} What about authentication? Should I use JWT or session cookies?
{`For a task management API, I'd recommend **JWT with refresh tokens**: \`\`\`typescript // Auth endpoints POST /api/auth/login // Returns access + refresh tokens POST /api/auth/refresh // Exchanges refresh for new access token POST /api/auth/logout // Invalidates refresh token // Middleware function authMiddleware(req, res, next) { const token = req.headers.authorization?.split(' ')[1]; try { req.user = jwt.verify(token, SECRET); next(); } catch { res.status(401).json({ error: 'Invalid token' }); } } \`\`\` **Why JWT over sessions:** - Stateless -- no server-side session store needed - Works across subdomains and mobile apps - Access tokens expire in 15min, limiting damage from theft **The tradeoff:** you can't instantly revoke JWTs. Mitigate this with short expiry + a blocklist for critical cases (password change, account compromise).`}
{/* Second checkpoint */} setRestoredTo('Auth strategy chosen')} >
Auth strategy chosen
{/* Third exchange after checkpoint */} Now help me think about error handling. What's a good error response format?
{`Use a consistent error envelope inspired by the **RFC 7807 Problem Details** spec: \`\`\`typescript interface ApiError { status: number; // HTTP status code code: string; // Machine-readable error code message: string; // Human-readable description details?: unknown[]; // Validation errors, field-level info requestId: string; // For debugging/support } // Example responses // 400 Bad Request { "status": 400, "code": "VALIDATION_ERROR", "message": "Invalid task data", "details": [ { "field": "title", "error": "Required field missing" }, { "field": "dueDate", "error": "Must be a future date" } ], "requestId": "req_abc123" } // 404 Not Found { "status": 404, "code": "RESOURCE_NOT_FOUND", "message": "Task not found", "requestId": "req_def456" } \`\`\` Always include the \`requestId\` -- it's invaluable for correlating client errors with server logs.`}
); }, };