learning_ai_common_plat/packages/ai-ui
saravanakumardb1 87e3bc490a feat: Wave 9.E (ai-ui@0.6.0) + Wave 13.D.1/.5 (motion@0.2.1)
──────────────────────────────────────────────────────────────────
motion@0.2.1 — Parallax + TiltGallery
──────────────────────────────────────────────────────────────────
  + Parallax.tsx
      - scroll-driven translate3d via rAF + window.scroll
      - speed multiplier + axis (y / x) + reduced-motion bypass
      - listener cleanup + cancelAnimationFrame on unmount
      - WAVE 13.D.1
  + TiltGallery.tsx
      - horizontally-scrolling rail of <TiltCard>-style tiles
      - per-tile cursor-tracking rotateX/Y + glare gradient
      - role=region + arrow-key scrolling (←/→) + scroll-snap
      - reduced-motion strips tilt + glare, keeps the rail
      - WAVE 13.D.5
  + 5 new tests (Parallax x 2, TiltGallery x 3) — 28/28 passing
  + index.ts: exports both + types
  + package.json: 0.2.0 → 0.2.1

──────────────────────────────────────────────────────────────────
ai-ui@0.6.0 — Wave 9.E composition surfaces
──────────────────────────────────────────────────────────────────
  + Markdown.tsx
      - dep-free subset renderer: h1-h3 / **bold** / *italic* /
        `code` / fenced code / ul + ol / [text](url)
      - inline `[cite:<id>]` chips resolved from a citations
        registry (missing ids render as [?] — failure mode is loud)
      - WAVE 9.E.1
  + CodeDiff.tsx
      - line-LCS diff in <100 LOC, zero deps
      - split (2-col) and unified views; tinted add/del rows
      - WAVE 9.E.2
  + ExplainThis.tsx
      - listens for selectionchange, pops 'Explain' CTA over the
        selection rect when inside the wrapper + ≥ minLength chars
      - fires onExplain({ text, rect }) so hosts can open a richer
        side panel if preferred
      - WAVE 9.E.3
  + usePromptHistory.ts
      - bash-style ↑/↓ recall with localStorage persistence
        (storage key configurable; null = in-memory for tests/SSR)
      - dedupes consecutive duplicates + trims to capacity
      - WAVE 9.E.4
  + useTokenCount.ts
      - cheap estimator (default ~4 chars/token; configurable for
        code/CJK) + optional USD cost
      - memoised — stable across re-renders
      - WAVE 9.E.5
  + 19 new tests in src/__tests__/composition.test.tsx — 98/98 passing
  + index.ts: '0.6 surfaces' section exports all 5 + types
  + package.json: 0.5.0 → 0.6.0

Showcase routes + roadmap flips land in the paired showcase commit.
2026-05-27 16:59:28 -07:00
..
src feat: Wave 9.E (ai-ui@0.6.0) + Wave 13.D.1/.5 (motion@0.2.1) 2026-05-27 16:59:28 -07:00
package.json feat: Wave 9.E (ai-ui@0.6.0) + Wave 13.D.1/.5 (motion@0.2.1) 2026-05-27 16:59:28 -07:00
README.md feat(ai-ui): Wave 2 MVP @bytelyst/ai-ui@0.1.0 2026-05-27 12:07:23 -07:00
tsconfig.json feat(ai-ui): Wave 2 MVP @bytelyst/ai-ui@0.1.0 2026-05-27 12:07:23 -07:00
vitest.config.ts feat(ai-ui): Wave 2 MVP @bytelyst/ai-ui@0.1.0 2026-05-27 12:07:23 -07:00

@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.0 MVP — 3 components + 1 hook + 1 utility. Subsequent 0.x bumps add <ToolCallCard>, <CitationChip>, <AgentTimeline>, <ModelPicker>, <ToolPalette>, and the useToolCalls / usePromptHistory / useTokenCount hooks.

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 shapeuseChat() returns the same shape as Vercel AI SDK's useChat. 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, or headers. 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 discovery
  • 0.5.0<Markdown> + <CodeDiff> (Wave 2 stretch)
  • 1.0.0 — API freeze when 3+ products consume in production