Components•AI chat app
Components•AI chat app
AI chat app
A complete chat app: searchable history grouped by day, a model picker, streamed replies you can stop, light markdown with copyable code blocks, copy, feedback and regenerate on each answer, edit-and-resend for your last message, file attachments by picker, paste or drop, and a jump-to-latest button when you scroll up. It runs on a local simulator until you pass your own streaming function.
Dependencies
Copy below cli
npx shadcn@latest add https://ui.isaiahbjork.com/app-ai-chat.jsonHow to use
import { AppAiChat } from "@/components/bjork-ui/blocks/app-ai-chat";export function Chat() { return ( <div className="h-dvh"> <AppAiChat conversations={[]} models={[{ id: "fast", name: "Fast", hint: "Quick answers" }]} // Yield text chunks as they arrive; stop when the signal aborts. respond={async function* ({ messages, model, signal }) { const res = await fetch("/api/chat", { method: "POST", body: JSON.stringify({ messages, model }), signal, }); const reader = res.body!.pipeThrough(new TextDecoderStream()).getReader(); while (true) { const { value, done } = await reader.read(); if (done) return; yield value; } }} onConversationsChange={(all) => localStorage.setItem("chats", JSON.stringify(all))} /> </div> );}
Debounce vs throttle for search
Debounce vs throttle for search
Rhea Castillo said
Should the dashboard search input be debounced or throttled?Assistant said
Debounce it. You want one query after the person stops typing, not a query every N milliseconds while they type.
- Debounce waits for a pause, then fires once. Right for search, autosave and resize-driven layout.
- Throttle fires at most once per interval while events keep coming. Right for scroll position and pointer tracking.
A small version:
tsfunction debounce<T extends unknown[]>(fn: (...args: T) => void, ms = 200) { let timer: ReturnType<typeof setTimeout> | undefined; return (...args: T) => { clearTimeout(timer); timer = setTimeout(() => fn(...args), ms); }; }For a filter over data already in memory, skip both and filter on every keystroke; it's fast enough and feels more direct.
Answers can be wrong. Check anything important.