@viliha/vui-ui 1.1.2 → 1.1.4

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/AGENT.md CHANGED
@@ -1,10 +1,17 @@
1
1
  # Using VUI in your project (AI agent guide)
2
2
 
3
3
  > **Audience:** developers — and their AI agents — **consuming** `@viliha/vui-ui`
4
- > in a downstream app. This file ships with the npm package; point your agent at
5
- > `node_modules/@viliha/vui-ui/AGENT.md` (or copy it into your repo, e.g. rename
6
- > to `AGENTS.md` so agent tools auto-load it). To *contribute to* the theme
7
- > itself, see [CONTRIBUTING.md](https://github.com/myviliha/vui-starter/blob/main/CONTRIBUTING.md)
4
+ > in a downstream app. This file ships with the npm package. To auto-load these
5
+ > rules, copy the ready-made pointer to your project root — it `@`-imports this
6
+ > file, so you never duplicate the rules:
7
+ >
8
+ > ```bash
9
+ > cp node_modules/@viliha/vui-ui/CLAUDE.template.md ./CLAUDE.md # Claude Code
10
+ > # or ./AGENTS.md for other agent tools
11
+ > ```
12
+ >
13
+ > To *contribute to* the theme itself, see
14
+ > [CONTRIBUTING.md](https://github.com/myviliha/vui-starter/blob/main/CONTRIBUTING.md)
8
15
  > and [AGENTS.md](https://github.com/myviliha/vui-starter/blob/main/AGENTS.md).
9
16
 
10
17
  You are an expert Frontend Architect building enterprise applications using **VUI Starter**.
@@ -15,10 +22,14 @@ Do not reinvent the framework. Build with it.
15
22
 
16
23
  > **What you get from the package vs. what to copy.** `@viliha/vui-ui` ships the
17
24
  > component primitives (`Button`, `Input`, `Select`, `Dialog`, `Menu`,
18
- > `RecordView`, `ChartContainer`, `theme.css`, …). App-shell patterns referenced
19
- > below — `SetPageTitle`, `Breadcrumbs`, the sidebar/`nav-config`, and the
20
- > `AuthCard*` auth screens — are **reference-app patterns**, not package exports.
21
- > Copy them from the [backoffice demo](https://github.com/myviliha/vui-starter/tree/main/apps/backoffice)
25
+ > `RecordView`, `ChartContainer`, `Breadcrumbs`, `theme.css`, …). App-shell
26
+ > patterns referenced below — `SetPageTitle`, the sidebar, and the `AuthCard*`
27
+ > auth screens — are **reference-app patterns**, not package exports.
28
+ > The breadcrumb *trail-building logic* (`crumbsFor` + `nav-config` +
29
+ > `route-meta`) is also a reference-app pattern: the package exports the
30
+ > presentational `Breadcrumbs` component; the app derives the trail from the
31
+ > route and feeds it in. Copy the patterns from the
32
+ > [backoffice demo](https://github.com/myviliha/vui-starter/tree/main/apps/backoffice)
22
33
  > and adapt.
23
34
 
24
35
  ---
@@ -179,6 +190,23 @@ Always use:
179
190
 
180
191
  Do not build custom navigation systems unless the project explicitly requires it.
181
192
 
193
+ ## Breadcrumbs
194
+
195
+ One trail, **derived from the route — never hand-written per page.**
196
+
197
+ - Render with the shared `Breadcrumbs` component (`@viliha/vui-ui/breadcrumbs`):
198
+ last crumb is the current page (bold, non-interactive), earlier crumbs are
199
+ links, chevron separators.
200
+ - Build the trail from the URL against a single nav config (copy `crumbsFor` +
201
+ `nav-config` + `route-meta` from the reference app). Root it at **Home**
202
+ (your dashboard route). A section/group parent has no page of its own, so its
203
+ crumb links to its **first child** — clicking a section lands on that
204
+ section's first page.
205
+ - Ship **one** landing page, labeled "Home". Don't split "Home" and "Dashboard"
206
+ into two routes.
207
+
208
+ To reorder or rename, edit the nav config; the trail follows automatically.
209
+
182
210
  ---
183
211
 
184
212
  # Forms
@@ -0,0 +1,15 @@
1
+ <!--
2
+ VUI — AI agent rules for apps that consume @viliha/vui-ui.
3
+
4
+ Copy this file to your PROJECT ROOT as CLAUDE.md (Claude Code) and/or
5
+ AGENTS.md (other agent tools):
6
+
7
+ cp node_modules/@viliha/vui-ui/CLAUDE.template.md ./CLAUDE.md
8
+
9
+ The line below loads the agent guide that ships inside the package, so
10
+ AGENT.md stays the single source of truth — you never copy the rules
11
+ themselves, only this pointer. If your agent tool doesn't resolve `@`
12
+ imports, open node_modules/@viliha/vui-ui/AGENT.md and paste it here.
13
+ -->
14
+
15
+ @node_modules/@viliha/vui-ui/AGENT.md
package/README.md CHANGED
@@ -61,17 +61,26 @@ export function Example() {
61
61
 
62
62
  This package ships an **AI-agent usage guide** at
63
63
  `node_modules/@viliha/vui-ui/AGENT.md` — the standards to follow when generating
64
- UI with VUI (token discipline, reuse-first, page layout, RecordView, a11y, dark
65
- mode). Point your agent at it, or copy it into your repo as `AGENTS.md` so tools
66
- auto-load it.
64
+ UI with VUI (token discipline, reuse-first, page layout, RecordView, forms,
65
+ a11y, dark mode). The quickest way to load it is the shipped
66
+ `CLAUDE.template.md`:
67
+
68
+ ```bash
69
+ cp node_modules/@viliha/vui-ui/CLAUDE.template.md ./CLAUDE.md # Claude Code
70
+ # or ./AGENTS.md for Cursor / Copilot
71
+ ```
72
+
73
+ It's a one-line `@import` of `AGENT.md`, so the rules stay in one place. Prefer a
74
+ verbatim copy? `cp node_modules/@viliha/vui-ui/AGENT.md AGENTS.md`.
67
75
 
68
76
  ## Components
69
77
 
70
- `avatar` · `badge` · `button` · `card` · `chart` (themed Recharts wrapper) ·
71
- `checkbox` · `command-palette` (⌘K launcher) · `dialog` · `confirm-dialog` ·
72
- `dropdown-menu` · `input` · `kbd` (key caps + `Shortcut`) · `menu` ·
73
- `required-mark` · `select` · `table` · `record-view` (the full datatable) · plus
74
- the `utils` (`cn`) helper and the `theme.css` design tokens.
78
+ `avatar` · `badge` · `breadcrumbs` · `button` · `card` · `chart` (themed Recharts
79
+ wrapper) · `checkbox` · `command-palette` (⌘K launcher) · `dialog` ·
80
+ `confirm-dialog` · `dropdown-menu` · `input` · `kbd` (key caps + `Shortcut`) ·
81
+ `menu` · `required-mark` · `select` · `table` · `record-view` (the full datatable
82
+ + `RecordForm`) · plus the `utils` (`cn`) helper and the `theme.css` design
83
+ tokens.
75
84
 
76
85
  ## Theming
77
86
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@viliha/vui-ui",
3
- "version": "1.1.2",
3
+ "version": "1.1.4",
4
4
  "description": "Vui UI — a clean, token-driven React admin/CRM component library built on Tailwind CSS v4, shadcn-style patterns, and Radix Icons. Ships as TypeScript source (Just-in-Time), compiled by the consuming app.",
5
5
  "license": "MIT",
6
6
  "author": "Suman Bonakurthi",
@@ -33,7 +33,8 @@
33
33
  "src",
34
34
  "!src/**/*.test.ts",
35
35
  "!src/**/*.test.tsx",
36
- "AGENT.md"
36
+ "AGENT.md",
37
+ "CLAUDE.template.md"
37
38
  ],
38
39
  "exports": {
39
40
  "./theme.css": "./src/theme.css",
@@ -334,6 +334,12 @@ export function RecordView<T extends { id: RowId }>({
334
334
  const tableFields = fields.filter((f) => !f.hideInTable);
335
335
  const visibleFields = tableFields.filter((f) => !hidden.has(f.key));
336
336
 
337
+ // The primary "Name" column renders the record's name field, which is hidden
338
+ // as a regular column (hideInTable) because it shows here. Mirror its
339
+ // required mark so a mandatory name shows `*` like every other column.
340
+ // ponytail: name field = a required hideInTable field (the app convention).
341
+ const nameRequired = fields.some((f) => f.hideInTable && f.required);
342
+
337
343
  const nameWidth = colWidths[NAME_COL] ?? NAME_DEFAULT_W;
338
344
  const totalWidth =
339
345
  CHECKBOX_W +
@@ -1057,6 +1063,7 @@ export function RecordView<T extends { id: RowId }>({
1057
1063
  <DEFAULT_FIELD_ICON className="size-3.5 shrink-0 text-foreground" />
1058
1064
  )}
1059
1065
  Name
1066
+ {nameRequired && <RequiredMark />}
1060
1067
  </span>
1061
1068
  {resizeHandle(NAME_COL, "Name")}
1062
1069
  </TableHead>
@@ -1468,11 +1475,14 @@ function RecordDetailPanel<T extends { id: RowId }>({
1468
1475
  </h3>
1469
1476
  <dl className="divide-y divide-border">
1470
1477
  {groupFields.map((f) => (
1478
+ // Label, icon, required mark and control share one baseline —
1479
+ // vertically centered. ponytail: a wrapped textarea grows down and
1480
+ // the label centers against it; acceptable for the single-line norm.
1471
1481
  <div
1472
1482
  key={f.key}
1473
- className="flex items-start gap-3 px-3 py-3 leading-relaxed"
1483
+ className="flex items-center gap-3 px-3 py-3 leading-relaxed"
1474
1484
  >
1475
- <dt className="flex w-28 shrink-0 items-center gap-1.5 pt-1.5 text-muted-foreground">
1485
+ <dt className="flex w-28 shrink-0 items-center gap-1.5 text-muted-foreground">
1476
1486
  {f.icon && (
1477
1487
  <f.icon className="size-3.5 text-[var(--button-primary)]" />
1478
1488
  )}
@@ -1481,7 +1491,7 @@ function RecordDetailPanel<T extends { id: RowId }>({
1481
1491
  </dt>
1482
1492
  <dd className="min-w-0 flex-1">
1483
1493
  {f.render ? (
1484
- <div className="pt-0.5">{f.render(draft)}</div>
1494
+ <div>{f.render(draft)}</div>
1485
1495
  ) : !readOnly && f.editable ? (
1486
1496
  <textarea
1487
1497
  value={String(draft[f.key as keyof T] ?? "")}
@@ -1499,7 +1509,7 @@ function RecordDetailPanel<T extends { id: RowId }>({
1499
1509
  )}
1500
1510
  />
1501
1511
  ) : (
1502
- <span className="block whitespace-pre-wrap break-words px-2 pt-1.5">
1512
+ <span className="block whitespace-pre-wrap break-words px-2 py-1.5">
1503
1513
  {String(draft[f.key as keyof T] ?? "") || (
1504
1514
  <span className="text-muted-foreground">—</span>
1505
1515
  )}