@elyxndra/ui
v0.1.0
Published
Elyxndra's shared chat/agent panel: React + Tailwind v4 components (transcript, tool rows, diffs, approvals, composer with mode/model pickers) styled with VS Code theme variables. Used by Elyxndra's desktop chat app and editor extension.
Downloads
85
Maintainers
Readme
@elyxndra/ui
Elyxndra's agent panel as a React component library: an IDE-style transcript (user turns, streamed replies with collapsible thinking, compact tool rows with expandable output, diff chips with revert, approval and question cards, task list), the composer (mode and model pickers, @ file context, / commands, context meter, stop/send) and the markdown renderer. React 19 + Tailwind v4 + Radix + lucide, styled entirely with the editor's --vscode-* theme variables so it matches whatever theme the host runs. Used by Elyxndra's desktop chat app and editor extension.
npm install @elyxndra/ui react react-domUsage
Mount the whole panel and connect it to your host through the bridge (the extension wires it to acquireVsCodeApi(), the desktop app to IPC):
import { createRoot } from "react-dom/client";
import { App, configureBridge } from "@elyxndra/ui";
import "@elyxndra/ui/styles.css"; // Tailwind source — process it with your own Tailwind build
configureBridge({
post: (m) => host.send(m), // ToExtension messages: send, stop, setMode, openFile, showDiff…
onMessage: (h) => host.subscribe(h), // ToWebview messages: state, delta, files, focus…
getState: (key, fallback) => persisted[key] ?? fallback,
setState: (key, value) => (persisted[key] = value),
});
createRoot(document.getElementById("root")!).render(<App />);The wire protocol lives in @elyxndra/ui/protocol (ViewState, ToWebview, ToExtension). The host pushes a state snapshot on structural change and delta events while a reply streams; the panel applies deltas locally.
Or compose the pieces yourself:
import { Markdown, AssistantMessage, UserMessage, ToolRow, Composer } from "@elyxndra/ui";
import { useStickToBottom, useAutoGrowTextarea, isSubmitKey, isStopKey } from "@elyxndra/ui";ViewState.engine carries the daemon's engine view (EngineStateDTO, active engine, model being loaded, typed from @elyxndra/engine/api); engineStateLabel(engine) collapses it to the 4-state label the panel renders. Tool rows take their icon from each tool's definition (ViewState.tools[].def.icon, a lucide name); ToolIcon({ icon }) renders it.
Notes
react/react-domare peer dependencies (one React runtime in the webview);tailwindcssis an optional peer for processingstyles.css.@elyxndra/agent(types,parseArguments, attachment helpers,shortModel,contextMeter) and@elyxndra/engine/api(compactNumber, DTO types) are runtime dependencies, imported from their browser-safe entries only.styles.cssis Tailwind source (@import "tailwindcss"+ tokens mapped to VS Code variables); the consumer's Tailwind build scans this package'sdist/via its@source.- The panel renders markdown without raw HTML and never emits a remote image:
in model output is shown as its alt text, not fetched (model output is untrusted, and an image load would be a silent exfiltration channel that skips every approval). Hosts should still setimg-src 'self' data:in their CSP. Links open through the host (openExternal/openFile).
Part of the Elyxndra monorepo · MIT
