diff --git a/LICENSE b/LICENSE new file mode 100644 index 0000000..9ccdf06 --- /dev/null +++ b/LICENSE @@ -0,0 +1,21 @@ +MIT License + +Copyright (c) 2026 Volodymyr Vreshch + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. diff --git a/README.md b/README.md index 3814913..fde85af 100644 --- a/README.md +++ b/README.md @@ -1,64 +1,178 @@ # @agentage/design-system -The Agentage design system — OKLCH design tokens + a React component library shared across the Agentage web dashboard, landing site, and showcase. +![Agentage Design System - OKLCH tokens + 60+ React components, ready to install](https://github.com/agentage/design-system/raw/master/docs/banner.svg) -Previously vendored as a package copy inside both the `web` and `landing` monorepos; this repo is the single source of truth (the copies had silently diverged on the same version number). +OKLCH design tokens and 60+ accessible React 19 components in one package. Install it, import +the theme, and you have a coherent dark/light UI kit - buttons through data tables, stat cards, +command palettes and docs layouts. -## Install +Browse every component live at **[ds.agentage.io](https://ds.agentage.io)**. + +## What is this? + +The design system behind the Agentage dashboard, admin console and public sites, published as a +plain npm package so anything can use it. + +It is deliberately unopinionated about your framework. It ships **standard ESM with one file per +component**, so tree-shaking works, and every interactive component already carries `'use client'`, +so it drops into a Next.js App Router server tree without wrappers or `dynamic()` tricks. Colors +are defined in [OKLCH](https://oklch.com), so the light and dark themes are perceptually matched +rather than hand-tuned, and contrast holds up under WCAG AA. + +## Get started + +### 1. Install ```bash npm install @agentage/design-system ``` -Peer dependencies: `react` / `react-dom` >= 19, and `tailwindcss` >= 4 (optional — only needed if you consume the token layer). +Peers: `react` and `react-dom` >= 19. `tailwindcss` >= 4 is an optional peer - the components +carry Tailwind utility classes, so you need it unless you ship your own compiled CSS. + +### 2. Load the theme + +```tsx +// app/layout.tsx (or your root entry) +import '@agentage/design-system/theme.css'; +``` + +### 3. Point Tailwind at the shipped bundle -## Usage +```css +/* globals.css - Tailwind v4, CSS-first config */ +@import 'tailwindcss'; +@import '@agentage/design-system/theme.css'; + +@source "../../node_modules/@agentage/design-system/dist/**/*.js"; +``` -Components (tree-shakeable ES module): +> Tailwind must scan the **shipped JS**, not the source, or every design-system class is +> tree-shaken out of your build. The glob has to resolve to wherever npm actually hoisted the +> package - in a workspace that is the repo-root `node_modules`, not the package-local one. This +> is the single most common cause of "the components render unstyled". + +### 4. Use it ```tsx -import { Button, Card, Alert } from '@agentage/design-system'; +import { Button, Card, CardHeader, CardTitle, StatCard } from '@agentage/design-system'; + +export const Panel = () => ( + + + Memories + + + + +); ``` -### React Server Components +Full walkthrough: [ds.agentage.io/install](https://ds.agentage.io/install). + +## What's in it + +62 documented component pages across eight areas, each with props generated from the source: + +| Area | What's there | +| ------------------------------------------------------------------- | ---------------------------------------------------------------------------------------------------------------------------- | +| [Foundations](https://ds.agentage.io/components/foundations) (6) | Button, Badge, Card, Avatar, loading states, Separator | +| [Data Display](https://ds.agentage.io/components/data-display) (10) | Table, DataTable, EntityList, StatCard, Pagination, EmptyState, StatusDot, CodeBlock, Progress, UsageMeter | +| [Cards](https://ds.agentage.io/components/cards) (7) | Gauge, donut, score, funnel, heatmap, multi-stat and ranked-list cards | +| [Forms](https://ds.agentage.io/components/forms) (8) | Input, Label, Checkbox, RadioGroup, Slider, Combobox, DatePicker, ToggleGroup | +| [Feedback](https://ds.agentage.io/components/feedback) (13) | Alert, Toast, Tooltip, Modal, AlertDialog, Sheet, DropdownMenu, ContextMenu, Popover, HoverCard, Command palette, DangerZone | +| [Layout](https://ds.agentage.io/components/layout) (5) | PageHeader, Section, Sidebar, Resizable panels, ScrollArea | +| [Navigation](https://ds.agentage.io/components/navigation) (7) | Breadcrumb, Tabs, Heading, Prose, Kbd, Collapsible, Accordion | +| [Site & Docs](https://ds.agentage.io/components/site-docs) (6) | Markdown, CopyButton, Chip, Footer, TopBar, DocSidebar | -Every interactive component ships `'use client'` as the first line of its emitted module, and the build -preserves one output file per source module — so the barrel above is safe to import from a React Server -Component: only the components you actually use that need the client runtime cross the boundary. +Those 62 pages cover 152 exported components once composable parts (`CardHeader`, `TableRow`, +`CommandItem` and friends) are counted, plus focus-trap, scroll-lock and anchor-positioning hooks. Every one +has a per-component subpath in the [exports map](./package.json). -Per-component subpaths are also exported, for consumers that want to keep the RSC graph explicit: +## Server components + +Every interactive component ships `'use client'` as line 1 of its emitted module, and the build +preserves one output file per source module. So the barrel is safe to import from a React Server +Component - only the components you actually use that need the client runtime cross the boundary. ```tsx -import { Card } from '@agentage/design-system/card'; // server component -import { Tabs } from '@agentage/design-system/tabs'; // 'use client' +import { Card } from '@agentage/design-system/card'; // server-safe +import { Modal } from '@agentage/design-system/modal'; // 'use client', already declared ``` -Design tokens (OKLCH color scales + semantic tokens) as CSS — import once at your app root: +No server-safe module transitively imports a client module, so importing `Card` never drags a +client boundary into your server tree. Per-component subpaths exist for consumers who want to keep +that graph explicit; the barrel works too. -```css -@import '@agentage/design-system/theme.css'; +## Theming + +Three tiers, composed by `theme.css`: + +| Layer | Import | What it holds | +| ---------------- | ---------------------------------------- | --------------------------------------------------- | +| `primitives.css` | `@agentage/design-system/primitives.css` | Raw OKLCH scales - 11 stops each, theme-independent | +| `tokens.css` | via `theme.css` | Semantic tokens, typography, shadows | +| `base.css` | via `theme.css` | Element resets | + +Dark is the default. Switch with one attribute on ``: + +```tsx +document.documentElement.setAttribute('data-theme', 'light'); // dark | light | system ``` -`theme.css` pulls in `primitives.css` (raw OKLCH scales), `tokens.css` (semantic tokens, typography, shadows), and `base.css` (element resets). `primitives.css` is also exported standalone. +`system` follows `prefers-color-scheme`. Override any semantic token in your own CSS to rebrand +without forking - see [ds.agentage.io/theming](https://ds.agentage.io/theming). + +## Requirements + +| Requirement | Version | Note | +| ----------- | ------- | --------------------------------------------------- | +| React | >= 19 | Peer, required | +| React DOM | >= 19 | Peer, required | +| Tailwind | >= 4 | Optional peer - needed unless you ship your own CSS | +| Node | >= 22 | Build/dev only; the package itself is browser code | + +Ships ESM only, with a `.d.ts` beside every module. ## Develop ```bash npm install -npm run dev # component showcase (Vite) on :5174 -npm run verify # type-check + lint + format + test + build +npm run dev # component showcase (Vite) on :5174 +npm run verify # type-check + lint + format + exports:check + test + build +npm run test:e2e # Playwright: axe WCAG A/AA scan + screenshot baselines ``` -- `src/components` — the components (barrel-exported from `src/index.ts`; add `'use client'` as line 1 to any component that uses client-only React — state, effects, refs, context, DOM APIs) -- `src/styles` — the OKLCH token + base-style CSS -- `src/lib` — `cn` and helpers -- `dev/` — the Vite showcase playground +- `src/components` - the components, barrel-exported from `src/index.ts`. Add `'use client'` as + line 1 to anything using state, effects, refs, context, portals, DOM APIs or event handlers. +- `src/styles` - the OKLCH token and base-style CSS. +- `src/lib` - `cn` and helpers. +- `dev/` - the showcase deployed to ds.agentage.io. + +Run `npm run exports:generate` after adding or renaming a component; `exports:check` fails +`verify` when the exports map drifts. + +Regenerate Playwright screenshot baselines inside the CI image, never on the host - font metrics +must match: + +```bash +docker run --rm --ipc=host -v "$PWD":/work -w /work -u "$(id -u):$(id -g)" -e HOME=/tmp \ + mcr.microsoft.com/playwright:v1.62.1-noble npx playwright test --update-snapshots +``` ## Release -Publishing to npm is release-gated (`.github/workflows/publish.yml`): +Publishing is release-gated (`.github/workflows/publish.yml`): bump `version` in `package.json` +with a `chore(release): vX.Y.Z` commit (or run the workflow via **workflow_dispatch**). On merge +to `master` the workflow runs `verify`, then `npm publish --access public --provenance`, and tags +the release. + +## Contributing + +Issues and PRs welcome at +[github.com/agentage/design-system](https://github.com/agentage/design-system). Branch off +`master`, keep `npm run verify` green, and add a test when you change interactive behavior. -1. Bump `version` in `package.json` with a commit like `chore(release): v0.3.1` (or run the workflow via **workflow_dispatch**). -2. On merge to `master` the workflow runs `verify`, then `npm publish --access public --provenance`, and tags the release. +## License -Requires an `NPM_TOKEN` repo secret with publish rights to the `@agentage` scope. +MIT - see [LICENSE](./LICENSE). diff --git a/dev/app.tsx b/dev/app.tsx index 9b21b3d..3fe4e1d 100644 --- a/dev/app.tsx +++ b/dev/app.tsx @@ -1,9 +1,9 @@ 'use client'; import { useState } from 'react'; -import { EmptyState, Heading, ToastProvider, ToggleGroup } from '../src'; +import { CopyButton, EmptyState, Heading, ToastProvider, ToggleGroup } from '../src'; import { DocsNav } from './components/docs-nav'; import { Search } from './components/search'; -import { BrandedLogo } from './lib/icons'; +import { BrandedLogo, GitHubIcon, NpmIcon } from './lib/icons'; import { Link, RouterProvider, useRoute } from './lib/router'; import { CategoryPage } from './pages/category-page'; import { ComponentPage } from './pages/component-page'; @@ -18,6 +18,13 @@ const TOP_NAV = [ { to: '/theming', label: 'Theming' }, ]; +const INSTALL_CMD = 'npm i @agentage/design-system'; + +const EXTERNAL_LINKS = [ + { href: 'https://www.npmjs.com/package/@agentage/design-system', label: 'npm', Icon: NpmIcon }, + { href: 'https://github.com/agentage/design-system', label: 'GitHub', Icon: GitHubIcon }, +]; + const AllCategories = () => (
@@ -80,7 +87,7 @@ const Shell = () => { {
+
+ + {INSTALL_CMD} + + +
+ {EXTERNAL_LINKS.map(({ href, label, Icon }) => ( + + + + ))} ( ); +export const GitHubIcon = () => ( + +); +export const NpmIcon = () => ( + +); diff --git a/docs/banner.svg b/docs/banner.svg new file mode 100644 index 0000000..0267d6e --- /dev/null +++ b/docs/banner.svg @@ -0,0 +1,88 @@ + + + + + + + + + + + + + + + + + + Agent + + Age + + + + Design System + OKLCH tokens + 60+ React components, ready to install. + + + + + + React 19 + + + + Tailwind v4 + + + + RSC-safe + + + + WCAG AA + + + + + + + $ + npm install @agentage/design-system + + + + + OKLCH GOLD SCALE + + + + + + + + + + + + + + + + Memories + 12,480 + + + + + + + Open + + + + + All systems nominal + + + diff --git a/package.json b/package.json index b854d51..8567214 100644 --- a/package.json +++ b/package.json @@ -1,14 +1,36 @@ { "name": "@agentage/design-system", "version": "0.12.0", - "description": "Agentage design system — OKLCH design tokens + React component library.", - "type": "module", - "license": "UNLICENSED", + "description": "Agentage Design System - OKLCH design tokens and 60+ accessible React 19 components. RSC-safe (per-module \"use client\"), Tailwind CSS v4, tree-shakeable ESM with per-component subpath exports.", + "keywords": [ + "design-system", + "react", + "react-19", + "component-library", + "ui-components", + "tailwindcss", + "tailwind-v4", + "oklch", + "design-tokens", + "rsc", + "react-server-components", + "accessibility", + "wcag", + "radix-ui", + "typescript", + "agentage" + ], + "license": "MIT", "author": "Volodymyr Vreshch ", + "homepage": "https://ds.agentage.io", "repository": { "type": "git", - "url": "https://github.com/agentage/design-system.git" + "url": "git+https://github.com/agentage/design-system.git" }, + "bugs": { + "url": "https://github.com/agentage/design-system/issues" + }, + "type": "module", "exports": { ".": { "types": "./dist/index.d.ts",