From 20287f368f6f6187be159857618b956a4562608a Mon Sep 17 00:00:00 2001 From: Sawyer Cutler Date: Thu, 24 Sep 2026 23:04:06 -0700 Subject: [PATCH] docs(readme): bun add, ChatThread example, component index Drops the pin-a-commit guidance and the Thinking indicator showcase, which its Ladle story covers, and links repo docs by absolute GitHub URL so they resolve on npm. --- README.md | 208 +++++++++++++++++++++++++++++++++++++++++++++--------- 1 file changed, 174 insertions(+), 34 deletions(-) diff --git a/README.md b/README.md index 72616506..586b901e 100644 --- a/README.md +++ b/README.md @@ -18,18 +18,9 @@ Optional peers, needed only by the subpaths that import them. These modules are ## Quickstart ```bash -npm add @corbits/react-ui -pnpm add @corbits/react-ui -yarn add @corbits/react-ui bun add @corbits/react-ui ``` -Until a release is cut, consumers pin a commit instead of a version range: - -```json -"@corbits/react-ui": "github:corbitsdev/react-ui#" -``` - Import the stylesheet once at the app root, before your own CSS (no Tailwind build required). Mount `ThemeProvider` near the root so dark mode persists per user, and `Toaster` once alongside it so any component can call `toast()`: ```tsx @@ -80,17 +71,188 @@ export function NotFoundPage() { } ``` +A conversation is a `ChatThread` over a `messages` array; each message is an ordered list of parts, so an agent turn can interleave text and tool calls: + +```tsx +import { ChatThread, type ChatMessage } from "@corbits/react-ui"; + +const messages: ChatMessage[] = [ + { + id: "m1", + role: "user", + createdAt: "2026-01-01T09:00:00Z", + parts: [{ type: "text", text: "What changed in the repo today?" }], + }, + { + id: "m2", + role: "agent", + createdAt: "2026-01-01T09:00:04Z", + parts: [ + { + type: "tool", + toolCallId: "t1", + toolName: "git__log", + label: "Read today's commits", + state: "done", + output: "3 commits", + }, + { type: "text", text: "Three commits landed today, all in the docs." }, + ], + }, +]; + +export function Conversation() { + return ( +
+ +
+ ); +} +``` + Every component is importable by subpath (`@corbits/react-ui/ui/button`); all but the optional-peer modules above are also exported from the root (`@corbits/react-ui`). The brand faces (Red Hat Display, Space Mono) are named by the theme but not bundled. Load them yourself, or the stack falls through to system fonts; to use a face loaded under a generated name, override `--font-sans` / `--font-mono`. This package ships no `"use client"` directives. In a React Server Components app, re-export stateful components from a file you mark yourself, using subpaths rather than the root barrel. +## Components + +Subpaths are relative to `@corbits/react-ui/`. + +### Chat + +| Component | Subpath | What it is | +| --- | --- | --- | +| `ChatThread` | `ui/chat-thread` | Scrolling transcript of user and agent messages | +| `AgentTurn` | `ui/agent-turn` | One agent reply: reasoning, tool calls, answer, in order | +| `MessageBubble` | `ui/message-bubble` | One user or system message | +| `ChatInput` | `ui/chat-input` | Auto-growing message input with a send/stop button | +| `ChatComposer` | `ui/chat-composer` | `ChatInput` with suggestion chips for an empty conversation | +| `ChatPanel` | `ui/chat-panel` | Docked chat frame with header and footer | +| `PartsRenderer` | `ui/parts-renderer` | Renders a list of message parts | +| `ReasoningBlock` | `ui/reasoning-block` | Collapsible thinking text | +| `ToolBlock` | `ui/tool-block` | A tool call's lifecycle: running, done, failed | +| `ToolNarrative` | `ui/tool-narrative` | What the agent did, as one expandable line | +| `ToolPicker` | `ui/tool-picker` | Browse, search and select tools | +| `QuickReplyChips` | `ui/quick-reply-chips` | Tappable suggested replies | +| `TypingIndicator` | `ui/typing-indicator` | Agent-is-typing dots | +| `ThinkingIndicator` | `ui/thinking-indicator` | Animated Corbits mark with a status label | +| `ThinkingMark` | `ui/thinking-mark` | Decorative animated Corbits mark | +| `ThinkingLabel` | `ui/thinking-label` | Rotating-verb status label | +| `ShimmerText` | `ui/shimmer-text` | Shimmer sweep over text | +| `MicButton` | `ui/mic-button` | Permission-aware microphone toggle | +| `VoiceWaveform` | `ui/voice-waveform` | Live audio level bars | +| `DictationStatusLine` | `ui/dictation-status-line` | Composer dictation status row | +| `MicPermissionDialog` | `ui/mic-permission-dialog` | Microphone permission prompt | + +### Runs + +| Component | Subpath | What it is | +| --- | --- | --- | +| `LiveRunBanner` | `ui/live-run-banner` | Status of a run in progress | +| `LiveStatusLine` | `ui/live-status-line` | The single "what's happening now" line | +| `ApprovalCard` | `ui/approval-card` | Approve or reject a pending action | +| `GateBlock` | `ui/gate-block` | Chrome for a run parked on a human decision | +| `StepList` | `ui/step-list` | Vertical list of run steps and their status | +| `HorizontalStepper` | `ui/horizontal-stepper` | Horizontal step progress | +| `ProgressChecklist` | `ui/progress-checklist` | Steps of a long operation and how far along it is | +| `TraceWaterfall` | `ui/trace-waterfall` | Run-trace timeline, one row per span | +| `IntakeForm` | `ui/intake-form` | Inputs a workflow asks for before it runs | +| `RunNowButton` | `ui/run-now-button` | Run something immediately | +| `ConfirmButton` | `ui/confirm-button` | Button that asks for a second click | +| `NowCards` | `ui/now-cards` | Attention band of items needing action | +| `NotificationsBell` | `ui/notifications-bell` | Bell with count and a panel slot | + +### Artifacts + +| Component | Subpath | What it is | +| --- | --- | --- | +| `ArtifactBody` | `ui/artifact-body` | One artifact, drawn the way its kind implies | +| `ArtifactNotice` | `ui/artifact-notice` | "Nothing to draw here" message for artifact viewers | +| `BlockCard` | `ui/block-card` | Generative-UI block frame | +| `ResearchBody` | `ui/research-body` | Research brief and report | +| `CompareBody` | `ui/compare-body` | Side-by-side comparison | +| `EmbedBody` | `ui/embed-body` | Sandboxed third-party embed | +| `CsvTable` | `ui/csv-table` | Capped preview of CSV text | +| `QuoteCard` | `ui/quote-card` | A rotating quote | +| `ProfileCard` | `ui/profile-card` | Identity, status, actions and channels | + +### Charts + +| Component | Subpath | What it is | +| --- | --- | --- | +| `ChartFrame` | `ui/chart-frame` | Caption, legend, plot, and the same data as a table | +| `TimeSeriesChart` | `ui/time-series-chart` | Values over time | +| `BarChart` | `ui/bar-chart` | Vertical bars | +| `CategoryBars` | `ui/category-bars` | Dense horizontal category ranking | +| `Sparkline` | `ui/sparkline` | Inline trend line | +| `TokenMosaic` | `ui/token-mosaic` | Shares of a whole as one stacked strip | +| `StatGrid` | `ui/stat-grid` | Grid of headline numbers | +| `AnimatedNumber` | `ui/animated-number` | Number that counts to its new value | + +### Layout + +| Component | Subpath | What it is | +| --- | --- | --- | +| `PageShell` | `ui/page-shell` | Page margins and scroll ownership | +| `PagePanel` | `ui/page-panel` | Bordered page-content frame | +| `TopBar` | `ui/top-bar` | Title, breadcrumbs and actions row | +| `Sidebar` | `ui/sidebar` | Collapsible navigation sidebar | +| `SidebarPanel` | `ui/sidebar-panel` | Sidebar with pins, body and footer | +| `SidebarItemRow` | `ui/sidebar-item-row` | One sidebar row | +| `ListDetail` | `ui/list-detail` | Index on the left, open item on the right | +| `InspectorShell` | `ui/inspector-shell` | Side inspector rail | +| `Section` | `ui/section` | Titled block of content | +| `SettingsPanel` | `ui/settings-panel` | Settings frame with optional save | +| `LibraryPageHeader` | `ui/library-page-header` | Title, count and controls for a library page | +| `Card` | `ui/card` | Bordered content card | +| `EmptyState` | `ui/empty-state` | Title, description, icon and action | +| `RichEmptyState` | `ui/rich-empty-state` | Empty state with suggested next-step actions | +| `BootScreen` | `ui/boot-screen` | Screen shown before the app loads | +| `DitherCanvas` | `ui/dither-canvas` | Animated dithered background | +| `CorbitsMark` | `ui/corbits-mark` | Corbits logo | +| `AuthLayout` | `blocks/login/auth-layout` | Sign-in page layout | +| `LoginForm` | `blocks/login/login-form` | Sign-in and sign-up form, with optional SSO | + +### Controls + +| Component | Subpath | What it is | +| --- | --- | --- | +| `Button` | `ui/button` | Button with variants and sizes | +| `Input` | `ui/input` | Text input | +| `Textarea` | `ui/textarea` | Multi-line input | +| `Select` | `ui/select` | Native select | +| `Checkbox` | `ui/checkbox` | Checkbox | +| `SelectionCheckbox` | `ui/selection-checkbox` | Row-selection checkbox | +| `Switch` | `ui/switch` | On/off toggle | +| `FileInput` | `ui/file-input` | File picker | +| `Tabs` | `ui/tabs` | Tab strip | +| `ViewToggle` | `ui/view-toggle` | Grid or rows segmented control | +| `FilterBar` | `ui/filter-bar` | Row of filters with an active-filter summary | +| `FilterChip` | `ui/filter-chip` | One toggleable filter | +| `KindCardGrid` | `ui/kind-card-grid` | Selectable card grid | +| `BulkActionBar` | `ui/bulk-action-bar` | Actions for a multi-row selection | +| `Table` | `ui/table` | Table primitives | +| `SortableTable` | `ui/sortable-table` | Table with sortable columns | +| `Badge` | `ui/badge` | Status label | +| `StatusDot` | `ui/status-dot` | Colored status dot | +| `Avatar` | `ui/avatar` | Initials or image avatar | +| `ProviderMark` | `ui/provider-mark` | Which service an action goes through | +| `Skeleton` | `ui/skeleton` | Loading placeholder | +| `Dialog` | `ui/dialog` | Modal dialog | +| `CommandPalette` | `ui/command-palette` | Global search overlay | +| `Menu` | `ui/menu` | Dropdown menu | +| `InfoTooltip` | `ui/tooltip` | Hover info tooltip | +| `Toaster` | `ui/toast` | Toast host; call `toast()` anywhere | +| `ThemeProvider` | `ui/theme-provider` | Persists light, dark or system mode and presets | +| `ThemeToggle` | `ui/theme-toggle` | Light, dark or system switch | + ## How it works Components never fetch — data arrives as props. The root entry is re-exports only and the package is side-effect free aside from the CSS files, so either import style tree-shakes to what you used. Tokens and keyframes live in `theme.css`; `styles.css` is the prebuilt sheet for hosts that do not run Tailwind. -See [PRODUCT.md](./PRODUCT.md) for why this library exists, [ARCHITECTURE.md](./ARCHITECTURE.md) for the no-fetch rule and the theme layer, and [IMPLEMENTATION.md](./IMPLEMENTATION.md) for toolchain and peers. +See [PRODUCT.md](https://github.com/corbitsdev/react-ui/blob/main/PRODUCT.md) for why this library exists, [ARCHITECTURE.md](https://github.com/corbitsdev/react-ui/blob/main/ARCHITECTURE.md) for the no-fetch rule and the theme layer, and [IMPLEMENTATION.md](https://github.com/corbitsdev/react-ui/blob/main/IMPLEMENTATION.md) for toolchain and peers. ## Development @@ -106,30 +268,8 @@ bun run test bun run stories # Ladle workbench ``` -A new component is not done until it has at least one story per meaningful state, checked in both themes. See [CONTRIBUTING.md](./CONTRIBUTING.md). - -## Thinking indicator - -The Corbits logo has three motion variants: `silk` (default), `strata`, and `echo`. - -```tsx -import { ThinkingIndicator, ThinkingMark } from "@corbits/react-ui"; - -export function Thinking() { - return ( - <> - - - - - ); -} -``` - -`ThinkingIndicator` supplies an accessible status label; `ThinkingMark` is decorative. -Both accept `variant`, `paused`, `className`, and `style`. Reduced-motion users see a -static highlight instead. +A new component is not done until it has at least one story per meaningful state, checked in both themes. See [CONTRIBUTING.md](https://github.com/corbitsdev/react-ui/blob/main/CONTRIBUTING.md). ## License -LGPL-2.1-only. See [LICENSE](./LICENSE). +LGPL-2.1-only. See [LICENSE](https://github.com/corbitsdev/react-ui/blob/main/LICENSE).