From 9faec593388b3037eea57a4c7798e4d8c05cf5f7 Mon Sep 17 00:00:00 2001 From: Denozordec Date: Tue, 21 Jul 2026 00:22:49 +0700 Subject: [PATCH] =?UTF-8?q?feat(web):=20=D1=83=D0=BD=D0=B8=D1=84=D0=B8?= =?UTF-8?q?=D1=86=D0=B8=D1=80=D0=BE=D0=B2=D0=B0=D1=82=D1=8C=20ReUI=20PRO?= =?UTF-8?q?=20=E2=80=94=20ResourcePage,=20KpiStatGrid,=20chrome?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Списки на ResourcePage, KPI на EvoBGP hybrid KpiStatGrid; удалены DataGridCard/SectionCards/ModeToggle; обновлены rules, skill и design contract. Co-authored-by: Cursor --- .agents/skills/reui/SKILL.md | 90 ++-- .agents/skills/reui/rules/adapting.md | 43 ++ .agents/skills/reui/rules/cli.md | 60 +++ .agents/skills/reui/rules/components.md | 358 ++++++++++++++ .agents/skills/reui/rules/craft.md | 45 ++ .agents/skills/reui/rules/icons.md | 39 ++ .agents/skills/reui/rules/quality.md | 22 + .agents/skills/reui/rules/registry.md | 35 ++ .agents/skills/reui/rules/styling.md | 26 + .agents/skills/reui/rules/workflow.md | 54 +++ .agents/skills/reui/tools.md | 58 +++ .claude/skills/reui/SKILL.md | 67 +++ .claude/skills/reui/rules/adapting.md | 43 ++ .claude/skills/reui/rules/cli.md | 60 +++ .claude/skills/reui/rules/components.md | 358 ++++++++++++++ .claude/skills/reui/rules/craft.md | 45 ++ .claude/skills/reui/rules/icons.md | 39 ++ .claude/skills/reui/rules/quality.md | 22 + .claude/skills/reui/rules/registry.md | 35 ++ .claude/skills/reui/rules/styling.md | 26 + .claude/skills/reui/rules/workflow.md | 54 +++ .claude/skills/reui/tools.md | 58 +++ .cursor/rules/backend-api-ui.mdc | 2 +- .cursor/rules/frontend-monorepo.mdc | 2 +- .cursor/rules/frontend-shadcn.mdc | 209 ++------- .cursor/rules/frontend-ui-patterns.mdc | 199 ++++++-- .cursor/rules/reui-mcp.mdc | 85 ++-- .cursor/rules/reui.mdc | 73 +++ .cursor/rules/shadcn-mcp.mdc | 62 +-- .cursor/rules/shadcn-ui-production.mdc | 33 +- .cursor/skills/reui/SKILL.md | 67 +++ .cursor/skills/reui/rules/adapting.md | 43 ++ .cursor/skills/reui/rules/cli.md | 60 +++ .cursor/skills/reui/rules/components.md | 358 ++++++++++++++ .cursor/skills/reui/rules/craft.md | 45 ++ .cursor/skills/reui/rules/icons.md | 39 ++ .cursor/skills/reui/rules/quality.md | 22 + .cursor/skills/reui/rules/registry.md | 35 ++ .cursor/skills/reui/rules/styling.md | 26 + .cursor/skills/reui/rules/workflow.md | 54 +++ .cursor/skills/reui/tools.md | 58 +++ AGENTS.md | 5 +- apps/web/src/components/analytics-page.tsx | 4 +- apps/web/src/components/data-grid-types.ts | 2 +- apps/web/src/components/mode-toggle.tsx | 29 -- .../frame-data-grid.tsx} | 14 +- apps/web/src/components/reui-kit/index.ts | 18 +- apps/web/src/components/reui-kit/kpi-cols.ts | 10 + .../src/components/reui-kit/kpi-stat-grid.tsx | 268 ++++++++--- .../components/reui-kit/quick-action-grid.tsx | 11 +- .../src/components/reui-kit/resource-page.tsx | 444 ++++++++++++------ apps/web/src/components/section-cards.tsx | 66 --- apps/web/src/components/skeletons.tsx | 52 +- .../src/components/tariff-filters-toolbar.tsx | 2 +- .../src/components/vps-filters-toolbar.tsx | 2 +- .../src/lib/data-grid-column-visibility.ts | 28 ++ apps/web/src/routes/_auth/accounts.tsx | 17 +- apps/web/src/routes/_auth/audit.tsx | 6 +- apps/web/src/routes/_auth/balance.tsx | 14 +- apps/web/src/routes/_auth/dashboard.tsx | 18 +- apps/web/src/routes/_auth/payments.tsx | 14 +- .../src/routes/_auth/projects.$projectId.tsx | 14 +- apps/web/src/routes/_auth/projects.tsx | 10 +- apps/web/src/routes/_auth/providers.tsx | 6 +- apps/web/src/routes/_auth/renewals.tsx | 8 +- apps/web/src/routes/_auth/reports.tsx | 4 +- apps/web/src/routes/_auth/resources.tsx | 10 +- apps/web/src/routes/_auth/sync-journal.tsx | 6 +- apps/web/src/routes/_auth/tariffs.tsx | 11 +- apps/web/src/routes/_auth/vps.$vpsId.tsx | 6 +- apps/web/src/routes/_auth/vps.tsx | 6 +- docs/ui-design-contract.md | 80 ++-- 72 files changed, 3505 insertions(+), 789 deletions(-) create mode 100644 .agents/skills/reui/rules/adapting.md create mode 100644 .agents/skills/reui/rules/cli.md create mode 100644 .agents/skills/reui/rules/components.md create mode 100644 .agents/skills/reui/rules/craft.md create mode 100644 .agents/skills/reui/rules/icons.md create mode 100644 .agents/skills/reui/rules/quality.md create mode 100644 .agents/skills/reui/rules/registry.md create mode 100644 .agents/skills/reui/rules/styling.md create mode 100644 .agents/skills/reui/rules/workflow.md create mode 100644 .agents/skills/reui/tools.md create mode 100644 .claude/skills/reui/SKILL.md create mode 100644 .claude/skills/reui/rules/adapting.md create mode 100644 .claude/skills/reui/rules/cli.md create mode 100644 .claude/skills/reui/rules/components.md create mode 100644 .claude/skills/reui/rules/craft.md create mode 100644 .claude/skills/reui/rules/icons.md create mode 100644 .claude/skills/reui/rules/quality.md create mode 100644 .claude/skills/reui/rules/registry.md create mode 100644 .claude/skills/reui/rules/styling.md create mode 100644 .claude/skills/reui/rules/workflow.md create mode 100644 .claude/skills/reui/tools.md create mode 100644 .cursor/rules/reui.mdc create mode 100644 .cursor/skills/reui/SKILL.md create mode 100644 .cursor/skills/reui/rules/adapting.md create mode 100644 .cursor/skills/reui/rules/cli.md create mode 100644 .cursor/skills/reui/rules/components.md create mode 100644 .cursor/skills/reui/rules/craft.md create mode 100644 .cursor/skills/reui/rules/icons.md create mode 100644 .cursor/skills/reui/rules/quality.md create mode 100644 .cursor/skills/reui/rules/registry.md create mode 100644 .cursor/skills/reui/rules/styling.md create mode 100644 .cursor/skills/reui/rules/workflow.md create mode 100644 .cursor/skills/reui/tools.md delete mode 100644 apps/web/src/components/mode-toggle.tsx rename apps/web/src/components/{data-grid-card.tsx => reui-kit/frame-data-grid.tsx} (97%) create mode 100644 apps/web/src/components/reui-kit/kpi-cols.ts delete mode 100644 apps/web/src/components/section-cards.tsx create mode 100644 apps/web/src/lib/data-grid-column-visibility.ts diff --git a/.agents/skills/reui/SKILL.md b/.agents/skills/reui/SKILL.md index 082d38f..d76c1c2 100644 --- a/.agents/skills/reui/SKILL.md +++ b/.agents/skills/reui/SKILL.md @@ -1,65 +1,67 @@ --- name: reui -description: ReUI enterprise-компоненты в vps-tracker — registry @reui, CLI, импорты, матрица выбора. Использовать при Data Grid, Filters, Autocomplete, Number Field, Date Selector и других @reui/* задачах. +description: Use the ReUI registry from your AI agent - find, install, and correctly use ReUI components (the 17 free building blocks like data-grid, kanban, filters), their free examples, premium blocks, and Motion Icons. Applies in any project using ReUI, the @reui registry, REUI_LICENSE_KEY, or any shadcn project where the user asks for premium blocks, data grids, kanban boards, dashboards, or full pages. Pairs with the free ReUI MCP server for live, scored registry search and inline component APIs. +user-invocable: false +allowed-tools: Bash(npx shadcn@latest *), Bash(pnpm dlx shadcn@latest *), Bash(bunx --bun shadcn@latest *) --- -# ReUI (vps-tracker) +> **ReUI skill version `42d70dcc3d`.** If the ReUI MCP's `get_agent_skill` reports a newer `version`, re-run the ReUI installer (see `get_agent_skill` -> `install.recommended`) to update this skill. Cloud/tools-only agents have no local file and always read the latest - they can ignore this. -## Источники +# ReUI for Agents -1. [llms.txt](https://reui.io/llms.txt) — каталог для ИИ -2. MCP `plugin-shadcn-shadcn` с `registries: ["@reui"]` -3. Docs: `https://reui.io/docs/components/base/` (Copy Markdown) -4. Правила: `.cursor/rules/reui-mcp.mdc` +ReUI is a shadcn-compatible registry. It ships four things you **reuse** - never redesign: -## CLI (только из apps/web) +- **components** - the 17 ReUI building blocks with real APIs: `data-grid`, `kanban`, `filters`, `date-selector`, `tree`, `stepper`, ... (free) +- **examples** - free `c-*` single-pattern use-cases of a component (`c-kanban-1`); install one and read it to see exact composition +- **blocks** - premium full-page sections that compose components (`data-grid-2`, `pricing-page-1`); Pro or Ultimate license at install +- **icons** - Motion Icons in 4 styles, static + hover-animated variants; Ultimate license at install -```bash -cd apps/web -pnpm dlx shadcn@latest add @reui/data-grid --dry-run -pnpm dlx shadcn@latest add @reui/filters -``` +The skill is free and this MCP is free to use; it just needs a ReUI account. On first use your agent opens a browser "Sign in with ReUI" prompt (a free account is created if you don't have one). Free covers components and examples with a daily request allowance; a Pro or Ultimate license unlocks premium blocks and Motion Icons and removes the limit (see [rules/registry.md](./rules/registry.md)). The same account and skill work in every agent and service the MCP connects to - this skill is agent-agnostic. -## Размещение +Skill + MCP are a team: this skill is the workflow (how to find, install, read the API, and adapt by reuse); the MCP is the live data and the hands (search, get_component, install commands). Your job: find the right item, install it with the shadcn CLI, read its real API, and **adapt by reuse** - wire real data and theme it; do not hand-roll or restyle what ReUI already provides. This skill **layers on the shadcn skill**: follow that for generic rules (spacing, `cn()`, semantic colors, forms); follow this for everything ReUI-specific. -| Registry | Путь | Импорт | -|----------|------|--------| -| `@shadcn` | `packages/ui/src/components/` | `@cfdm/ui/components/*` | -| `@reui` | `apps/web/src/components/reui/` | `@/components/reui/*` | +## The core loop (MCP-native) -Только **Base UI** (`base-nova`). Radix-варианты не использовать. +1. **Find** - call the ReUI MCP `search` tool with the user's intent. It returns a ranked, scored list across components/examples/blocks/icons, each with an `install` command, `previewUrl`, `docsUrl`, and `componentsUsed`. Pass hints (`type`, `component`, `category`, `features`, `free`) when you can infer them. +2. **Install** - run the returned command non-interactively (`npx shadcn@latest add @reui/ --yes`). The CLI resolves deps, aliases, and the base/style from `components.json`. See [cli.md](./rules/cli.md). +3. **Read the API (on your base)** - first note your base from `components.json` -> `style` (`base-nova` -> Base UI, `radix-nova` -> Radix UI). For each component an item uses, call `get_component(name)` and read its **inline `api`** (no web fetch); then `get_examples(name)` to install a worked example and copy its composition - the installed files are already in your base. Whenever you work with a component's API, also **share its `docsUrl`** (the primitive's API documentation page) with the user so they have the full reference. See [components.md](./rules/components.md). +4. **Adapt (reuse-first)** - swap demo data for real data, fix icon imports, align tokens. Do not redesign. See [adapting.md](./rules/adapting.md). -## Уже установлено +**Always show the preview.** Every item a tool returns carries a `previewUrl` (a live preview page). Whenever you list, recommend, or present ReUI items to the user - blocks, components, examples, or icons, whether from `search`, `search_icons`, `list_components`, `compose_page`, or any getter - include each item's `previewUrl` so they can SEE it before installing. Blocks and examples open an individual live preview; icons and components link to their live category/component page. Never present an item without its preview link. -`autocomplete`, `badge`, `color-picker`, `data-grid/*`, `date-selector`, `filters`, `number-field` +If the ReUI MCP is not configured, fall back to `npx shadcn@latest search @reui -q "..."` then `add` - but the MCP gives scored matches + inline APIs; prefer it. -## Shared-обёртки проекта +## Commands -| ReUI | Обёртка | -|------|---------| -| data-grid | `DataGridCard` | -| filters | `VpsFiltersToolbar` | -| autocomplete | `AutoCompleteInput` | -| date-selector | `lib/date-selector-i18n.ts` | -| color-picker | напрямую в domain forms (`project-edit-sheet`) | +Run ReUI as explicit slash commands (via the ReUI MCP) **or** just ask in plain language - both run the same workflow. -## Матрица выбора +| Command | Invoke | Does | +| ----------- | ------------------------------ | ------------------------------------------------------------------------------------------------------------------ | +| **build** | `/mcp__reui__build ` | Compose a page/section/feature from ReUI: plan → install → read API → adapt → craft → audit. | +| **add** | `/mcp__reui__add ` | Find & install one component/example/block/icon and wire it in. | +| **fix** | `/mcp__reui__fix [target]` | Diagnose & fix ReUI usage: wrong/undocumented props, base/radix mismatch, missing states, a11y/scroll. | +| **improve** | `/mcp__reui__improve [target]` | Refine + extend existing ReUI UI to a production-exceptional bar (hierarchy, density, states, responsive, motion). | -- Простая таблица → shadcn `Table` -- Списки с sort/pagination/virtual/columns → `DataGridCard` (`@reui/data-grid`) -- Мультифильтры → `@reui/filters` -- Числа со stepper → `@reui/number-field` -- Semantic status → `StatusBadge` или `@reui/badge` variant +Invocation differs slightly per agent (`/mcp__reui__build` in Claude Code/Cursor/Windsurf, `/mcp.reui.build` in VS Code). No command surface? Just describe what you want - this skill drives the identical loop. -## Зависимости (apps/web only) +## When to reach for ReUI vs plain shadcn -`@tanstack/react-table`, `@tanstack/react-virtual`, `@dnd-kit/*`, `date-fns`, `react-day-picker` +| Need | Reach for | +| -------------------------------------------------------------------- | ------------------------------------------------------------------------- | +| A full page or section (dashboard, billing, auth, pricing, settings) | `compose_page` first (plans sections + best blocks), then ReUI **blocks** | +| A data table with sorting/filtering/pagination/virtualization | the **data-grid** component (never hand-roll a ``) | +| A drag-and-drop board | the **kanban** component | +| Advanced column filtering, date range, tree, stepper, ... | the matching ReUI **component** | +| A single generic control already in shadcn (Button, Dialog, Select) | plain **shadcn** | -После add — `pnpm install` + `pnpm --filter web build`. +## Detailed references -## Post-add - -- `@/components/ui/*` → `@cfdm/ui/components/*` -- Не класть ReUI в `packages/ui` -- Semantic colors: `variant="success"` — не `bg-emerald-*` -- `color-picker`: hex только в preset data, не в Tailwind `className` +- [rules/registry.md](./rules/registry.md) - the four types, the @reui registry, base/radix, free vs premium + license +- [rules/workflow.md](./rules/workflow.md) - the find -> install -> read-API -> adapt loop (most important) +- [rules/components.md](./rules/components.md) - the 17 components, the data-grid contract, base vs radix +- [rules/adapting.md](./rules/adapting.md) - reuse-first: preserve the design (no over-customizing), reuse examples + a block's own elements, real data, don't invent APIs +- [rules/craft.md](./rules/craft.md) - make it exceptional: point of view, hierarchy, density, states, responsive, motion, the bar +- [rules/quality.md](./rules/quality.md) - security, accessibility, and scroll gates (the done gate) +- [rules/styling.md](./rules/styling.md) - ReUI extended tokens, theme adaptation, density +- [rules/icons.md](./rules/icons.md) - portable icons, swapping imports, Motion Icons (static + animated) +- [tools.md](./tools.md) - the ReUI MCP: golden path, the 19 tools, token rules, result shapes, errors diff --git a/.agents/skills/reui/rules/adapting.md b/.agents/skills/reui/rules/adapting.md new file mode 100644 index 0000000..b0c1a16 --- /dev/null +++ b/.agents/skills/reui/rules/adapting.md @@ -0,0 +1,43 @@ +# Adapting installed ReUI code (reuse-first, no AI slop) + +ReUI items ship production-quality. Your job is to **adapt by reuse** - wire real data and fit the app - not to redesign or hand-roll. The output should look like ReUI built it for this product. + +## Preserve the design - don't over-customize + +The design IS the product. A ReUI block/component encodes senior-designer decisions: spacing, hierarchy, density, color treatment, and component choices. The fastest way to turn a premium block back into generic AI slop is to "improve" its look - so don't. + +- Change **data, copy, and props**; keep the **structure and styling** it ships with. Make the **smallest** change that wires the real data. If your diff touches `className` / JSX structure more than data / props, you are over-customizing - stop and reuse. +- Don't swap ReUI components for hand-rolled ones, restructure the layout, re-skin spacing / radius / colors, or add decorative chrome. Let the installed components carry the default spacing, radius, sizing, icon rhythm, density, and state styling; add custom Tailwind only when a component genuinely lacks a contract you need. +- Want a different look? `search` for a block whose design already fits and reuse that - don't restyle this one into a new design. + +## Reuse the parts: examples and the block's own elements + +- **Examples are building parts.** A free `c-*` example is a correct, single-pattern composition you can reuse. Before composing from scratch, `get_examples(component)`, install the closest one, and reuse its wiring - assemble UI from examples instead of hand-rolling what an example already shows. +- **Reuse a block's own elements.** Need more rows, cards, items, or sections than ship by default? Repeat the block's **existing** element by mapping real data through the same markup - never invent parallel markup that drifts from its design. Need a variant (empty / loading / expanded)? Derive it from an element the block already has. + +## Don't invent (read, don't guess) + +- Never write a prop, variant value, import path, or `@reui/...` name you didn't read in a component's inline `api`, an installed example, or a `search` result. If you didn't see it, treat it as nonexistent - call `get_component` / `get_examples` / `search` first, or run the MCP `validate_usage` tool to check planned names + props against the docs before writing code. +- If a getter returns `found: false` or `search` returns nothing, say so and fall back (plain shadcn, or ask) - never fabricate an install command or an API. + +## What to change vs leave alone + +- **Change:** the item's own data, copy, props, and layout to fit the app. +- **Leave alone:** installed component files, hooks, and the shared theme - do not edit vendored ReUI internals; change behavior through props and the documented API. +- Blocks are **portable React** - no `next/link`, `next/image`, or other framework-runtime imports inside them. Keep them portable. + +## Demo data -> real data + +- Replace every placeholder with the user's real data. Model it as **typed data structures** and **map over arrays** - never duplicate JSX per row/card. Keep small block-specific formatters next to the data. +- Wire the real source (columns, fields, fetch). For `data-grid`, implement the server fetch contract if the user needs server-side data. +- **Type from the component API, derive during render.** Type domain state through the component's own types - e.g. map status to `BadgeProps["variant"]` via a typed `Record` - instead of stringly-typed values. Compute view state during render; don't mirror derived data into `useState`/`useEffect`. +- **Adapt on the right base.** Use the API for the project's base (Base UI vs Radix - see [components.md](./components.md)); the installed files are already base-correct, so reuse their shape rather than translating from memory. + +## Believable content (no AI tells) + +- Use realistic labels, counts, timestamps, and statuses that map to a real workflow. +- No decorative buttons, fake tabs, meaningless toggles, equal-weight card walls, empty gradients, ornamental icons, or generic SaaS filler. Every element should do something. + +## Operational surfaces (settings / profile / admin) + +Pick ONE archetype and keep the family consistent: a vertical rail (3-6 sections), horizontal tabs (5-8), or a frame/stack. Prefer `frame` for tool-like surfaces, a card for profile-like ones. Don't mix archetypes in one surface. diff --git a/.agents/skills/reui/rules/cli.md b/.agents/skills/reui/rules/cli.md new file mode 100644 index 0000000..7c40844 --- /dev/null +++ b/.agents/skills/reui/rules/cli.md @@ -0,0 +1,60 @@ +# CLI: registry setup, license, non-interactive install + +## Registry setup (one-time, per project) + +Free items (the 17 components and all `c-*` examples) need only the plain string registry in `components.json`: + +```json +{ "registries": { "@reui": "https://reui.io/r/{style}/{name}.json" } } +``` + +Premium items (blocks; Motion Icons and templates) require a ReUI license at install: + +1. Add the key to `.env.local`: + +```bash +REUI_LICENSE_KEY=your-license-key +``` + +2. Switch `components.json` to the authenticated object form: + +```json +{ + "registries": { + "@reui": { + "url": "https://reui.io/r/{style}/{name}.json", + "headers": { "Authorization": "Bearer ${REUI_LICENSE_KEY}" } + } + } +} +``` + +The shadcn CLI expands `${REUI_LICENSE_KEY}` from `.env.local` inside `components.json`, but an MCP client config never expands variables, so a ReUI MCP server config must carry the raw token instead (for example `reui_pat_your_token_here`). + +The MCP `get_project_context` tool returns the right config. Full guide: https://reui.io/docs/registry + +## Installing + +Use the project's package runner (check `packageManager`): + +```bash +npx shadcn@latest add @reui/ --yes # npm +pnpm dlx shadcn@latest add @reui/ --yes # pnpm +bunx --bun shadcn@latest add @reui/ --yes # bun +``` + +`--yes` skips confirmation prompts. The CLI auto-detects the package manager from the lockfile (there is no `--package-manager` flag). It also resolves the correct base+style variant from `components.json`, so do not pass a style. + +## Handling prompts and conflicts + +- **Always pass `--yes`** so the CLI does not block on confirmation prompts. +- **Do NOT pass `--overwrite` by default.** If the CLI reports an existing file, read the output and resolve deliberately: install under a different name, adjust the path, or ask the user. Only use `--overwrite` when the user explicitly wants to replace a file. +- **Preview first when touching an existing project**: `npx shadcn@latest add @reui/ --dry-run` shows what would change; `--diff ` shows a specific file's diff. Use these before overwriting. +- Run from the **project root** so `components.json` and `.env.local` are found. + +## Free vs premium boundary + +- Public, no key: `c-*` examples and the 17 components (`@reui/data-grid`, `@reui/badge`, ...) that those examples depend on. +- Key required at install: blocks (`@reui/-N`) need a Pro or Ultimate license; Motion Icons (`@reui/icons/...`) and templates need Ultimate. + +If an install 401/403s, the license key is missing, invalid, or the plan does not cover that resource (blocks: Pro or higher; icons and templates: Ultimate). Point the user to https://reui.io/account (their key) or https://reui.io/pricing (upgrade). diff --git a/.agents/skills/reui/rules/components.md b/.agents/skills/reui/rules/components.md new file mode 100644 index 0000000..0c24578 --- /dev/null +++ b/.agents/skills/reui/rules/components.md @@ -0,0 +1,358 @@ +# ReUI components + +The 19 ReUI building blocks: `alert`, `autocomplete`, `badge`, `data-grid`, `date-selector`, `event-calendar`, `filters`, `frame`, `gantt`, `icon-stack`, `kanban`, `number-field`, `phone-input`, `rating`, `scrollspy`, `sortable`, `stepper`, `timeline`, `tree`. Examples and blocks are composed from these. + +**Rule one: never guess a component's API. Read it first.** Call **`get_component(name)`** for its inline `api` (props + usage, no web fetch), and **share the result's `docsUrl`** (the component's API documentation page) with the user whenever you work with that component's API, so they have the full reference (the `/llms.txt` index is a further fallback). Then call **`get_examples(name)`** to install a worked example and copy real composition. The contracts below are first-try orientation (required props, composition shape, the one gotcha); the inline `api` is the full reference. No single block fits? Compose: search the components you need, read each `get_component`, install a `get_examples` example per component, and adapt. + +## data-grid (the flagship - read its API every time) + +`data-grid` wraps TanStack Table v8. It is NOT a styled `
` and does NOT take `data`/`columns` props directly. The contract: + +- Build a TanStack table instance with `useReactTable(...)` (columns, data, the feature models you need: sorting, pagination, row selection). +- Pass that instance to ``. +- Compose the body with `DataGridTable` inside `DataGrid`, and enable features through `tableLayout` (e.g. `{ headerSticky: true, columnsResizable: true }`), not ad-hoc classes. +- Server-side data uses the documented fetch shape (`recordCount` is the total for pagination). + +```tsx +const table = useReactTable({ + data, + columns, + getCoreRowModel: getCoreRowModel(), + // add sorting/pagination/selection models per the API +}) + + + + +``` + +Common mistakes: + +- **Incorrect:** `` - these props do not exist. **Correct:** build a `useReactTable` instance and pass `table={table}` + `recordCount`. +- **Incorrect:** a raw `
` / hand-rolled pagination. **Correct:** use `data-grid`; read its API for sticky header, pagination, virtualization, row selection. +- **Incorrect:** styling rows/cells with arbitrary classes. **Correct:** drive layout via `tableLayout` and the documented `ColumnMeta` (e.g. `cellClassName`, `headerTitle`). + +## event-calendar + +**Required:** events via `events`/`onEventsChange` (controlled) or `defaultEvents` (uncontrolled), plus a height on the root. +**Shape:** + +```tsx + + + + +``` + +**Gotcha:** headless-first: `EventCalendarContent` renders the active view (month/week/day/days/agenda; a resource view activates when `resources` is passed) - there is no per-view JSX to compose. Events are `{ id, title, start, end (exclusive), allDay?, color?, recurrence?, resourceId? }`. Mutations flow through `onEventUpdate`/`canDropEvent` (return `false` to reject); the root needs an explicit height because it is a min-h-0 flex column. + +## gantt + +**Required:** `resources` (the left tree) plus bars via `events`/`defaultEvents` attached by `resourceId`. +**Shape:** + +```tsx + + + + +``` + +**Gotcha:** bars move along the time axis only (never across rows) and are all-day spans with exclusive `end`; `progress` is 0-100. Scales are `day | week | month | quarter | year`. Zoom control, infinite scroll, summary rollups, and row checkboxes are ON by default - turn off what you do not need. Same `onEventUpdate`/`canDropEvent` commit pipeline as `event-calendar`; the root needs an explicit height. + +## kanban + +**Required:** `value` (`Record`), `onValueChange`, `getItemValue` +**Shape:** + +```tsx + i.id}> + + {Object.entries(cols).map(([id, items]) => ( + +

{id}

+ + {items.map((i) => ( + + {i.title} + + ))} + +
+ ))} +
+
+ +``` + +**Gotcha:** state is `Record`. Each `KanbanColumnContent value` must match its parent `KanbanColumn value`. Omit `KanbanOverlay` and the drag preview silently breaks. + +## sortable + +**Required:** `value` (`T[]`), `onValueChange`, `getItemValue` +**Shape:** + +```tsx + i.id}> + {items.map((i) => ( + + + {i.label} + + ))} + +``` + +**Gotcha:** a flat 1D reorder list (not columns - that is `kanban`). `getItemValue` must return a stable, unique string. Pass `layout="grid"` or `layout="nested"` for non-list layouts. + +## filters + +**Required:** `filters` (`Filter[]`), `fields` (`FilterFieldConfig[]`), `onChange` +**Shape:** + +```tsx +const [filters, setFilters] = useState([ + createFilter("priority", "is_any_of", ["low"]), +]) +const fields: FilterFieldConfig[] = [ + { key: "priority", label: "Priority", type: "multiselect", + options: [{ value: "low", label: "Low" }, { value: "high", label: "High" }] }, +] + + +``` + +**Gotcha:** always build initial filters with `createFilter(field, operator, values)` - it generates the required `id`. Never hand-construct a `Filter` object. Pairs naturally with `data-grid`. + +## date-selector + +**Required:** none, but wire `onChange` to capture the value. +**Shape:** + +```tsx +const [value, setValue] = useState() + + +``` + +**Gotcha:** the value is a structured `DateSelectorValue` (period / operator / start+end dates), NOT a `Date` - never pass a raw `Date`. Use `allowRange={false}` to lock single-date picking. Read `get_component("date-selector")` for the value shape. + +## tree + +**Required:** `tree` (a `@headless-tree/core` instance you construct) +**Shape:** + +```tsx + + {tree.getItems().map((item) => ( + + + + ))} + +``` + +**Gotcha:** `Tree` is a styled shell - it takes a headless-tree instance via `tree`, NOT `data`/`items` props. Build the instance with `@headless-tree/react`. External API: https://headless-tree.lukasbach.com/ + +## stepper + +**Required:** `StepperItem step` (number), `StepperContent value` (number) +**Shape:** + +```tsx + + + + 1 + + + + 2 + + + + Step 1 content + Step 2 content + + +``` + +**Gotcha:** steps are 1-indexed. Without `StepperPanel` + `StepperContent` you render the nav trail but no body. Put `StepperSeparator` in every `StepperItem` except the last. + +## timeline + +**Required:** `TimelineItem step` (number) +**Shape:** + +```tsx + + + + March 2024 + Project initialized + + + + Repo and architecture set up. + + +``` + +**Gotcha:** each item needs a unique `step`. `orientation` is `"vertical"` (default) or `"horizontal"`. This is a static event display, not interactive like `stepper`. + +## autocomplete + +**Required:** `items` (array; each item has at least `value`) +**Shape:** + +```tsx + + + + No results found. + + {(item) => ( + {item.label} + )} + + + +``` + +**Gotcha:** `AutocompleteList` takes a render-prop `(item) => ReactNode`, NOT a mapped array of children. External API: https://base-ui.com/react/components/autocomplete + +## phone-input + +**Required:** none, but wire `onChange`. +**Shape:** + +```tsx + +``` + +**Gotcha:** `value`/`onChange` use an E.164 string (e.g. `"+14155551234"`), not a display-formatted string; `onChange` can fire `undefined`. `defaultCountry` is a 2-letter ISO code. Wraps `react-phone-number-input`. + +## number-field + +**Required:** wrap the controls in `NumberFieldGroup`. +**Shape:** + +```tsx + + + + + + + + +``` + +**Gotcha:** import from `@/components/ui/number-field`. The accessible label goes on `NumberFieldScrubArea`, not `NumberField`. External API: https://base-ui.com/react/components/number-field + +## rating + +**Required:** `rating` (number) +**Shape:** + +```tsx + +``` + +**Gotcha:** supports decimals (partial stars). Pass `editable` + `onRatingChange` for interactive input; omit both for a read-only display. + +## scrollspy + +**Required:** `targetRef` (the scroll container ref) +**Shape:** + +```tsx + + Section 1 + Section 2 + +
+
...
+
...
+
+``` + +**Gotcha:** each link's `data-scrollspy-anchor` must match a section `id`. `targetRef` is the scrollable container (defaults to the window). + +## frame + +**Required:** `Frame` > `FramePanel` +**Shape:** + +```tsx + + + + Title + Description + +
Content
+ Footer +
+ +``` + +**Gotcha:** a structured card shell for tool-like surfaces. `stacked` connects multiple panels with shared borders; `dense` removes panel padding; radius via the `--frame-radius` CSS variable. + +## icon-stack + +**Required:** one child icon +**Shape:** + +```tsx + +``` + +**Gotcha:** isometric layered artwork for empty states and illustrations; style the inner icon via its own `className`. Mark purely decorative stacks `aria-hidden="true"` and keep the real label in surrounding copy. + +## alert + +**Required:** `Alert` > `AlertTitle` +**Shape:** + +```tsx + + + Security update + Enable two-factor authentication. + + +``` + +**Gotcha:** shadcn-compatible API. `variant`: `default | destructive | info | success | warning | invert`. The non-default variants use ReUI extended color tokens (`--success`/`--info`/`--warning`/`--invert`), which the install adds. Defer generic alert rules to the shadcn skill. + +## badge + +**Required:** none (text child). +**Shape:** + +```tsx +Success +Pill +``` + +**Gotcha:** shadcn-compatible. Rich `variant` set (solid, `-outline`, `-light` per color), `size` `xs..xl`, `radius` `default | full`. Like `alert`, the color variants rely on ReUI extended tokens. Prefer `Badge` variants over raw color classes for statuses. + +## base vs radix - write for the project's base + +ReUI ships every component in two builds: `base` (Base UI) and `radix` (Radix UI). The install command and name are identical, and the CLI installs the build matching the project. But you must write/adapt code against the **right base**, because their APIs differ. + +**Detect the base first.** Read `components.json` -> `style` and take the segment before the first `-`: + +- `"style": "base-nova"` -> **Base UI** +- `"style": "radix-nova"` -> **Radix UI** + +**Then use that base's API.** The deltas mirror shadcn's base-vs-radix split: + +- Slot/composition: Base UI `render={<… />}` vs Radix `asChild`. +- `Select`: Base UI takes `items`; Radix uses `` children. +- `ToggleGroup`: Base UI `multiple` boolean vs Radix `type="single" | "multiple"`. + +The safest path is to **read the installed files and `c-*` examples** - they're already in your base, so reuse their wiring instead of guessing. When `get_component`'s inline `api` or an example shows the other base's shape, translate it to your base (or `validate_usage` to confirm). Defer the generic base/radix mechanics to the shadcn skill. diff --git a/.agents/skills/reui/rules/craft.md b/.agents/skills/reui/rules/craft.md new file mode 100644 index 0000000..4649858 --- /dev/null +++ b/.agents/skills/reui/rules/craft.md @@ -0,0 +1,45 @@ +# Craft: make ReUI UI exceptional, not generic + +ReUI items ship senior-designer quality. Your adaptation has to hold that bar, so the result reads like a real product surface a team would keep - not a wireframe an AI generated. Use these alongside the reuse rules in [adapting.md](./adapting.md). + +## Have a point of view + +Pick an emotional register before you compose - calm, operational, premium, editorial, dense, energetic - and let layout, spacing, surface treatment, and icon behavior all reinforce it. One or two memorable decisions and restraint everywhere else beats ten generic ones. UI with no point of view reads as generated. + +## Brutally clear hierarchy + +One focal point per card or panel: the dominant metric or task first, its label second, supporting detail third. The first thing the eye lands on should be the right thing; secondary text must read as secondary. Borders, separators, and surfaces do real work to create 2-3 information bands - don't flatten everything to equal weight. + +## Spacing rhythm and deliberate density + +Gaps are a signal, not a default. Keep them intentional and consistent within a family (`gap-1`/`gap-2` for tight operational rows, larger gaps for section breaks), and smaller within a group than between groups. Match the surrounding ReUI density; don't pad an operational surface like a marketing page, and don't drift density mid-section. The composition should still feel authored in grayscale. + +## Cover the real states (the usual miss) + +A surface isn't done at the happy path. Compose, and wire: + +- **Empty** - a purposeful empty state (short message + the primary action), never a blank panel. +- **Loading** - a **skeleton** that matches the real layout, not a centered spinner. +- **Error** - an inline, recoverable error with a retry, announced via `role="status"`/`aria-live`. + +Derive these from an element the block already has (don't invent parallel markup), or `get_examples` for a state-specific example. + +## Responsive by default + +Mobile-first, not mobile-afterthought. In constrained rows/cards/sidebars, put `min-w-0` on the shrinking container and `truncate` long single-line labels; protect the primary label's width and let secondary content compress. Reflow layouts (multi-column -> single column) rather than just shrinking them. Desktop and mobile should both look designed. + +## Motion, subtly + +Motion should clarify, not decorate. Use ReUI Motion Icons on primary actions for a subtle hover cue; keep transitions short (~200-300ms) with calm easing; prefer a skeleton pulse over a spinner. No bouncing, no gratuitous entrance animations on every element. + +## Real, activated content + +Use believable, typed data (realistic labels, counts, timestamps, statuses that map to a real workflow) - never lorem or abstract filler. Every visible control does something: no decorative buttons, fake tabs, meaningless toggles, or stats with no job. It must still hold with long names, empty values, and crowded data. + +## Avoid the AI tells + +These instantly read as generated - don't ship them: equal-weight card walls, empty gradients, repetitive padding everywhere, generic enterprise copy, ornamental icons, and number tiles that don't earn their place. + +## The bar + +Before you finish, ask: **would a product team keep this instead of replacing it? Does it still feel strong after swapping in real content?** If not, reuse the shipped ReUI design harder - don't restyle it into something new - then run the [quality.md](./quality.md) gates. diff --git a/.agents/skills/reui/rules/icons.md b/.agents/skills/reui/rules/icons.md new file mode 100644 index 0000000..453d21c --- /dev/null +++ b/.agents/skills/reui/rules/icons.md @@ -0,0 +1,39 @@ +# Icons (ReUI delta over shadcn) + +Follow the shadcn icon rules (use the project's configured `iconLibrary`, `data-icon` on icons inside `Button`, no sizing classes on icons inside components, pass icons as component objects not string keys). ReUI adds the following. + +## Portable icons (library-agnostic) + +ReUI components, examples, and blocks are authored to be icon-library-agnostic. When `iconLibrary` is set in `components.json`, the shadcn CLI installs each item's icons in **your** library automatically - you swap nothing. If an installed item's icons don't match your project (for example `iconLibrary` isn't set, so they came in from the item's demo library), change the **import source and component name** to your library, keeping the same icon-name semantics: + +- `lucide` -> `lucide-react` +- `tabler` -> `@tabler/icons-react` +- `phosphor` -> `@phosphor-icons/react` +- `remix` -> `@remixicon/react` +- `hugeicons` -> `@hugeicons/react` + +Don't assume `lucide-react`; read `iconLibrary` from `components.json`. + +## Keep icons purposeful + +Icons support the hierarchy, they don't replace it: keep them small, matched to the surrounding density, and decorative ones `aria-hidden="true"` (an icon-only control still needs an accessible label on the control). Don't add ornamental icons that do no job. + +## Motion Icons (the `@reui/icons/...` set) + +ReUI ships its own icon set in 4 styles (outline, solid, duotone, filled), each icon in two variants: + +```bash +npx shadcn@latest add @reui/icons/default/