diff --git a/README.md b/README.md index 47ca533f..c57a03ca 100644 --- a/README.md +++ b/README.md @@ -1,67 +1,35 @@ # @corbits/react-ui -React components for agent and workflow surfaces — chat, runs, schedules, artifacts, -analytics, collections. 197 modules, importable one at a time. +React components for agent and workflow surfaces — chat, runs, schedules, artifacts, analytics, collections. Import one module at a time, or from the root barrel. -Licensed LGPL-2.1-only (see `LICENSE`). +## Runtime support -## Install - -Not published to npm yet. Requires Node.js 24 LTS or later. +Node >= 24 consumes built `dist/`. Peers: `react` and `react-dom` (18 or 19), `lucide-react`, `sonner`, `@radix-ui/react-dialog`, `@radix-ui/react-dropdown-menu`, `@radix-ui/react-slot`, `@radix-ui/react-tooltip`. `@tanstack/react-query` is an optional peer, needed only for `createTanstackDataPort()`. +## Quickstart ```bash -bun add github:corbitsdev/react-ui react react-dom lucide-react sonner @radix-ui/react-dialog @radix-ui/react-dropdown-menu @radix-ui/react-slot @radix-ui/react-tooltip +npm add @corbits/react-ui +pnpm add @corbits/react-ui +yarn add @corbits/react-ui +bun add @corbits/react-ui ``` -Until a registry publish, `npm install @corbits/react-ui` (and the pnpm/yarn/bun -registry equivalents) 404. Git is the install path. - -The `prepare` hook builds `dist/` on the way in, and under bun that requires -trusting the package's lifecycle scripts -(`trustedDependencies: ["@corbits/react-ui"]`). - -React 18 or 19. `@tanstack/react-query` is an **optional** peer, needed only if you use -`createTanstackDataPort()`; components take their data through a `DataPort` and work with -any data layer, or none. - -## Styling - -Import the prebuilt stylesheet once, at the root of your app. It needs no Tailwind and no -build configuration: +Import the prebuilt stylesheet once at the app root (no Tailwind build required): ```tsx import "@corbits/react-ui/styles.css"; ``` -**This sheet is not inert — it restyles your page.** It carries Tailwind's preflight and a -base layer, so importing it resets margins and list styles across your app, sets every -element's default border color, and sets the page background, text color and font. That is -what makes the components look right with no build configuration, and it is a global -change. Import it at the root of an app you are willing to hand over to it. - -If you already use Tailwind v4 — or you need the components styled without the reset — -import the theme instead and let your own build generate the utilities: - -```css -@import "tailwindcss"; -@import "@corbits/react-ui/theme.css"; -``` - -That one directive gives you the tokens, the keyframes and the base layer without a second -copy of preflight, and points Tailwind at the package's own class names. - -Dark mode is a `dark` class on an ancestor. The library reads it; it does not manage it. +That sheet includes Tailwind preflight and a base layer — it restyles the page. If you already use Tailwind v4, import `@corbits/react-ui/theme.css` instead and let your own build generate utilities. Dark mode is a `dark` class on an ancestor; the library reads it and does not manage it. ```tsx - -``` +import { Button } from "@corbits/react-ui/ui/button"; -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`. + +``` -## Usage +Every component is importable by subpath (`@corbits/react-ui/ui/button`) or from the root (`@corbits/react-ui`). One module is subpath-only: `@corbits/react-ui/lib/tanstack-data-port`, because it statically imports the optional `@tanstack/react-query` peer. ```tsx import "@corbits/react-ui/styles.css"; @@ -71,18 +39,25 @@ import { DataTable } from "@corbits/react-ui/ui/data-table"; import { DataPortProvider } from "@corbits/react-ui/lib/data-port"; import { createTanstackDataPort } from "@corbits/react-ui/lib/tanstack-data-port"; +type Run = { id: string; name: string; status: string }; + export function Runs() { return ( - + caption="Runs" + rowKey={(run) => run.id} request={{ key: ["runs"], pageSize: 50, - fetch: ({ signal, offset, pageSize }) => api.runs({ signal, offset, pageSize }), + fetch: async ({ signal, offset, pageSize }) => { + const items: readonly Run[] = await api.runs({ signal, offset, pageSize }); + return { items, nextOffset: null }; + }, }} columns={[ - { id: "name", header: "Run", cell: (run) => run.name }, - { id: "status", header: "Status", cell: (run) => run.status }, + { header: "Run", cell: (run) => run.name }, + { header: "Status", cell: (run) => run.status }, ]} /> @@ -91,55 +66,30 @@ export function Runs() { } ``` -Every component is importable by subpath (`@corbits/react-ui/ui/button`) or from the root -(`@corbits/react-ui`). Both resolve to the same module; the root entry is re-exports only -and the package is side-effect free, so either way you bundle just what you used. +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. -**One module is subpath-only: `@corbits/react-ui/lib/tanstack-data-port`.** It is fully -public, just deliberately absent from the root entry, because it statically imports the -optional `@tanstack/react-query` peer — re-exporting it from the root would make that peer -mandatory for everyone. Import the adapter by its subpath, as above. +## How it works -## Server components +Components take data through a `DataPort` (or none). 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. -**This package ships no `"use client"` directives.** In a React Server Components app — -Next.js App Router and similar — components that hold state or take event handlers must be -imported from a file you mark yourself: - -```tsx -"use client"; -export { Button } from "@corbits/react-ui/ui/button"; -export { CommandPalette } from "@corbits/react-ui/ui/command-palette"; -``` - -Use subpaths rather than the root entry here: a client-boundary file is re-exported into -your own bundle, and naming the modules you actually mark keeps the boundary — and the -bundle — to exactly those. Components that render no state (tiles, badges, layout shells) -work directly in a server component with no boundary at all. +See [ARCHITECTURE.md](./ARCHITECTURE.md) for the DataPort seam and the theme layer. ## Development -```bash +```sh +git clone https://github.com/corbitsdev/react-ui.git +cd react-ui bun install -bun run build # generate → SWC → tsc → Tailwind → contrast gate +bun run build # generate → SWC → tsc → Tailwind → contrast gate bun run typecheck bun run lint bun run dep-guard +bun run test +bun run stories # Ladle workbench ``` -`ARCHITECTURE.md` covers the `DataPort` seam, the theme layer and the known limits. -`CONTRIBUTING.md` covers the gates and how to add a component. - -### Component 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). -```bash -bun run stories # Ladle dev server — live, hot-reloading, theme-aware -bun run stories:build # static build of the same canvas -``` +## License -[Ladle](https://ladle.dev) renders every story under `stories/` against the real -`src/theme.css`, with a light/dark toggle in its top bar that flips the actual `.dark` -class — not a canvas-only colour swap. **A story is the definition-of-done artifact for -every new component**: a change isn't finished until it has at least one story per -meaningful state, checked in both themes. See `CONTRIBUTING.md#the-component-workbench` -for what a story is expected to cover. +LGPL-2.1-only. See [LICENSE](./LICENSE).