──────────────────────────────────────────────────────────────────
docs/design-system/ANTIPATTERNS.md (CC.6 — new file)
──────────────────────────────────────────────────────────────────
Twelve anti-patterns codified, every product engineer + AI agent
should treat as a hard 'no':
1. Hard-coded colour / spacing / radius values
2. Bespoke skeleton / spinner / empty-state per surface
3. Bespoke tag editor / searchable select
4. Raw API responses inside React state
5. Hidden privacy / cost / refusal state
6. Motion without prefers-reduced-motion
7. SSR-unsafe ID generation (Math.random)
8. console.log / console.error in production
9. Cross-product imports
10. `any` (especially in public API surfaces)
11. Untested primitives in @bytelyst/*
12. Animations that block keyboard focus
Each entry has Smell → Why it's wrong → Do this instead, with
canonical `@bytelyst/*` references.
──────────────────────────────────────────────────────────────────
packages/ai-ui/src/DebugOverlay.tsx (audit cleanup)
──────────────────────────────────────────────────────────────────
Dropped dead `patchSingleChild` helper. It cloned the single child
unchanged, doing literally nothing — the click handler always lived
on the outer <span>. Replaced the call site with `{children}` and
removed 4 unused React imports (Children, cloneElement,
isValidElement, ReactElement).
Same 98/98 tests pass.
──────────────────────────────────────────────────────────────────
Roadmap flips (this commit + the prior unflag pass)
──────────────────────────────────────────────────────────────────
9.E.1 <Markdown> + citation interop ai-ui@0.6.0
9.E.2 <CodeDiff> split + unified ai-ui@0.6.0
9.E.3 <ExplainThis> ai-ui@0.6.0
9.E.4 usePromptHistory ai-ui@0.6.0
9.E.5 useTokenCount ai-ui@0.6.0
9.E.6 /showcase/ai-ui/markdown showcase
13.C.4 <ProvenanceDrawer> ai-ui@0.5.0+
13.C.5 <DebugOverlay> ai-ui@0.5.0+
13.C.6 <PrivacyBadge> ai-ui@0.5.0+
13.D.1 <Parallax> motion@0.2.1
13.D.5 <TiltGallery> motion@0.2.1
CC.6 ANTIPATTERNS.md docs
MAG.8 /showcase/futurism/debug-overlay showcase
§11.2 counter rewrote (37 / 202 done · 18%)
Wave 9 Data: 9/42 → 15/42 (36%)
Wave 13 Futurism: 9/39 → 17/39 (44%)
Cross-cutting: 0/8 → 1/8 (13%)
Magnet demos: 2/8 → 3/8 (38%)
Three MAG.* magnets are now live:
✨ MAG.1 spatial-hero (Wave 13.D.6)
✨ MAG.3 trust-surfaces (Wave 13.C.7)
✨ MAG.8 debug-overlay (Wave 13.C.5)
|
||
|---|---|---|
| .. | ||
| src | ||
| package.json | ||
| README.md | ||
| tsconfig.json | ||
| vitest.config.ts | ||
@bytelyst/ai-ui
AI-native UI primitives for ByteLyst products. The flagship deliverable
of Wave 2 in learning_ai_uxui_web/docs/ROADMAP_2026.md.
Status:
0.1.0MVP — 3 components + 1 hook + 1 utility. Subsequent 0.x bumps add<ToolCallCard>,<CitationChip>,<AgentTimeline>,<ModelPicker>,<ToolPalette>, and theuseToolCalls/usePromptHistory/useTokenCounthooks.
Quick start
import { ChatStream } from '@bytelyst/ai-ui';
export function ChatPage() {
return (
<div style={{ height: '70vh' }}>
<ChatStream
endpoint="/api/chat"
placeholder="Ask anything…"
emptyState={<EmptyHint />}
/>
</div>
);
}
Architectural decisions
Per learning_ai_common_plat/docs/ROADMAP_2026_DECISIONS.md:
- §10 hook shape —
useChat()returns the same shape as Vercel AI SDK'suseChat. Drop-in compatible for any engineer who has already written a chat UI with the AI SDK. - Transport is pluggable — products inject
endpoint,streamProtocol,fetcher, orheaders. We are not locked to Vercel's SSE wire format.
Components
<ChatStream>
Opinionated composition of useChat + <MessageBubble> +
<PromptComposer>. Auto-scrolls (sticky-bottom), shows Stop while
streaming, surfaces transport errors inline.
<MessageBubble>
Single chat message atom. Variants by role (user / assistant / system /
tool). Built-in "thinking" indicator while streaming with no content
yet. Honors --bl-* design tokens.
<PromptComposer>
Multi-line input. Enter submits, Shift+Enter newlines, Cmd/Ctrl+Enter
alternates submit. Auto-grows up to maxLines. Slot for leading
actions (slash-commands etc.).
Hooks
useChat(options?)
Vercel-AI-SDK-shaped:
const {
messages, input, setInput, handleInputChange, handleSubmit,
append, isLoading, error, stop, reload, setMessages
} = useChat({
endpoint: '/api/chat',
streamProtocol: 'text', // 'text' | 'sse' | 'data'
initialMessages: [],
onFinish: (msg) => console.log('done', msg),
onError: (err) => console.error(err),
});
streamText(response, protocol?, signal?)
Low-level async generator that yields text deltas from a streaming
HTTP response. Supports 'text', 'sse', and 'data' protocols.
Wire protocols
| Protocol | Body format | Use when |
|---|---|---|
'text' (default) |
Plain text, streamed chunk-by-chunk | Any backend that pipes an LLM stream directly |
'sse' |
Server-Sent Events with data: ... frames |
OpenAI-compatible, Anthropic, most HF inference |
'data' |
Vercel AI SDK "data stream" prefix protocol | Backends using streamText() from ai/server |
For tool calls / citations / images, use 'sse' or 'data' once the
matching components ship in 0.2.x.
Tests
pnpm --filter @bytelyst/ai-ui test
Roadmap
0.2.0—<ToolCallCard>,<CitationChip>,useToolCalls()0.3.0—<AgentTimeline>,<ModelPicker>0.4.0—<ToolPalette>with MCP discovery0.5.0—<Markdown>+<CodeDiff>(Wave 2 stretch)1.0.0— API freeze when 3+ products consume in production