diff --git a/.changeset/README.md b/.changeset/README.md index 6fb1b2a3..a5ae1360 100644 --- a/.changeset/README.md +++ b/.changeset/README.md @@ -1,7 +1,7 @@ # Changesets This folder is managed by [changesets](https://github.com/changesets/changesets). Each -pull request that changes a published package (`@intentface/chat`) should add a changeset: +pull request that changes a published package (`@intentface/ui`) should add a changeset: ```bash bunx changeset @@ -24,7 +24,7 @@ merging that PR publishes to npm. ```md --- -"@intentface/chat": minor +"@intentface/ui": minor --- - [Composer] Fix an Escape in one composer stopping generation in another. @@ -37,5 +37,5 @@ If a package change intentionally needs no release, add an empty changeset inste bunx changeset --empty ``` -The app (`intentface-chat`) is private, so changesets skips it — `@intentface/chat` is the +The app (`intentface-ui`) is private, so changesets skips it — `@intentface/ui` is the only published package. diff --git a/.changeset/rename-to-ui.md b/.changeset/rename-to-ui.md new file mode 100644 index 00000000..371c6ded --- /dev/null +++ b/.changeset/rename-to-ui.md @@ -0,0 +1,5 @@ +--- +"@intentface/ui": minor +--- + +- [Breaking] Renamed from `@intentface/chat`. Swap the dependency for `@intentface/ui` and replace `@intentface/chat/` with `@intentface/ui/` in imports; the rename changes nothing else. diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 5d967f5e..da4f15ea 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -57,10 +57,10 @@ jobs: - name: Package tests run: bun test - working-directory: packages/chat + working-directory: packages/ui - name: Package build (publint gate) - working-directory: packages/chat + working-directory: packages/ui run: | bun run build bunx --no-install publint diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 4a377080..dcb05823 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -59,8 +59,8 @@ jobs: id: check if: steps.changesets.outputs.hasChangesets == 'false' run: | - name=$(node -p "require('./packages/chat/package.json').name") - version=$(node -p "require('./packages/chat/package.json').version") + name=$(node -p "require('./packages/ui/package.json').name") + version=$(node -p "require('./packages/ui/package.json').version") # Exact version, not the latest dist-tag, and a registry error must not # read as "unpublished" — that would ask for an approval on every run. if output=$(npm view "$name@$version" version 2>&1); then @@ -99,7 +99,7 @@ jobs: - name: Verify release candidate run: bun run verify:release - working-directory: packages/chat + working-directory: packages/ui publish: needs: [version, verify-release] diff --git a/AGENTS.md b/AGENTS.md index 05337d18..33b2f330 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -59,7 +59,7 @@ Rules for compound components: - **Accept `className`** on every sub-component for style overrides - **Convenience wrappers are fine** — a higher-level component can compose the primitives with default behavior (e.g. `Composer.Attachments` composes `Attachments`, `Attachments.Item`, `Attachments.Remove`) -#### Package layer — `packages/chat/` +#### Package layer — `packages/ui/` Published primitives use **namespace exports**, not `Object.assign`, and the root is explicit: ``, never ``. Three modules per primitive: @@ -98,15 +98,15 @@ The chat API follows Vercel AI SDK conventions 2. Avoid `useEffect` for syncing/deriving state. Use it only for true side effects (subscriptions, DOM integrations). 3. Use standard size naming: `xs`, `sm`, `md`, `lg`, `xl`. 4. Organize CVA base classes with arrays/comments when classes are long. -5. Every component must use the compound component pattern — via `Object.assign` in `components/ai/` and `components/ui/`, via namespace exports in `packages/chat/` (see Component Architecture above). +5. Every component must use the compound component pattern — via `Object.assign` in `components/ai/` and `components/ui/`, via namespace exports in `packages/ui/` (see Component Architecture above). 6. Use `cn()` from `lib/utils.ts` for className merging. 7. Follow Biome rules and formatting. -8. Use data attributes for styling and state selectors: app components (`components/ai`, `components/ui`) stamp `data-slot` / `data-role`; package primitives (`packages/chat`) emit bespoke part attributes instead (`data-composer-editor`, `data-command-badge`) — `data-slot` belongs to the consumer layer. +8. Use data attributes for styling and state selectors: app components (`components/ai`, `components/ui`) stamp `data-slot` / `data-role`; package primitives (`packages/ui`) emit bespoke part attributes instead (`data-composer-editor`, `data-command-badge`) — `data-slot` belongs to the consumer layer. 9. Leverage Motion for entrance/exit animations. -10. Rich text editing goes through `Composer` from `@intentface/chat/composer` — no editor framework; don't add one. +10. Rich text editing goes through `Composer` from `@intentface/ui/composer` — no editor framework; don't add one. 11. Follow AI SDK patterns (`useChat()`, `streamText()`, `toUIMessageStreamResponse()`). 12. No monolithic components — always decompose into composable sub-components. Consumers compose the pieces; components never hardcode their own layout. -13. Do not use index/barrel files (`index.ts` that re-exports from other files). Import directly from the specific module instead. **Exception:** each `packages/chat/src//` has exactly two barrels — `index.parts.ts` and `index.ts` — which are required for server-component reach and must stay directive-free. +13. Do not use index/barrel files (`index.ts` that re-exports from other files). Import directly from the specific module instead. **Exception:** each `packages/ui/src//` has exactly two barrels — `index.parts.ts` and `index.ts` — which are required for server-component reach and must stay directive-free. ## Environment Variables diff --git a/CHAT_ARCHITECTURE.md b/CHAT_ARCHITECTURE.md index 4bd3c7bf..c5c04105 100644 --- a/CHAT_ARCHITECTURE.md +++ b/CHAT_ARCHITECTURE.md @@ -6,7 +6,7 @@ A reference for the chat surface in this project — the UI primitives (`Compose - **Vercel AI SDK** (`ai@^6`) and **`@ai-sdk/react@^3`** — `Chat` class, `useChat()`, `DefaultChatTransport`, `UIMessage` parts as the wire format - **`@ai-sdk/openai@^3`** — the only model provider; chat models are selectable demo ids (`gpt-5.5` / `gpt-5.4` / `gpt-5.4-mini` / `gpt-5.4-nano`, default `gpt-5.4-mini`) -- **No editor framework** — the composer's contenteditable engine (inline chips, prefix-triggered command lists) is hand-rolled in `packages/chat/src/composer/` +- **No editor framework** — the composer's contenteditable engine (inline chips, prefix-triggered command lists) is hand-rolled in `packages/ui/src/composer/` - **Zustand** (`^5`, with `persist`) — chat-list metadata, model selection, and settings - **Streamdown** (`^2`) — streaming-safe markdown renderer used by `Message.Markdown` - **Base UI** (`@base-ui/react`) + **motion** — popovers, collapsibles, transitions @@ -248,7 +248,7 @@ Pass a `commands` map to the root: ### Editor engine -The composer runs on a purpose-built contenteditable engine (`packages/chat/src/composer/`), not an editor framework: +The composer runs on a purpose-built contenteditable engine (`packages/ui/src/composer/`), not an editor framework: - **Document model** (`segments.ts`) — a flat list of text and chip segments. Every mutation reduces to one contiguous range replacement (`TextChange`), which makes position mapping a single arithmetic rule. - **DOM reconciliation** (`editor-dom.ts`) — renders the canonical child list, reusing chip spans by id so a moved chip keeps its React portal instead of remounting. @@ -258,7 +258,7 @@ Chips are atomic inline `contenteditable=false` spans carrying `prefix` / `label #### Chip wire format -A chip segment serializes to a self-describing markdown-link token (`packages/chat/src/chip-markdown.ts`): +A chip segment serializes to a self-describing markdown-link token (`packages/ui/src/chip-markdown.ts`): ``` [Label](chip:prefix:value?variant=…&icon=…) diff --git a/README.md b/README.md index 323afdb3..a036734d 100644 --- a/README.md +++ b/README.md @@ -1,19 +1,19 @@ -# intentface-chat +# intentface-ui -Monorepo for **[@intentface/chat](https://www.npmjs.com/package/@intentface/chat)** — headless chat UI -primitives for React — and the documentation site and playground at -[ui.intentface.com](https://ui.intentface.com). +Monorepo for **[@intentface/ui](https://www.npmjs.com/package/@intentface/ui)** — headless React UI +primitives for AI chat interfaces and the app shells around them — and the documentation site and +playground at [ui.intentface.com](https://ui.intentface.com). The package ships behavior, state, and wire formats with no styling of its own: a contenteditable composer with commands and chips, a thread with scroll auto-follow, message part segmentation, tool-call timelines, and the app-shell parts around them — a collapsible sidebar, a nav tree, a closable tab -collection. This is the Base UI model applied to chat — the package owns behavior, you own every class. +collection. The package owns behavior; you own every class. ## Layout | Path | What it is | | --- | --- | -| `packages/chat` | The published package. Namespace exports per primitive, built per-module by `tsc`. | +| `packages/ui` | The published package. Namespace exports per primitive, built per-module by `tsc`. | | `content/docs` | Documentation pages (MDX, via fumadocs). | | `components/docs` | Docs-site chrome: previews, code blocks, tables. | | `components/ai`, `components/ui` | The playground's own styled layer. **App-private** — it uses design tokens, Motion, and local icons, and is not published or supported for copying. | @@ -37,7 +37,7 @@ No environment variables are needed. The playground chat runs on your own OpenAI Package tests and build: ```bash -cd packages/chat +cd packages/ui bun test bun run build ``` @@ -45,7 +45,7 @@ bun run build ## Contributing Conventions, architecture, and patterns live in [AGENTS.md](./AGENTS.md) — read it before opening a PR. -Changesets gate releases: run `bunx changeset` for any user-facing change to `packages/chat`. +Changesets gate releases: run `bunx changeset` for any user-facing change to `packages/ui`. ## License diff --git a/app/api/chat/route.ts b/app/api/chat/route.ts index 64c49898..d1bb80a4 100644 --- a/app/api/chat/route.ts +++ b/app/api/chat/route.ts @@ -19,7 +19,7 @@ import { readSourceFile } from "@/tools/read-source-file"; import { renderUi } from "@/tools/render-ui"; import { createWebSearch } from "@/tools/web-search"; -const SYSTEM_PROMPT = `You are the assistant in the Intentface Chat playground — a demo built with @intentface/chat, headless React chat primitives. You are knowledgeable, concise, and friendly. +const SYSTEM_PROMPT = `You are the assistant in the playground — a demo built with @intentface/ui, headless React UI primitives. You are knowledgeable, concise, and friendly. ## Response Guidelines - Be concise and direct. Avoid unnecessary filler or preamble. @@ -30,10 +30,10 @@ const SYSTEM_PROMPT = `You are the assistant in the Intentface Chat playground - Use the current date and time context when answering time-sensitive questions. ## Library Questions -When the user asks about @intentface/chat — its primitives (composer, thread, message, chip, steps, reasoning, attachments), installation, styling, state, or how this playground is built: +When the user asks about @intentface/ui — its primitives (composer, thread, message, chip, steps, reasoning, attachments), installation, styling, state, or how this playground is built: 1. Call listDocsPages to see the documentation index 2. Read the relevant pages with readDocsPage before answering -3. For implementation internals ("how does X work under the hood"), read the code with readSourceFile — each docs page's source field names its component under packages/chat/src +3. For implementation internals ("how does X work under the hood"), read the code with readSourceFile — each docs page's source field names its component under packages/ui/src - Answer strictly from the documentation and source — never invent props, exports, or APIs - Link to pages inline using their url from the tool output, e.g. [Composer](/primitives/composer) - If the documentation doesn't cover something, say so instead of guessing diff --git a/app/layout.tsx b/app/layout.tsx index 830ed162..b090c613 100644 --- a/app/layout.tsx +++ b/app/layout.tsx @@ -4,7 +4,7 @@ import localFont from "next/font/local"; import { Providers } from "@/components/providers"; import { SiteShell } from "@/components/site-shell"; import { source } from "@/lib/docs/source"; -import chatPackage from "@/packages/chat/package.json"; +import uiPackage from "@/packages/ui/package.json"; import "streamdown/styles.css"; import "./globals.css"; const inter = Inter({ @@ -30,9 +30,9 @@ export const metadata: Metadata = { // Absolute base for Open Graph and canonical URLs. Without it Next cannot // resolve them, so link previews fall back to relative paths. metadataBase: new URL("https://ui.intentface.com"), - title: "@intentface/chat", + title: "@intentface/ui", description: - "Headless chat UI primitives for React — unstyled compound components, hooks, and wire formats for building AI chat interfaces.", + "Headless UI primitives for React — unstyled compound components, hooks, and wire formats for AI chat interfaces and the app shells around them.", }; export default function RootLayout({ @@ -48,7 +48,7 @@ export default function RootLayout({ > {/* Read here on the server, so only the version reaches the client. */} - + {children} diff --git a/app/llms.txt/route.ts b/app/llms.txt/route.ts index 8738fc12..52fb96bc 100644 --- a/app/llms.txt/route.ts +++ b/app/llms.txt/route.ts @@ -7,8 +7,8 @@ const SITE = "https://ui.intentface.com"; // that save a round trip: how to fetch a page, and which Tailwind version the // demos assume. const SUMMARY = [ - "This is the documentation for the `@intentface/chat` package.", - "It provides headless, unstyled React primitives for building AI chat interfaces — a rich-text composer, thread scroll ownership, message segmentation, and streaming disclosure. Styling is entirely the consumer's.", + "This is the documentation for the `@intentface/ui` package.", + "It provides headless, unstyled React primitives for AI chat interfaces and the app shells around them — a rich-text composer, thread scroll ownership, message segmentation, streaming disclosure, and a sidebar, nav tree and tabs. Styling is entirely the consumer's.", "Every page below is markdown; append `.md` to any docs URL to fetch the same content. Demo source is inlined into those pages.", "The demos are written for Tailwind CSS v4. If `package.json` uses Tailwind CSS v3, convert unsupported utilities to v3-compatible equivalents.", ].join("\n"); @@ -65,7 +65,7 @@ export const GET = () => { const { loose, groups } = sectionsOf(source.pageTree.children as TreeNode[]); const body = [ - "# @intentface/chat", + "# @intentface/ui", "", SUMMARY, "", diff --git a/biome.json b/biome.json index 9c250c3e..93e46649 100644 --- a/biome.json +++ b/biome.json @@ -15,7 +15,7 @@ "!build", "!.source", "!packages/intentface/registry/registry.json", - "!packages/chat/src/internal/render" + "!packages/ui/src/internal/render" ] }, "formatter": { diff --git a/bun.lock b/bun.lock index 24152c26..96569a6c 100644 --- a/bun.lock +++ b/bun.lock @@ -9,7 +9,7 @@ "@ai-sdk/provider": "^3.0.13", "@ai-sdk/react": "^3.0.220", "@base-ui/react": "^1.6.0", - "@intentface/chat": "workspace:*", + "@intentface/ui": "workspace:*", "@keyline-icons/react": "^1.4.0", "@tabler/icons-react": "^3.46.0", "ai": "^6.0.218", @@ -44,9 +44,9 @@ "typescript": "^5.9.3", }, }, - "packages/chat": { - "name": "@intentface/chat", - "version": "0.5.3", + "packages/ui": { + "name": "@intentface/ui", + "version": "0.6.0", "dependencies": { "@floating-ui/dom": "^1.7.6", }, @@ -268,7 +268,7 @@ "@inquirer/external-editor": ["@inquirer/external-editor@1.0.3", "", { "dependencies": { "chardet": "^2.1.1", "iconv-lite": "^0.7.0" }, "peerDependencies": { "@types/node": ">=18" }, "optionalPeers": ["@types/node"] }, "sha512-RWbSrDiYmO4LbejWY7ttpxczuwQyZLBUyygsA9Nsv95hpzUWwnNTVQmAq3xuh7vNwCp07UTmE5i11XAEExx4RA=="], - "@intentface/chat": ["@intentface/chat@workspace:packages/chat"], + "@intentface/ui": ["@intentface/ui@workspace:packages/ui"], "@jridgewell/gen-mapping": ["@jridgewell/gen-mapping@0.3.13", "", { "dependencies": { "@jridgewell/sourcemap-codec": "^1.5.0", "@jridgewell/trace-mapping": "^0.3.24" } }, "sha512-2kkt/7niJ6MgEPxF0bYdQ6etZaA+fQvDcLKckhy1yIQOzaoKjBBjSj63/aLVjYE3qhRt5dvM+uUyfCg6UKCBbA=="], diff --git a/components/ai/ask-user.tsx b/components/ai/ask-user.tsx index 2bfb3d14..e7bec5c2 100644 --- a/components/ai/ask-user.tsx +++ b/components/ai/ask-user.tsx @@ -5,7 +5,7 @@ import { AskUser as AskUserPrimitive, useAskUserOption, useAskUserOptions, -} from "@intentface/chat/ask-user"; +} from "@intentface/ui/ask-user"; import { Check, ChevronDown, diff --git a/components/ai/attachments.tsx b/components/ai/attachments.tsx index fc250ab1..e1f4a052 100644 --- a/components/ai/attachments.tsx +++ b/components/ai/attachments.tsx @@ -1,6 +1,6 @@ "use client"; -import type { AttachmentErrorCode, AttachmentItem } from "@intentface/chat/attachments"; +import type { AttachmentErrorCode, AttachmentItem } from "@intentface/ui/attachments"; import { File, Paperclip, X } from "@keyline-icons/react"; import { AnimatePresence } from "motion/react"; import * as m from "motion/react-m"; @@ -22,7 +22,7 @@ export { revokeAllAttachmentUrls, revokeAttachmentUrl, toAttachmentItem, -} from "@intentface/chat/attachments"; +} from "@intentface/ui/attachments"; export { ATTACHMENT_ACCEPT, ATTACHMENT_MAX_FILE_SIZE, diff --git a/components/ai/chip.tsx b/components/ai/chip.tsx index d2cf53e6..10a33889 100644 --- a/components/ai/chip.tsx +++ b/components/ai/chip.tsx @@ -1,6 +1,6 @@ "use client"; -import { Chip as ChipPrimitive } from "@intentface/chat/chip"; +import { Chip as ChipPrimitive } from "@intentface/ui/chip"; import { cva, type VariantProps } from "class-variance-authority"; import type { ComponentProps } from "react"; import HoverCard from "@/components/ui/hover-card"; diff --git a/components/ai/composer.tsx b/components/ai/composer.tsx index eb248350..c99d0360 100644 --- a/components/ai/composer.tsx +++ b/components/ai/composer.tsx @@ -1,7 +1,7 @@ "use client"; import { ArrowUp, Stop } from "@keyline-icons/react"; -// Styled composer — thin wrappers over @intentface/chat/composer. Behavior +// Styled composer — thin wrappers over @intentface/ui/composer. Behavior // (editor, store, machines, command plumbing) lives in the package; this file // carries the Tailwind classes, icons, and motion, and re-exports the public // surface so consumers keep importing from "@/components/ai/composer". @@ -15,7 +15,7 @@ import { useComposerController, useComposerStore, useComposerSubmit, -} from "@intentface/chat/composer"; +} from "@intentface/ui/composer"; import { AnimatePresence } from "motion/react"; import * as m from "motion/react-m"; import { Children, type ComponentProps, type ReactNode, useMemo, useRef } from "react"; @@ -60,7 +60,7 @@ export type { ComposerSubmitOn, PrefixOnSelectContext, TriggerRule, -} from "@intentface/chat/composer"; +} from "@intentface/ui/composer"; // --------------------------------------------------------------------------- // Root diff --git a/components/ai/generated-ui.tsx b/components/ai/generated-ui.tsx index 759fcd65..fa796d94 100644 --- a/components/ai/generated-ui.tsx +++ b/components/ai/generated-ui.tsx @@ -1,6 +1,6 @@ "use client"; -import { type TreeNode, useTree } from "@intentface/chat/generative"; +import { type TreeNode, useTree } from "@intentface/ui/generative"; import * as m from "motion/react-m"; import type { ReactNode } from "react"; import { catalog } from "@/lib/ai/generative-catalog"; diff --git a/components/ai/message.tsx b/components/ai/message.tsx index 2953a3ae..89aa0bf3 100644 --- a/components/ai/message.tsx +++ b/components/ai/message.tsx @@ -1,12 +1,12 @@ "use client"; import { Popover as PopoverPrimitive } from "@base-ui/react/popover"; -import type { ChipData } from "@intentface/chat/chip-markdown"; +import type { ChipData } from "@intentface/ui/chip-markdown"; import { Message as MessagePrimitive, useMessageSelection, useMessageSelectionScope, -} from "@intentface/chat/message"; +} from "@intentface/ui/message"; import { Check, Copy, File, MessageSquare, Paperclip, Stop } from "@keyline-icons/react"; import * as m from "motion/react-m"; import Image from "next/image"; diff --git a/components/ai/reasoning.tsx b/components/ai/reasoning.tsx index c4ce9951..ee2f9702 100644 --- a/components/ai/reasoning.tsx +++ b/components/ai/reasoning.tsx @@ -1,6 +1,6 @@ "use client"; -import { Reasoning as ReasoningPrimitive, useReasoning } from "@intentface/chat/reasoning"; +import { Reasoning as ReasoningPrimitive, useReasoning } from "@intentface/ui/reasoning"; import { Brain, ChevronDown } from "@keyline-icons/react"; import { AnimatePresence } from "motion/react"; import * as m from "motion/react-m"; diff --git a/components/ai/steps.tsx b/components/ai/steps.tsx index 923280eb..fb19e9fe 100644 --- a/components/ai/steps.tsx +++ b/components/ai/steps.tsx @@ -1,6 +1,6 @@ "use client"; -import { Steps as StepsPrimitive } from "@intentface/chat/steps"; +import { Steps as StepsPrimitive } from "@intentface/ui/steps"; import type { ComponentProps } from "react"; import { cn } from "@/lib/utils"; diff --git a/components/ai/thread.tsx b/components/ai/thread.tsx index a643af3a..e9da5443 100644 --- a/components/ai/thread.tsx +++ b/components/ai/thread.tsx @@ -6,7 +6,7 @@ import { type ThreadVisibilityState, useThread, useThreadVisibility, -} from "@intentface/chat/thread"; +} from "@intentface/ui/thread"; import { ArrowDown } from "@keyline-icons/react"; import { AnimatePresence } from "motion/react"; import * as m from "motion/react-m"; diff --git a/components/chat.tsx b/components/chat.tsx index 2257d7d5..e0f719cf 100644 --- a/components/chat.tsx +++ b/components/chat.tsx @@ -7,8 +7,8 @@ import { getTextInfo, groupTurns, type MessageSegment, -} from "@intentface/chat/message-utils"; -import type { ToolPart } from "@intentface/chat/types"; +} from "@intentface/ui/message-utils"; +import type { ToolPart } from "@intentface/ui/types"; import { Brain, Check, @@ -1063,7 +1063,7 @@ const ChatPlaceholder = () => { variants={variants} className="font-semibold text-[20px] text-ink-primary leading-7 tracking-[-0.01em]" > - Intentface Chat + Playground Start a conversation diff --git a/components/docs/page-actions.tsx b/components/docs/page-actions.tsx index a43b4433..214159e1 100644 --- a/components/docs/page-actions.tsx +++ b/components/docs/page-actions.tsx @@ -7,11 +7,11 @@ import Button from "@/components/ui/button"; import { IconButton } from "@/components/ui/icon-button"; import { useCopy } from "@/hooks/use-copy"; -const REPO = "https://github.com/Intentface/intentface-chat"; +const REPO = "https://github.com/Intentface/intentface-ui"; type PageActionsProps = { slug: string[]; - // Component path under packages/chat/src (frontmatter `source`); omitted on + // Component path under packages/ui/src (frontmatter `source`); omitted on // pages that document no single component. source?: string; }; @@ -41,7 +41,7 @@ export const PageActions = ({ slug, source }: PageActionsProps) => { aria-label={source ? "Primitive source on GitHub" : "GitHub repository"} render={ diff --git a/components/playground-settings.tsx b/components/playground-settings.tsx index 55ffcb85..436f6830 100644 --- a/components/playground-settings.tsx +++ b/components/playground-settings.tsx @@ -496,7 +496,7 @@ const KeyTab = () => { for the length of that request — never written to disk or logged. It is stored in your browser in a cookie that scripts cannot read.{" "} - intentface/chat + intentface/ui
@@ -171,12 +171,12 @@ export const SiteShell = ({
} /> } /> diff --git a/components/ui/sidebar.tsx b/components/ui/sidebar.tsx index 0bc62a8c..9d0bec12 100644 --- a/components/ui/sidebar.tsx +++ b/components/ui/sidebar.tsx @@ -1,7 +1,7 @@ "use client"; import { useRender } from "@base-ui/react/use-render"; -import { Shell, useShell } from "@intentface/chat/shell"; +import { Shell, useShell } from "@intentface/ui/shell"; import { PanelLeft } from "@keyline-icons/react"; import { cva, type VariantProps } from "class-variance-authority"; import { AnimatePresence, useReducedMotion } from "motion/react"; @@ -27,7 +27,7 @@ import { IconButton } from "./icon-button"; /* * Open/collapsed state and the whole hotspot choreography live in `Shell` - * from @intentface/chat/shell — this file is the styled layer over it. What + * from @intentface/ui/shell — this file is the styled layer over it. What * stays here is what the package deliberately has no opinion about: every * class, the off-canvas/card geometry, the mobile drawer, where the layout is * persisted, and the keyboard shortcut. diff --git a/content/docs/build-a-chat.mdx b/content/docs/build-a-chat.mdx index 3890beab..a41c40ec 100644 --- a/content/docs/build-a-chat.mdx +++ b/content/docs/build-a-chat.mdx @@ -67,7 +67,7 @@ Swap local state for `useChat`, which owns the message list and the request: "use client"; import { useChat } from "@ai-sdk/react"; -import { Composer, type ComposerSubmitData } from "@intentface/chat/composer"; +import { Composer, type ComposerSubmitData } from "@intentface/ui/composer"; export function Chat() { const { messages, sendMessage, status, stop } = useChat(); diff --git a/content/docs/build-a-chat/demos/composer.tsx b/content/docs/build-a-chat/demos/composer.tsx index a731f741..d2e885f2 100644 --- a/content/docs/build-a-chat/demos/composer.tsx +++ b/content/docs/build-a-chat/demos/composer.tsx @@ -1,8 +1,8 @@ "use client"; -import { Composer, type ComposerSubmitData } from "@intentface/chat/composer"; -import { Message } from "@intentface/chat/message"; -import { Thread, useThread } from "@intentface/chat/thread"; +import { Composer, type ComposerSubmitData } from "@intentface/ui/composer"; +import { Message } from "@intentface/ui/message"; +import { Thread, useThread } from "@intentface/ui/thread"; import { ArrowDown, ArrowUp } from "@keyline-icons/react"; import { useState } from "react"; diff --git a/content/docs/build-a-chat/demos/messages.tsx b/content/docs/build-a-chat/demos/messages.tsx index 33bafcaf..37d6f2a0 100644 --- a/content/docs/build-a-chat/demos/messages.tsx +++ b/content/docs/build-a-chat/demos/messages.tsx @@ -1,7 +1,7 @@ "use client"; -import { Message } from "@intentface/chat/message"; -import { Thread } from "@intentface/chat/thread"; +import { Message } from "@intentface/ui/message"; +import { Thread } from "@intentface/ui/thread"; const MESSAGES = [ { id: "1", role: "user", text: "What does Message actually render?" }, diff --git a/content/docs/build-a-chat/demos/thread.tsx b/content/docs/build-a-chat/demos/thread.tsx index fcc8714b..24d7e681 100644 --- a/content/docs/build-a-chat/demos/thread.tsx +++ b/content/docs/build-a-chat/demos/thread.tsx @@ -1,6 +1,6 @@ "use client"; -import { Thread } from "@intentface/chat/thread"; +import { Thread } from "@intentface/ui/thread"; const LINES = [ "Thread owns the scroll container and nothing else.", diff --git a/content/docs/changelog.mdx b/content/docs/changelog.mdx index 411941f6..37a2d785 100644 --- a/content/docs/changelog.mdx +++ b/content/docs/changelog.mdx @@ -1,15 +1,15 @@ --- title: Changelog -description: Every release of @intentface/chat, newest first. +description: Every release of @intentface/ui, newest first. --- -{/* Changesets writes packages/chat/CHANGELOG.md on every release; it is included +{/* Changesets writes packages/ui/CHANGELOG.md on every release; it is included here at build time, so this page is always the released notes. Its own - `# @intentface/chat` title is hidden, and the first version keeps no rule. + `# @intentface/ui` title is hidden, and the first version keeps no rule. A line's leading [Tag]s become badges (lib/docs/remark-changelog-tags.ts). */}
-../../packages/chat/CHANGELOG.md +../../packages/ui/CHANGELOG.md
diff --git a/content/docs/generative/catalog.mdx b/content/docs/generative/catalog.mdx index 788a3b34..40a467c4 100644 --- a/content/docs/generative/catalog.mdx +++ b/content/docs/generative/catalog.mdx @@ -36,7 +36,7 @@ defineCatalog({ A real catalog names each component, describes it for the model, and takes its props schema from any validator that converts to JSON Schema. ```ts -import { defineCatalog, markdown } from "@intentface/chat/generative"; +import { defineCatalog, markdown } from "@intentface/ui/generative"; import { z } from "zod"; export const catalog = defineCatalog({ @@ -64,7 +64,7 @@ export const catalog = defineCatalog({ The tool runs on your server, so this one is code only. `tree.schema` builds its input schema from the catalog, and types `input` from it. In `execute`, `tree.validate` checks the finished call, and `bindings.resolve` puts each bound prop's data in place. Following the AI SDK's convention, the result is what the chat draws: the finished tree, or the issues when the call is refused. `toModelOutput` turns that into one line for the model. Pass the same tools to `convertToModelMessages(messages, { tools })` when you rebuild the history; otherwise later turns send each whole result back to the model, bound rows included. ```ts -import { bindings, tree } from "@intentface/chat/generative"; +import { bindings, tree } from "@intentface/ui/generative"; import { tool } from "ai"; import { catalog } from "./catalog"; diff --git a/content/docs/generative/catalog/demos/as-markdown.tsx b/content/docs/generative/catalog/demos/as-markdown.tsx index b9da80da..73f67246 100644 --- a/content/docs/generative/catalog/demos/as-markdown.tsx +++ b/content/docs/generative/catalog/demos/as-markdown.tsx @@ -1,6 +1,6 @@ "use client"; -import { markdown, tree, useTree } from "@intentface/chat/generative"; +import { markdown, tree, useTree } from "@intentface/ui/generative"; import { useState } from "react"; import { catalog } from "./catalog"; import { DrawNode } from "./draw"; diff --git a/content/docs/generative/catalog/demos/basic.tsx b/content/docs/generative/catalog/demos/basic.tsx index 9d898998..78b2ec96 100644 --- a/content/docs/generative/catalog/demos/basic.tsx +++ b/content/docs/generative/catalog/demos/basic.tsx @@ -1,6 +1,6 @@ "use client"; -import { useTree } from "@intentface/chat/generative"; +import { useTree } from "@intentface/ui/generative"; import { parsePartialJson } from "ai"; import { useEffect, useRef, useState } from "react"; import { catalog } from "./catalog"; diff --git a/content/docs/generative/catalog/demos/binding.tsx b/content/docs/generative/catalog/demos/binding.tsx index f21d4913..22f4b083 100644 --- a/content/docs/generative/catalog/demos/binding.tsx +++ b/content/docs/generative/catalog/demos/binding.tsx @@ -1,6 +1,6 @@ "use client"; -import { type FoundBinding, useTree } from "@intentface/chat/generative"; +import { type FoundBinding, useTree } from "@intentface/ui/generative"; import { useEffect, useRef, useState } from "react"; import { catalog } from "./catalog"; import { DrawNode } from "./draw"; diff --git a/content/docs/generative/catalog/demos/catalog.ts b/content/docs/generative/catalog/demos/catalog.ts index b8ff8e23..90320327 100644 --- a/content/docs/generative/catalog/demos/catalog.ts +++ b/content/docs/generative/catalog/demos/catalog.ts @@ -1,4 +1,4 @@ -import { defineCatalog, markdown } from "@intentface/chat/generative"; +import { defineCatalog, markdown } from "@intentface/ui/generative"; import { z } from "zod"; /* diff --git a/content/docs/generative/catalog/demos/draw.tsx b/content/docs/generative/catalog/demos/draw.tsx index 9fcf9201..abe5d939 100644 --- a/content/docs/generative/catalog/demos/draw.tsx +++ b/content/docs/generative/catalog/demos/draw.tsx @@ -1,6 +1,6 @@ "use client"; -import type { TreeNode } from "@intentface/chat/generative"; +import type { TreeNode } from "@intentface/ui/generative"; import { type ReactNode, useCallback, useState } from "react"; import type { catalog } from "./catalog"; diff --git a/content/docs/generative/catalog/demos/refusal.tsx b/content/docs/generative/catalog/demos/refusal.tsx index 8a3c8564..3390a3dd 100644 --- a/content/docs/generative/catalog/demos/refusal.tsx +++ b/content/docs/generative/catalog/demos/refusal.tsx @@ -1,6 +1,6 @@ "use client"; -import { tree, useTree } from "@intentface/chat/generative"; +import { tree, useTree } from "@intentface/ui/generative"; import { useEffect, useRef, useState } from "react"; import { catalog } from "./catalog"; import { DrawNode } from "./draw"; diff --git a/content/docs/generative/catalog/demos/single.tsx b/content/docs/generative/catalog/demos/single.tsx index 67df8bae..da9c010a 100644 --- a/content/docs/generative/catalog/demos/single.tsx +++ b/content/docs/generative/catalog/demos/single.tsx @@ -1,6 +1,6 @@ "use client"; -import { useTree } from "@intentface/chat/generative"; +import { useTree } from "@intentface/ui/generative"; import { catalog } from "./catalog"; import { DrawNode } from "./draw"; diff --git a/content/docs/index.mdx b/content/docs/index.mdx index a5075d0c..4a141482 100644 --- a/content/docs/index.mdx +++ b/content/docs/index.mdx @@ -1,12 +1,13 @@ --- title: Introduction -description: An unstyled React primitive library for building AI chat interfaces. +description: An unstyled React primitive library for AI chat interfaces and the app shells around them. --- -`@intentface/chat` is an unstyled React library for building chat interfaces. It -provides the behavior that chat UIs need and is hard to write — a rich-text -composer, scroll ownership, message segmentation, streaming disclosure — and -renders no styles of its own. +`@intentface/ui` is an unstyled React library for AI chat interfaces and the app +shells around them. It provides the behavior that is hard to write and renders +no styles of its own. For the chat, that means a rich-text composer, scroll +ownership, message segmentation and streaming disclosure. For the shell around +it, that means a resizable sidebar, a nav tree and closable tabs. React and React DOM are the only peer dependencies. There is no editor framework underneath, no animation library, and no opinion about transport: the package diff --git a/content/docs/primitives/attachments.mdx b/content/docs/primitives/attachments.mdx index 34f5f15e..8ae92ed6 100644 --- a/content/docs/primitives/attachments.mdx +++ b/content/docs/primitives/attachments.mdx @@ -132,7 +132,7 @@ file input; wire this to your own. Renders a `