@nurix/etna 0.20.1 → 0.20.3
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/data/catalog/rules/testing.md +13 -9
- package/data/harness-index.json +1 -1
- package/data/harnesses/code/CLAUDE.md +5 -1
- package/data/harnesses/code/agents/bookkeeper.md +1 -1
- package/data/harnesses/code/agents/issue-bridge.md +16 -0
- package/data/harnesses/code/agents/maintenance.md +36 -3
- package/data/harnesses/code/docs/README.md +1 -1
- package/data/harnesses/code/docs/history/backlog.md +1 -1
- package/data/harnesses/code/docs/structure.md +2 -2
- package/data/harnesses/code/harness.json +12 -2
- package/data/harnesses/code/hooks/awareness.mjs +75 -14
- package/data/harnesses/code/hooks/compliance.mjs +25 -17
- package/data/harnesses/code/hooks/lib/exempt.mjs +7 -5
- package/data/harnesses/code/hooks/lib/frozen.mjs +9 -6
- package/data/harnesses/code/hooks/lib/ledger.mjs +26 -4
- package/data/harnesses/code/hooks/lib/ownership.mjs +73 -2
- package/data/harnesses/code/hooks/lib/plans.mjs +2 -2
- package/data/harnesses/code/hooks/lib/repo.mjs +22 -0
- package/data/harnesses/code/hooks/lib/state.mjs +38 -2
- package/data/harnesses/code/hooks/lib/sweep.mjs +37 -15
- package/data/harnesses/code/rules/testing.md +13 -9
- package/data/harnesses/code/skills/codegraph/SKILL.md +57 -0
- package/data/harnesses/code/skills/design/components/charts.md +1 -1
- package/data/harnesses/code/skills/design/components/collections.md +3 -3
- package/data/harnesses/code/skills/design/components/index.md +98 -98
- package/data/harnesses/code/skills/design/components/layout.md +1 -1
- package/data/harnesses/code/skills/design/components/media.md +1 -1
- package/data/harnesses/code/skills/design/components/motion.md +1 -1
- package/data/harnesses/code/skills/design/components/navigation.md +2 -2
- package/data/harnesses/code/skills/design/components/overlays.md +1 -1
- package/data/harnesses/code/skills/design/components/setup.md +3 -3
- package/data/harnesses/code/skills/design/components/typography.md +2 -2
- package/data/harnesses/code/skills/documentation/SKILL.md +12 -5
- package/data/harnesses/code/skills/documentation/references/frontmatter.md +29 -4
- package/data/harnesses/code/skills/documentation/templates/behavioral-checklist.md +18 -1
- package/data/harnesses/code/skills/documentation/templates/feature.md +1 -0
- package/data/harnesses/code/skills/documentation/templates/plan.md +2 -0
- package/data/harnesses/code/skills/documentation/templates/ux-behavior.md +1 -1
- package/data/harnesses/code/skills/issue-bridge/SKILL.md +55 -0
- package/data/harnesses/code/skills/issue-bridge/references/trackers/github.md +37 -0
- package/data/harnesses/code/skills/issue-bridge/references/trackers/jira.md +40 -0
- package/data/harnesses/code/skills/issue-bridge/references/trackers/linear.md +37 -0
- package/data/harnesses/code/skills/testing/SKILL.md +20 -4
- package/data/harnesses/delivery/agents/maintenance.md +36 -3
- package/data/harnesses/delivery/harness.json +4 -2
- package/data/harnesses/delivery/skills/documentation/SKILL.md +12 -5
- package/data/harnesses/delivery/skills/documentation/references/frontmatter.md +29 -4
- package/data/harnesses/delivery/skills/documentation/templates/behavioral-checklist.md +18 -1
- package/data/harnesses/delivery/skills/documentation/templates/feature.md +1 -0
- package/data/harnesses/delivery/skills/documentation/templates/plan.md +2 -0
- package/data/harnesses/delivery/skills/documentation/templates/ux-behavior.md +1 -1
- package/data/harnesses/discover/harness.json +2 -0
- package/data/harnesses/discussion/harness.json +2 -0
- package/data/harnesses/etna/agents/maintenance.md +36 -3
- package/data/harnesses/etna/harness.json +4 -2
- package/data/harnesses/etna/rules/testing.md +13 -9
- package/data/harnesses/etna/skills/documentation/SKILL.md +12 -5
- package/data/harnesses/etna/skills/documentation/references/frontmatter.md +29 -4
- package/data/harnesses/etna/skills/documentation/templates/behavioral-checklist.md +18 -1
- package/data/harnesses/etna/skills/documentation/templates/feature.md +1 -0
- package/data/harnesses/etna/skills/documentation/templates/plan.md +2 -0
- package/data/harnesses/etna/skills/documentation/templates/ux-behavior.md +1 -1
- package/data/harnesses/hr/harness.json +2 -0
- package/data/harnesses/kb-agi/harness.json +2 -0
- package/lib/install/plan.mjs +22 -1
- package/package.json +2 -2
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: codegraph
|
|
3
|
+
requires-tool: codegraph
|
|
4
|
+
description: Query the codegraph index before reading source. An LLM-first codebase index (symbols, call references, git history, co-change coupling, ownership) answering whole questions in one call. Use it to localize, scope, and assess blast radius on this repository; use grep/read for string literals, mechanism, and data flow — the skill states which is which. Applies to any task that starts with "where is", "who calls", "what changed", "who owns", "what breaks", or "is this tested".
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
# codegraph — the index-first method
|
|
8
|
+
|
|
9
|
+
**If the tool is absent** (`codegraph --version` fails): do not stall. Read `.claude/state/decisions.tsv` for `tool.codegraph`.
|
|
10
|
+
|
|
11
|
+
- **`declined`** — fall back to the cold method (grep, targeted reads, `git log`) **silently**. Do not mention the tool, do not re-offer. The user has answered.
|
|
12
|
+
- **undecided** (no file, no key, or anything unrecognised) — fall back to the cold method *and* make the offer **once**: this repository would answer "where is / who calls / what changed / who owns" from an index instead of a grep sweep; install with `npm install -g @nurix/codegraph`, then `codegraph index`. **Ask, never act** — a global npm install modifies the machine, and indexing writes to `~/.codegraph`. Record the answer with `recordDecision` either way, so the question is asked at most once per repo per machine.
|
|
13
|
+
- **`accepted` but the binary is gone** — treat as undecided; a failed or removed install is not a standing yes.
|
|
14
|
+
|
|
15
|
+
**A failed install is `absent`, not an error to retry.** Global installs fail on machines without permission; say so once, fall back, and move on.
|
|
16
|
+
|
|
17
|
+
**An explicit invocation overrides a stored decline.** If the user asks for this skill by name, honour it and re-offer — "stop asking" must never become "never usable".
|
|
18
|
+
|
|
19
|
+
**If the repository is not indexed** (a query answers `UNAVAILABLE: this repository has not been indexed yet`), that is the tool degrading correctly, not a failure: offer `codegraph index` under the same ask-first rule. The SessionStart probe deliberately does **not** claim index freshness — it can only see the binary — so this is where index state is actually established.
|
|
20
|
+
|
|
21
|
+
Everything below assumes the tool is present and the repository indexed.
|
|
22
|
+
|
|
23
|
+
The `codegraph` CLI is on PATH and defaults to the git root of the working directory — inside this repository, no flags are needed. The index is prebuilt; `codegraph projects` shows freshness (a `[STALE]` marker means HEAD moved since indexing — refresh with `codegraph index --commits 30000`, ~40s). Every answer states its own confidence per section (`CERTAIN` / `INFERRED` / `UNRESOLVED`), announces anything the token budget dropped, and says what an empty section means. Trust those labels.
|
|
24
|
+
|
|
25
|
+
## The method order
|
|
26
|
+
|
|
27
|
+
Localize through the index **before** opening any file, in this order; then read only the files it points at.
|
|
28
|
+
|
|
29
|
+
1. **`codegraph find <fragment>`** — symbols and file paths by name fragment. The entry point when you only have issue vocabulary. Symbol names only — it will never match string literals, dict keys, or SQL fragments (grep for those, without shame).
|
|
30
|
+
2. **`codegraph where-defined <symbol>`** / **`codegraph outline <file>`** — pin the definition; map a big file. `outline` turns a 100+ declaration file into a navigable, line-numbered list — use it instead of reading god files blind. On a large file add `--budget 0` (see traps).
|
|
31
|
+
3. **`codegraph who-calls <symbol>`** / **`codegraph impact <target>`** — callers, and blast radius (static reach + historical co-change reach, reported separately on purpose: they disagree, and the disagreement is information).
|
|
32
|
+
4. **`codegraph churn --days N --path <dir>`** · **`coupling --path <file>`** · **`owners <path>`** · **`tests-covering <file>`** — the history layer: what's hot, what changes together (including *hidden coupling* — co-change with no static reference, the one fact reading code cannot reveal), who knows this area and how recently, which test file historically guards this file.
|
|
33
|
+
5. **`codegraph god-objects --minSymbols 30`** / **`hotspots`** / **`overview`** — repo-scale orientation and risk.
|
|
34
|
+
|
|
35
|
+
Then read, with `sed -n` ranges at the lines the index gave you. The index does discovery; reading does diagnosis. Add `--json` when a wrapper needs structure.
|
|
36
|
+
|
|
37
|
+
There is also **`codegraph blame <file> [--line N]`** — the commits behind a file or one specific line, answered by git at query time; **`codegraph refs <name>`** — the data-reference layer: where a name is used as a dict/object key, attribute/field, import, or type annotation, with read/write direction, and a cross-language flag when the same name spans Python and TypeScript files (this answers "who reads `x_axis_sort`" / "who writes `chart.query_context`" in one call — the questions that used to need grep); and **`codegraph drift`** — near-duplicate function bodies crossed with co-change history: similar code whose files never change together is an unfinished refactor waiting to disagree. `who-calls` additionally tabulates which keyword arguments each call site passes, so "which call sites omit this option" is one query.
|
|
38
|
+
|
|
39
|
+
## The boundary — what the index cannot answer (fall back immediately, don't retry)
|
|
40
|
+
|
|
41
|
+
- **Free-text string literals** (SQL templates, prose, format strings) — grep. Identifier-shaped keys and fields ARE indexed (`refs <name>`); anything longer or with spaces is not.
|
|
42
|
+
- **Framework reflection** (Marshmallow `@post_load`, signal handlers, `appbuilder.add_api(Cls)` registration) — invisible to call edges. Bare decorator *application* (`@has_access_api`) IS indexed as a reference; what the decorator does and when it runs is not.
|
|
43
|
+
- **Data flow and mechanism** ("does this value reach that function", "what order do these run in") — always reading work.
|
|
44
|
+
|
|
45
|
+
Indexed symbol forms include statement declarations, `const X = () => {}`, named function expressions inside wrapper calls (`typedMemo(function DataTable() {})`), TS/JS class fields, and Python class-body fields (`is_dttm = Column(...)`); nested members render as `Parent › member` in `outline`.
|
|
46
|
+
|
|
47
|
+
## Traps (each cost a prior agent real time)
|
|
48
|
+
|
|
49
|
+
- **Bare-name collision.** Call references match by name, not resolved binding. When a name has several definitions, `who-calls` lists every candidate and says so in its subject line — read that section before trusting the call sites, and pass `--scope <path-fragment>` (also on `find`, `where-defined`, `impact`) to narrow to a package.
|
|
50
|
+
- **`codegraph functions` lists the CLI's own functions**, not the repository's. For repo functions use `find`. An explicit `--limit` lifts the default token budget, so a full `outline` needs no `--budget 0` incantation (an explicit `--budget` still wins).
|
|
51
|
+
- **Churn windows.** `churn --days 180` returning nothing does not mean quiet history — widen the window. Directory-scope churn ranks by raw commit count and buries small-but-critical files; for specific files use `owners`/`coupling` per file.
|
|
52
|
+
- **`tests-covering` is co-change evidence, not executed coverage** — it names the right test file to open; it cannot say the specific scenario is tested.
|
|
53
|
+
- **Coupling on a busy file has a noise tail** — partners at <15% shared commits are usually PR-cohabitation, not real coupling. Verify a partner with a read before adding it to a touch-list.
|
|
54
|
+
|
|
55
|
+
## Division of truth in this repository
|
|
56
|
+
|
|
57
|
+
`docs/` is the source of truth for **intent** — what a feature is for, its invariants, decisions, vocabulary. codegraph is the source of truth for **facts** — where things are, who calls what, what changed together, who owns what. Never copy live facts (caller counts, churn numbers) into docs as if permanent; never ask the index for intent.
|
|
@@ -12,7 +12,7 @@ Three tiers, all consuming the canonical `ChartSeries[]` / `ChartPoint` data con
|
|
|
12
12
|
|
|
13
13
|
## Spark
|
|
14
14
|
|
|
15
|
-
Tier-0 inline mark — no axes, no chrome. Import from `@nurix/components/spark`.
|
|
15
|
+
Tier-0 inline mark — no axes, no chrome. Import from `@nurix/components/element/spark`.
|
|
16
16
|
|
|
17
17
|
**Props:** `series` (`ChartSeries[]` or plain `number[]`), `type` [line|bar|pie], `filled`, `fillOpacity`, `strokeWidth` (line), `gap` (bar), `width`, `height`, `useTokens` (default false: self-contained oklch; true: `--chart-N` tokens)
|
|
18
18
|
|
|
@@ -47,7 +47,7 @@ Define table columns using the `defineColumn()` helper.
|
|
|
47
47
|
- `display` - `{ width, sortable }` (width optional — columns are fluid when unset)
|
|
48
48
|
- `cell` - Custom render function `(row) => ReactNode`
|
|
49
49
|
|
|
50
|
-
For full control, pass your own `cell()` or import a renderer from `@nurix/components/table` (`StatusPill`, `SelectCell`, etc.) as an escape hatch.
|
|
50
|
+
For full control, pass your own `cell()` or import a renderer from `@nurix/components/block/table` (`StatusPill`, `SelectCell`, etc.) as an escape hatch.
|
|
51
51
|
|
|
52
52
|
### Metadata options by component
|
|
53
53
|
|
|
@@ -64,7 +64,7 @@ For full control, pass your own `cell()` or import a renderer from `@nurix/compo
|
|
|
64
64
|
### Example
|
|
65
65
|
|
|
66
66
|
```tsx
|
|
67
|
-
import { defineColumn } from "@nurix/components/table";
|
|
67
|
+
import { defineColumn } from "@nurix/components/block/table";
|
|
68
68
|
|
|
69
69
|
const columns = [
|
|
70
70
|
defineColumn({
|
|
@@ -100,7 +100,7 @@ const columns = [
|
|
|
100
100
|
|
|
101
101
|
## PageHeader
|
|
102
102
|
|
|
103
|
-
Config-driven page masthead with an optional stat ledger — router-agnostic (the consumer owns navigation). Import from `@nurix/components/page-header`.
|
|
103
|
+
Config-driven page masthead with an optional stat ledger — router-agnostic (the consumer owns navigation). Import from `@nurix/components/block/page-header`.
|
|
104
104
|
|
|
105
105
|
**Props:** `title`, `eyebrow` (breadcrumb segments — strings or linked `Crumb`s; last is the current page), `description`, `statusSlot`, `actions`, `stats` (`Stat[]` ledger), `back` (`BackLink`), `onBack`, `onNavigate` (fired with a crumb's/stat's `href`), `statsAlign` [left|right], `tall`
|
|
106
106
|
|
|
@@ -10,49 +10,49 @@ Columns: `concept` (the composable idea) · `category` (which deep reference cov
|
|
|
10
10
|
|
|
11
11
|
```csv
|
|
12
12
|
concept,category,nurix,shadcn,fallback
|
|
13
|
-
button,inputs,Button (button),Button,"native <button>, variants via class, focus-visible ring"
|
|
14
|
-
text-input,inputs,"Input (input) — onSave commit, regex validator",Input,"<input type=text>, commit on blur/Enter"
|
|
15
|
-
number-input,inputs,"NumberInput (number-input) — min/max/step",—,"<input inputmode=numeric>, clamp on commit, Escape reverts"
|
|
16
|
-
textarea,inputs,"Textarea (textarea) — Cmd/Ctrl+Enter commits",Textarea,"<textarea>, blur commits, Escape resets draft"
|
|
17
|
-
checkbox,inputs,Checkbox (checkbox),Checkbox,"<input type=checkbox> + label, indeterminate via JS"
|
|
18
|
-
switch,inputs,Switch (switch),Switch,"role=switch button, aria-checked, Space toggles"
|
|
19
|
-
radio-group,inputs,"RadioGroup + card/segmented variants (radio-group)",RadioGroup,"fieldset of <input type=radio>, arrow-key roving focus"
|
|
20
|
-
select,inputs,"Select — searchable, multi, async (select)","Select; Combobox (Popover + Command)","<select> or listbox popover, typeahead, option objects not raw values"
|
|
21
|
-
native-select,inputs,"Select* Radix family (native-select)",Select,"plain <select> behind a styled trigger"
|
|
22
|
-
date-picker,inputs,DatePicker (date-picker),Date Picker (Calendar + Popover),"<input type=date> or calendar popover, ISO value"
|
|
23
|
-
date-range-picker,inputs,"DateRangePicker — presets sidebar (date-
|
|
24
|
-
calendar,inputs,"Calendar (calendar) — react-day-picker",Calendar,"month grid <table>, arrow-key day navigation"
|
|
25
|
-
slider,inputs,Slider (slider),Slider,"<input type=range> with visible value readout"
|
|
26
|
-
rating,inputs,Rating (rating),—,"radio group of icon buttons, half-step optional"
|
|
27
|
-
toggle,inputs,"Toggle · ToggleGroup (toggle, toggle-group)","Toggle, Toggle Group","aria-pressed buttons, single or multiple selection"
|
|
28
|
-
otp-input,inputs,InputOTP (input-otp),Input OTP,"segmented one-char inputs, paste distributes across slots"
|
|
29
|
-
icon-picker,inputs,"IconPicker · Icon (icon-picker)",—,"searchable icon grid in a popover, categorized"
|
|
30
|
-
file-upload,inputs,MediaFilePicker (media-file-picker),—,"<input type=file> + drop zone, previews, size and count caps"
|
|
31
|
-
form-field,inputs,"Cell — label/content/helper/error slots (cell)",Form + FormField (react-hook-form),"label + control + helper in one block, error slot below control"
|
|
13
|
+
button,inputs,Button (element/button),Button,"native <button>, variants via class, focus-visible ring"
|
|
14
|
+
text-input,inputs,"Input (element/input) — onSave commit, regex validator",Input,"<input type=text>, commit on blur/Enter"
|
|
15
|
+
number-input,inputs,"NumberInput (element/number-input) — min/max/step",—,"<input inputmode=numeric>, clamp on commit, Escape reverts"
|
|
16
|
+
textarea,inputs,"Textarea (element/textarea) — Cmd/Ctrl+Enter commits",Textarea,"<textarea>, blur commits, Escape resets draft"
|
|
17
|
+
checkbox,inputs,Checkbox (element/checkbox),Checkbox,"<input type=checkbox> + label, indeterminate via JS"
|
|
18
|
+
switch,inputs,Switch (element/switch),Switch,"role=switch button, aria-checked, Space toggles"
|
|
19
|
+
radio-group,inputs,"RadioGroup + card/segmented variants (element/radio-group)",RadioGroup,"fieldset of <input type=radio>, arrow-key roving focus"
|
|
20
|
+
select,inputs,"Select — searchable, multi, async (element/select)","Select; Combobox (Popover + Command)","<select> or listbox popover, typeahead, option objects not raw values"
|
|
21
|
+
native-select,inputs,"Select* Radix family (element/native-select)",Select,"plain <select> behind a styled trigger"
|
|
22
|
+
date-picker,inputs,DatePicker (compound/date-picker),Date Picker (Calendar + Popover),"<input type=date> or calendar popover, ISO value"
|
|
23
|
+
date-range-picker,inputs,"DateRangePicker — presets sidebar (compound/date-picker)",—,"two bound date inputs, partial selection reverts on close"
|
|
24
|
+
calendar,inputs,"Calendar (element/calendar) — react-day-picker",Calendar,"month grid <table>, arrow-key day navigation"
|
|
25
|
+
slider,inputs,Slider (element/slider),Slider,"<input type=range> with visible value readout"
|
|
26
|
+
rating,inputs,Rating (element/rating),—,"radio group of icon buttons, half-step optional"
|
|
27
|
+
toggle,inputs,"Toggle · ToggleGroup (element/toggle, element/toggle-group)","Toggle, Toggle Group","aria-pressed buttons, single or multiple selection"
|
|
28
|
+
otp-input,inputs,InputOTP (compound/input-otp),Input OTP,"segmented one-char inputs, paste distributes across slots"
|
|
29
|
+
icon-picker,inputs,"IconPicker · Icon (compound/icon-picker)",—,"searchable icon grid in a popover, categorized"
|
|
30
|
+
file-upload,inputs,MediaFilePicker (compound/media-file-picker),—,"<input type=file> + drop zone, previews, size and count caps"
|
|
31
|
+
form-field,inputs,"Cell — label/content/helper/error slots (compound/cell)",Form + FormField (react-hook-form),"label + control + helper in one block, error slot below control"
|
|
32
32
|
form-validation,inputs,,Form (react-hook-form),"form element with submit-time validation and inline field errors"
|
|
33
33
|
rich-text-editor,inputs,,—,"@tiptap/react editor with toolbar and markdown shortcuts"
|
|
34
34
|
code-editor,inputs,,—,"@monaco-editor/react, mono, optional read-only diff mode"
|
|
35
|
-
modal-dialog,overlays,Dialog (dialog),Dialog,"<dialog> or fixed layer, focus trap, ESC closes, header→body→footer"
|
|
36
|
-
confirm-dialog,overlays,"Dialog variant=danger — non-dismissible (dialog)",Alert Dialog,"modal with explicit confirm/cancel, no outside-click dismiss"
|
|
37
|
-
side-panel,overlays,Sheet (sheet),Sheet,"fixed aside, focus-trapped, ESC closes, interruptible slide"
|
|
38
|
-
bottom-drawer,overlays,Sheet side=bottom (sheet),Drawer (vaul),"fixed bottom panel spanning full width"
|
|
39
|
-
command-palette,overlays,Command (command),Command (cmdk),"filtered list in a dialog, ⌘K opens, arrow-key + Enter"
|
|
40
|
-
dropdown-menu,overlays,DropdownMenu (dropdown-menu),Dropdown Menu,"role=menu under a trigger, arrow-key nav, outside click closes"
|
|
41
|
-
context-menu,overlays,ContextMenu (context-menu),Context Menu,"right-click menu at pointer position"
|
|
42
|
-
popover,overlays,Popover (popover),Popover,"anchored floating panel, dismiss on outside/ESC"
|
|
43
|
-
hover-card,overlays,HoverCard (
|
|
44
|
-
tooltip,overlays,Tooltip (tooltip),Tooltip,"short hint on hover/focus, never load-bearing content"
|
|
45
|
-
data-table,collections,"Table + defineColumn (table)","<Table> + TanStack Table","semantic <table>, sticky header, tabular-nums, real pagination, status chips"
|
|
46
|
-
table-primitives,collections,UiTable* family (ui-table),Table,"bare styled <table>/<thead>/<tbody> parts"
|
|
47
|
-
list,collections,"List + ListToolbar + ListPagination (list)",—,"<ul> of rows with toolbar and pager"
|
|
48
|
-
record-header,collections,"Header — config-driven (header)",—,"page-top block: breadcrumbs, title, status bar, actions"
|
|
49
|
-
page-header-stats,collections,"PageHeader — Stat/Crumb/BackLink (page-header)",—,"title row + KPI strip + back link"
|
|
35
|
+
modal-dialog,overlays,Dialog (compound/dialog),Dialog,"<dialog> or fixed layer, focus trap, ESC closes, header→body→footer"
|
|
36
|
+
confirm-dialog,overlays,"Dialog variant=danger — non-dismissible (compound/dialog)",Alert Dialog,"modal with explicit confirm/cancel, no outside-click dismiss"
|
|
37
|
+
side-panel,overlays,Sheet (block/sheet),Sheet,"fixed aside, focus-trapped, ESC closes, interruptible slide"
|
|
38
|
+
bottom-drawer,overlays,Sheet side=bottom (block/sheet),Drawer (vaul),"fixed bottom panel spanning full width"
|
|
39
|
+
command-palette,overlays,Command (compound/command),Command (cmdk),"filtered list in a dialog, ⌘K opens, arrow-key + Enter"
|
|
40
|
+
dropdown-menu,overlays,DropdownMenu (compound/dropdown-menu),Dropdown Menu,"role=menu under a trigger, arrow-key nav, outside click closes"
|
|
41
|
+
context-menu,overlays,ContextMenu (compound/context-menu),Context Menu,"right-click menu at pointer position"
|
|
42
|
+
popover,overlays,Popover (element/popover),Popover,"anchored floating panel, dismiss on outside/ESC"
|
|
43
|
+
hover-card,overlays,HoverCard (element/popover),Hover Card,"preview panel on hover intent, delayed open/close"
|
|
44
|
+
tooltip,overlays,Tooltip (element/tooltip),Tooltip,"short hint on hover/focus, never load-bearing content"
|
|
45
|
+
data-table,collections,"Table + defineColumn (block/table)","<Table> + TanStack Table","semantic <table>, sticky header, tabular-nums, real pagination, status chips"
|
|
46
|
+
table-primitives,collections,UiTable* family (block/ui-table),Table,"bare styled <table>/<thead>/<tbody> parts"
|
|
47
|
+
list,collections,"List + ListToolbar + ListPagination (block/list)",—,"<ul> of rows with toolbar and pager"
|
|
48
|
+
record-header,collections,"Header — config-driven (block/app-header)",—,"page-top block: breadcrumbs, title, status bar, actions"
|
|
49
|
+
page-header-stats,collections,"PageHeader — Stat/Crumb/BackLink (block/page-header)",—,"title row + KPI strip + back link"
|
|
50
50
|
gantt-timeline,collections,GanttChart (activity-timeline),—,"time-scaled task rows, date axis, horizontal scroll"
|
|
51
|
-
changes-feed,collections,ChangesList (changes-list),—,"grouped change-history feed, entity + operation labels"
|
|
52
|
-
message-thread,collections,"Message family + MessageScroller (message, message-scroller)",—,"scrolling feed pinned to bottom, jump-to-new button"
|
|
53
|
-
chat-bubble,collections,BubbleGroup + Bubble (bubble),—,"aligned bubble rows with reactions row"
|
|
54
|
-
attachment,collections,Attachment family (attachment),—,"file card: media, title, actions, error state, dashed idle border"
|
|
55
|
-
thread-marker,collections,"Marker — separator/border variants (marker)",—,"inline separator row with icon and label"
|
|
51
|
+
changes-feed,collections,ChangesList (block/changes-list),—,"grouped change-history feed, entity + operation labels"
|
|
52
|
+
message-thread,collections,"Message family + MessageScroller (compound/message, block/message-scroller)",—,"scrolling feed pinned to bottom, jump-to-new button"
|
|
53
|
+
chat-bubble,collections,BubbleGroup + Bubble (element/bubble),—,"aligned bubble rows with reactions row"
|
|
54
|
+
attachment,collections,Attachment family (compound/attachment),—,"file card: media, title, actions, error state, dashed idle border"
|
|
55
|
+
thread-marker,collections,"Marker — separator/border variants (element/marker)",—,"inline separator row with icon and label"
|
|
56
56
|
json-viewer,collections,,—,"react18-json-view collapsible tree, mono"
|
|
57
57
|
virtualized-list,collections,,—,"react-window fixed-row virtualization for 1k+ rows"
|
|
58
58
|
kanban-board,collections,,—,"flex columns of cards, @dnd-kit drag between columns, per-column count"
|
|
@@ -60,29 +60,29 @@ event-calendar,collections,,—,"month/week grid of events, today marker, overfl
|
|
|
60
60
|
description-list,collections,,—,"<dl> two-column key/value grid, tabular values"
|
|
61
61
|
filter-toolbar,collections,,—,"row of faceted filter chips + clear-all + result count"
|
|
62
62
|
vertical-timeline,collections,,—,"ordered event list with time rail and node markers"
|
|
63
|
-
sidebar,navigation,"Sidebar family + Brand/Switcher/ItemGroup/UserMenu/Callout (sidebar)",Sidebar,"fixed <nav>: brand + icon sections + badges + user footer, collapsible to icons"
|
|
64
|
-
file-tree,navigation,FileTree (sidebar),—,"nested tree with disclosure carets, keyboard nav"
|
|
65
|
-
breadcrumb,navigation,Breadcrumb (breadcrumb),Breadcrumb,"<nav aria-label=breadcrumb>, current page unlinked"
|
|
66
|
-
tabs,navigation,Tabs (tabs),Tabs,"role=tablist, arrow-key switching, one panel per tab"
|
|
67
|
-
pagination,navigation,Pagination (pagination),Pagination,"page buttons + prev/next, aria-current on active page"
|
|
68
|
-
navbar,navigation,Navbar (
|
|
69
|
-
navigation-menu,navigation,NavigationMenu (navigation-menu),Navigation Menu,"top-level nav with flyout panels"
|
|
70
|
-
menubar,navigation,Menubar (menubar),Menubar,"desktop-app menu strip with full keyboard model"
|
|
71
|
-
slide-out-menu,navigation,SlideOutMenu (slide-out-menu),—,"off-canvas nav panel for narrow viewports"
|
|
72
|
-
icon-rail,navigation,VerticalIconBar (vertical-icon-bar),—,"narrow vertical icon strip with tooltips"
|
|
63
|
+
sidebar,navigation,"Sidebar family + Brand/Switcher/ItemGroup/UserMenu/Callout (block/sidebar)",Sidebar,"fixed <nav>: brand + icon sections + badges + user footer, collapsible to icons"
|
|
64
|
+
file-tree,navigation,FileTree (block/sidebar),—,"nested tree with disclosure carets, keyboard nav"
|
|
65
|
+
breadcrumb,navigation,Breadcrumb (compound/breadcrumb),Breadcrumb,"<nav aria-label=breadcrumb>, current page unlinked"
|
|
66
|
+
tabs,navigation,Tabs (compound/tabs),Tabs,"role=tablist, arrow-key switching, one panel per tab"
|
|
67
|
+
pagination,navigation,Pagination (compound/pagination),Pagination,"page buttons + prev/next, aria-current on active page"
|
|
68
|
+
navbar,navigation,Navbar (block/app-header),—,"horizontal top <nav> with links and actions"
|
|
69
|
+
navigation-menu,navigation,NavigationMenu (compound/navigation-menu),Navigation Menu,"top-level nav with flyout panels"
|
|
70
|
+
menubar,navigation,Menubar (compound/menubar),Menubar,"desktop-app menu strip with full keyboard model"
|
|
71
|
+
slide-out-menu,navigation,SlideOutMenu (block/slide-out-menu),—,"off-canvas nav panel for narrow viewports"
|
|
72
|
+
icon-rail,navigation,VerticalIconBar (block/vertical-icon-bar),—,"narrow vertical icon strip with tooltips"
|
|
73
73
|
stepper,navigation,,—,"ordered steps with done/current/todo states, aria-current=step"
|
|
74
|
-
alert,feedback,Alert (alert),Alert,"role=alert block, tone via border + icon"
|
|
75
|
-
empty-state,feedback,EmptyState (empty-state),Empty,"icon + heading + motivation line + primary action"
|
|
76
|
-
error-boundary,feedback,ErrorBoundary (error-boundary),—,"React boundary rendering a retry block"
|
|
77
|
-
not-found,feedback,NotFound (
|
|
78
|
-
skeleton,feedback,Skeleton (skeleton),Skeleton,"pulsing placeholder matching the final layout"
|
|
79
|
-
loader,feedback,Loader (loader),Spinner,"centered spinner with optional label"
|
|
80
|
-
text-spinner,feedback,"Braille (braille) · spinner frames (
|
|
81
|
-
progress,feedback,Progress (progress),Progress,"role=progressbar with aria-valuenow"
|
|
82
|
-
toast,feedback,Toaster (sonner),Sonner,"stacked corner notifications, auto-dismiss, action slot"
|
|
83
|
-
typing-indicator,feedback,TypingIndicator (typing-indicator),—,"three-dot pulse row"
|
|
84
|
-
sparkline,charts,"Spark — line|bar|pie (spark) · Sparkline (sparkline)",—,"inline no-axis SVG mark, token or self-contained color"
|
|
85
|
-
inline-bar,charts,BarGraph (bar-graph),—,"compact bar SVG with skeleton, token colors"
|
|
74
|
+
alert,feedback,Alert (element/alert),Alert,"role=alert block, tone via border + icon"
|
|
75
|
+
empty-state,feedback,EmptyState (compound/empty-state),Empty,"icon + heading + motivation line + primary action"
|
|
76
|
+
error-boundary,feedback,ErrorBoundary (lib/error-boundary),—,"React boundary rendering a retry block"
|
|
77
|
+
not-found,feedback,NotFound (compound/empty-state),—,"404 block with a way back"
|
|
78
|
+
skeleton,feedback,Skeleton (element/skeleton),Skeleton,"pulsing placeholder matching the final layout"
|
|
79
|
+
loader,feedback,Loader (element/loader),Spinner,"centered spinner with optional label"
|
|
80
|
+
text-spinner,feedback,"Braille (braille) · spinner frames (element/loader)",—,"animated unicode frames inline with text"
|
|
81
|
+
progress,feedback,Progress (element/progress),Progress,"role=progressbar with aria-valuenow"
|
|
82
|
+
toast,feedback,Toaster (compound/sonner),Sonner,"stacked corner notifications, auto-dismiss, action slot"
|
|
83
|
+
typing-indicator,feedback,TypingIndicator (element/typing-indicator),—,"three-dot pulse row"
|
|
84
|
+
sparkline,charts,"Spark — line|bar|pie (element/spark) · Sparkline (sparkline)",—,"inline no-axis SVG mark, token or self-contained color"
|
|
85
|
+
inline-bar,charts,BarGraph (element/bar-graph),—,"compact bar SVG with skeleton, token colors"
|
|
86
86
|
inline-line,charts,LineGraph (line-graph),—,"compact line SVG with skeleton"
|
|
87
87
|
pie-donut,charts,"PieGraph — pie|half-pie|doughnut|half-doughnut (pie-graph)",—,"SVG arcs, max ~6 slices, center slot in doughnut"
|
|
88
88
|
segmented-progress,charts,ProgressBar (progress-bar),—,"stacked horizontal segments with legend"
|
|
@@ -100,44 +100,44 @@ matrix-heatmap,charts,MatrixHeatmap + legend/tooltip (heatmap),—,"x-by-y cell
|
|
|
100
100
|
radar,charts,Radar (radar),—,"spider axes with series polygons"
|
|
101
101
|
ring,charts,Ring (ring),—,"segmented circular progress with center info"
|
|
102
102
|
chart-chrome,charts,"ChartEmpty · ChartHoverCard · ChartLegend (chart-primitives)",—,"shared empty/tooltip/legend chrome for inline charts"
|
|
103
|
-
card,layout,Card family (card),Card,"bordered section: header, content, footer"
|
|
103
|
+
card,layout,Card family (block/card),Card,"bordered section: header, content, footer"
|
|
104
104
|
stat-card,layout,Statistics family (statistics),—,"number + comparison + trend + state + door, composable regions"
|
|
105
|
-
accordion,layout,Accordion (accordion),Accordion,"stacked disclosure sections, single or multiple open"
|
|
106
|
-
collapsible,layout,"Collapsible (collapsible) · CollapsiblePanel (
|
|
107
|
-
split-panes,layout,ResizablePanelGroup (resizable),Resizable,"draggable divider panes, keyboard resize"
|
|
108
|
-
scroll-area,layout,ScrollArea (scroll-area),Scroll Area,"styled overflow container, visible-on-hover scrollbar"
|
|
109
|
-
separator,layout,"Separator (separator) · SeparatorWithText (separator
|
|
110
|
-
aspect-ratio,layout,AspectRatio (aspect-ratio),Aspect Ratio,"CSS aspect-ratio box"
|
|
111
|
-
carousel,layout,Carousel (carousel),Carousel,"scroll-snap track with prev/next controls"
|
|
105
|
+
accordion,layout,Accordion (compound/accordion),Accordion,"stacked disclosure sections, single or multiple open"
|
|
106
|
+
collapsible,layout,"Collapsible (element/collapsible) · CollapsiblePanel (compound/accordion)",Collapsible,"button-controlled region with hidden state"
|
|
107
|
+
split-panes,layout,ResizablePanelGroup (block/resizable),Resizable,"draggable divider panes, keyboard resize"
|
|
108
|
+
scroll-area,layout,ScrollArea (element/scroll-area),Scroll Area,"styled overflow container, visible-on-hover scrollbar"
|
|
109
|
+
separator,layout,"Separator (element/separator) · SeparatorWithText (element/separator)",Separator,"<hr>/role=separator, optional centered label"
|
|
110
|
+
aspect-ratio,layout,AspectRatio (element/aspect-ratio),Aspect Ratio,"CSS aspect-ratio box"
|
|
111
|
+
carousel,layout,Carousel (compound/carousel),Carousel,"scroll-snap track with prev/next controls"
|
|
112
112
|
bento-grid,layout,BentoGrid + BentoCard (bento-grid),—,"asymmetric feature grid with spanning cells"
|
|
113
|
-
editable-card,layout,EditableCard (editable-card),—,"card with edit-in-place body and commit footer"
|
|
114
|
-
drag-reorder,layout,Sortable family (sortable),—,"dnd-kit list reorder, keyboard sortable, drag overlay ghost"
|
|
115
|
-
text,typography,Text (text),Typography,"semantic p/span with size and weight scale"
|
|
116
|
-
badge,typography,Badge (badge),Badge,"small status pill, tokenized tone"
|
|
117
|
-
chip,typography,"Chip (chip) · Option display (select)",—,"removable tag, optional color dot"
|
|
118
|
-
code,typography,Code (code),—,"inline <code>, mono"
|
|
119
|
-
kbd,typography,Kbd (kbd),Kbd,"<kbd> keycap"
|
|
120
|
-
label,typography,Label (label),Label,"<label for> bound to a control"
|
|
121
|
-
link,typography,Link (link),—,"<a> with underline discipline"
|
|
113
|
+
editable-card,layout,EditableCard (compound/editable-card),—,"card with edit-in-place body and commit footer"
|
|
114
|
+
drag-reorder,layout,Sortable family (compound/sortable),—,"dnd-kit list reorder, keyboard sortable, drag overlay ghost"
|
|
115
|
+
text,typography,Text (element/text),Typography,"semantic p/span with size and weight scale"
|
|
116
|
+
badge,typography,Badge (element/badge),Badge,"small status pill, tokenized tone"
|
|
117
|
+
chip,typography,"Chip (element/chip) · Option display (element/select)",—,"removable tag, optional color dot"
|
|
118
|
+
code,typography,Code (element/code),—,"inline <code>, mono"
|
|
119
|
+
kbd,typography,Kbd (element/kbd),Kbd,"<kbd> keycap"
|
|
120
|
+
label,typography,Label (element/label),Label,"<label for> bound to a control"
|
|
121
|
+
link,typography,Link (element/link),—,"<a> with underline discipline"
|
|
122
122
|
secure-text,typography,SecureText (secure-text),—,"masked value with reveal toggle, mono"
|
|
123
|
-
markdown,typography,Markdown (markdown),—,"react-markdown rendering with typographic defaults"
|
|
124
|
-
avatar,media,Avatar (avatar),Avatar,"image with initials fallback, round"
|
|
125
|
-
copy-button,media,CopyButton (copy-button),—,"clipboard write with copied-state swap"
|
|
126
|
-
icon,media,"IconRenderer (icon-renderer) + icons-data (icons-data)",—,"lucide icon by name, consistent stroke and size grid"
|
|
127
|
-
voice-waveform,media,"LiveWaveform (live-waveform) · MicIcon (mic-icon)",—,"animated level bars from mic input"
|
|
128
|
-
brand-logo,media,"Logo — blue-black|white-white|lime-white|blue-white (logo)",—,"inline SVG logo sized by height"
|
|
129
|
-
shine-border,media,ShineBorder (shine-border),—,"animated gradient border wrapper, decorative"
|
|
130
|
-
theme-toggle,media,ThemeToggler (theme-toggler),—,"light/dark switch writing data-theme"
|
|
131
|
-
view-switcher,media,ViewSwitcher (
|
|
132
|
-
animated-number,motion,"AnimatedNumber (animated-number) · SlidingNumber (
|
|
133
|
-
stagger-entrance,motion,AnimatedGroup (
|
|
134
|
-
text-effects,motion,"TextEffect · TextMorph · TextScramble · TextShimmer (
|
|
135
|
-
morphing-overlay,motion,"MorphingDialog · MorphingPopover (
|
|
136
|
-
panel-transitions,motion,"TransitionPanel · Disclosure · motion Accordion (
|
|
137
|
-
decorative-effects,motion,"Spotlight · GlowEffect · AnimatedBackground · InfiniteSlider · Highlight (
|
|
138
|
-
dynamic-toolbar,motion,ToolbarDynamic (
|
|
139
|
-
utility-hooks,hooks,"useClickOutside · useFileUpload · useMediaQuery · useIsMobile (
|
|
140
|
-
class-merge,utils,cn (utils),cn,"clsx + tailwind-merge"
|
|
141
|
-
formatting-utils,utils,"formatDate (format) · generateId (id) · getErrorMessage (handle-error)",—,"Intl date formatting, nanoid ids, error-to-message normalization"
|
|
142
|
-
composition-utils,utils,"getStrictContext (get-strict-context) · composeRefs (compose-refs)",—,"throwing Provider/hook pair, ref composition"
|
|
123
|
+
markdown,typography,Markdown (element/markdown),—,"react-markdown rendering with typographic defaults"
|
|
124
|
+
avatar,media,Avatar (element/avatar),Avatar,"image with initials fallback, round"
|
|
125
|
+
copy-button,media,CopyButton (compound/copy-button),—,"clipboard write with copied-state swap"
|
|
126
|
+
icon,media,"IconRenderer (element/icon-renderer) + icons-data (lib/icons-data)",—,"lucide icon by name, consistent stroke and size grid"
|
|
127
|
+
voice-waveform,media,"LiveWaveform (element/live-waveform) · MicIcon (element/mic-icon)",—,"animated level bars from mic input"
|
|
128
|
+
brand-logo,media,"Logo — blue-black|white-white|lime-white|blue-white (element/logo)",—,"inline SVG logo sized by height"
|
|
129
|
+
shine-border,media,ShineBorder (effect/shine-border),—,"animated gradient border wrapper, decorative"
|
|
130
|
+
theme-toggle,media,ThemeToggler (element/theme-toggler),—,"light/dark switch writing data-theme"
|
|
131
|
+
view-switcher,media,ViewSwitcher (compound/tabs),—,"segmented control switching view-type projections"
|
|
132
|
+
animated-number,motion,"AnimatedNumber (element/animated-number) · SlidingNumber (element/animated-number)",—,"tick-up numerals, renders plain text until JS ready"
|
|
133
|
+
stagger-entrance,motion,AnimatedGroup (effect/animated-group),—,"staggered child arrival, identity moments only, never on 100×/day actions"
|
|
134
|
+
text-effects,motion,"TextEffect · TextMorph · TextScramble · TextShimmer (effect/*)",—,"per-character text animation, low-frequency surfaces only"
|
|
135
|
+
morphing-overlay,motion,"MorphingDialog · MorphingPopover (effect/*)",—,"trigger morphs into overlay, interruptible"
|
|
136
|
+
panel-transitions,motion,"TransitionPanel · Disclosure · motion Accordion (effect/*) · animated Tabs (animate-ui)",—,"crossfade/slide between sibling panels, height-animated reveal, interruptible"
|
|
137
|
+
decorative-effects,motion,"Spotlight · GlowEffect · AnimatedBackground · InfiniteSlider · Highlight (effect/*, effect/*)",—,"pointer-tracked washes and loops, decorative only, never on data"
|
|
138
|
+
dynamic-toolbar,motion,ToolbarDynamic (effect/toolbar-dynamic),—,"toolbar expanding to contextual actions"
|
|
139
|
+
utility-hooks,hooks,"useClickOutside · useFileUpload · useMediaQuery · useIsMobile (lib/*)",—,"outside-click, file-upload state, matchMedia boolean, <768px boolean"
|
|
140
|
+
class-merge,utils,cn (lib/utils),cn,"clsx + tailwind-merge"
|
|
141
|
+
formatting-utils,utils,"formatDate (lib/format) · generateId (lib/id) · getErrorMessage (lib/handle-error)",—,"Intl date formatting, nanoid ids, error-to-message normalization"
|
|
142
|
+
composition-utils,utils,"getStrictContext (lib/get-strict-context) · composeRefs (lib/compose-refs)",—,"throwing Provider/hook pair, ref composition"
|
|
143
143
|
```
|
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
|
|
3
3
|
> Generated reference (regen-owned; see [index.md](index.md)). Binds only under `primitives: nurix`.
|
|
4
4
|
|
|
5
|
-
Content structure and containers. Import each from its own subpath, e.g. `import { Card, CardContent } from "@nurix/components/card";`.
|
|
5
|
+
Content structure and containers. Import each from its own subpath, e.g. `import { Card, CardContent } from "@nurix/components/block/card";`.
|
|
6
6
|
|
|
7
7
|
## Statistics
|
|
8
8
|
|
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
|
|
3
3
|
> Generated reference (regen-owned; see [index.md](index.md)). Binds only under `primitives: nurix`.
|
|
4
4
|
|
|
5
|
-
Icons, avatars, and media display; import each from its kebab-case subpath, e.g. `import { Avatar } from "@nurix/components/avatar"`.
|
|
5
|
+
Icons, avatars, and media display; import each from its kebab-case subpath, e.g. `import { Avatar } from "@nurix/components/element/avatar"`.
|
|
6
6
|
|
|
7
7
|
## Avatar
|
|
8
8
|
|
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
|
|
3
3
|
> Generated reference (regen-owned; see [index.md](index.md)). Binds only under `primitives: nurix`.
|
|
4
4
|
|
|
5
|
-
Animation primitives built on the `motion` library (`motion-primitives/*`) plus a small `animate-ui/*` layer. Compose sparingly — decorative and low-frequency surfaces only; never on data or on actions users repeat dozens of times a day. Import each from its own subpath, e.g. `import { AnimatedGroup } from "@nurix/components/
|
|
5
|
+
Animation primitives built on the `motion` library (`motion-primitives/*`) plus a small `animate-ui/*` layer. Compose sparingly — decorative and low-frequency surfaces only; never on data or on actions users repeat dozens of times a day. Import each from its own subpath, e.g. `import { AnimatedGroup } from "@nurix/components/effect/animated-group"`.
|
|
6
6
|
|
|
7
7
|
## Animated numbers
|
|
8
8
|
|
|
@@ -4,11 +4,11 @@
|
|
|
4
4
|
|
|
5
5
|
Components: Breadcrumb, Menubar, Navbar, NavigationMenu, Pagination, Sidebar, SlideOutMenu, Tabs, VerticalIconBar
|
|
6
6
|
|
|
7
|
-
Each imports from its own subpath, with compound members alongside, e.g. `import { Tabs, TabsList, TabsTrigger, TabsContent } from "@nurix/components/tabs"`.
|
|
7
|
+
Each imports from its own subpath, with compound members alongside, e.g. `import { Tabs, TabsList, TabsTrigger, TabsContent } from "@nurix/components/compound/tabs"`.
|
|
8
8
|
|
|
9
9
|
## Sidebar
|
|
10
10
|
|
|
11
|
-
App sidebar: full shadcn primitives plus an opinionated layer, all from the single `@nurix/components/sidebar` subpath.
|
|
11
|
+
App sidebar: full shadcn primitives plus an opinionated layer, all from the single `@nurix/components/block/sidebar` subpath.
|
|
12
12
|
|
|
13
13
|
**Sub-components:** `SidebarProvider`, `Sidebar` (`side` [left|right], `variant` [sidebar|floating|inset], `collapsible` [offcanvas|icon|none]), `SidebarTrigger`, `SidebarHeader`, `SidebarContent`, `SidebarFooter`, `SidebarGroup`, `SidebarMenu`, `SidebarMenuItem`, `SidebarMenuButton`, `SidebarRail`, `SidebarInset`, `useSidebar`. **Opinionated layer:** `Brand`, `Switcher` (`render` [simple|rich], `options`, `activeId`, `onSelect`), `ItemGroup` (`render` [list|tree|rich], `collapsible`, `compact`, `collapsedLabel` [hide|divider], `items`, `onItemClick`), `UserMenu`, `Callout`, `FileTree`, `SidebarCommandTrigger`.
|
|
14
14
|
|
|
@@ -62,7 +62,7 @@ Side panel overlay with header/body/footer layout.
|
|
|
62
62
|
|
|
63
63
|
## Other Overlays
|
|
64
64
|
|
|
65
|
-
Standard compound components following the Trigger/Content pattern; import each from its kebab-case subpath (e.g. `@nurix/components/popover`):
|
|
65
|
+
Standard compound components following the Trigger/Content pattern; import each from its kebab-case subpath (e.g. `@nurix/components/element/popover`):
|
|
66
66
|
|
|
67
67
|
- `Command` (`command`)
|
|
68
68
|
- `ContextMenu` (`context-menu`)
|
|
@@ -34,7 +34,7 @@ The design skill's token artifact (CSS custom properties emitted from the projec
|
|
|
34
34
|
Use subpath imports — each published entry maps to one; never import from the root barrel in generated code:
|
|
35
35
|
|
|
36
36
|
```tsx
|
|
37
|
-
import { Button } from "@nurix/components/button";
|
|
38
|
-
import { Cell } from "@nurix/components/cell";
|
|
39
|
-
import { defineColumn } from "@nurix/components/table";
|
|
37
|
+
import { Button } from "@nurix/components/element/button";
|
|
38
|
+
import { Cell } from "@nurix/components/compound/cell";
|
|
39
|
+
import { defineColumn } from "@nurix/components/block/table";
|
|
40
40
|
```
|
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
|
|
3
3
|
> Generated reference (regen-owned; see [index.md](index.md)). Binds only under `primitives: nurix`.
|
|
4
4
|
|
|
5
|
-
Import each from its kebab-case subpath, e.g. `import { Badge } from "@nurix/components/badge"`.
|
|
5
|
+
Import each from its kebab-case subpath, e.g. `import { Badge } from "@nurix/components/element/badge"`.
|
|
6
6
|
|
|
7
7
|
## Text
|
|
8
8
|
|
|
@@ -43,4 +43,4 @@ Masked display for sensitive values (passwords, API keys, card numbers) with an
|
|
|
43
43
|
- `kbd` — `Kbd`: keycap; `variant` [default|outline], `size` [sm|default|lg]
|
|
44
44
|
- `label` — `Label`: Radix `Label.Root`, tracks a peer/group's `disabled` state automatically
|
|
45
45
|
- `link` — `Link`: `variant` [default|muted|plain|underline], `size` [sm|default|lg], `asChild`, `external` (forces `target="_blank"` + a trailing icon; also auto-detects `target="_blank"`)
|
|
46
|
-
- `markdown` — `Markdown`: GFM `react-markdown` + `remark-gfm` render with a full element map (headings, lists, code, blockquote, tables) styled on the library's own tokens — no `@tailwindcss/typography` plugin needed; safe to re-render incrementally while streaming. **Props:** `children` (markdown string), `className`
|
|
46
|
+
- `markdown` — `Markdown`: GFM `react-markdown` + `remark-gfm` render with a full element map (headings, lists, element/code, blockquote, tables) styled on the library's own tokens — no `@tailwindcss/typography` plugin needed; safe to re-render incrementally while streaming. **Props:** `children` (markdown string), `className`
|
|
@@ -122,11 +122,18 @@ The two guarantees are complementary and both break on mixing: a reader holding
|
|
|
122
122
|
|
|
123
123
|
**Frontmatter is compulsory on every document this skill authors** — `type:` (the genre) on every
|
|
124
124
|
doc, plus the genre's own keys beside it; a document without its frontmatter fails the skill's
|
|
125
|
-
contract and is not done.
|
|
126
|
-
`module:` (optional), `keywords:` (required), `status:` (required),
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
125
|
+
contract and is not done. **There is no frontmatter-less genre.** A feature or UX doc carries the
|
|
126
|
+
full set — `owns:` (required), `module:` (optional), `keywords:` (required), `status:` (required),
|
|
127
|
+
`applies:` (the architecture docs it obeys; omitted when none), optional `last-reviewed:`. A
|
|
128
|
+
behavioral checklist (`docs/tests/`) carries `type: checklist` and `verifies:` — the doc whose
|
|
129
|
+
promises it proves. An acceptance-criteria doc (`docs/acceptance/`) carries `type:` and `status:`.
|
|
130
|
+
|
|
131
|
+
**The frontmatter is where the docs tree's edges live**, and a doc that declares none is a node
|
|
132
|
+
nothing can reach: no change implicates it, so it rots without the rot being detectable. Deriving
|
|
133
|
+
every edge — `owns:` from code, `verifies:` and `applies:` from the docs they answer to — is
|
|
134
|
+
[`references/frontmatter.md`](references/frontmatter.md), and it carries the rule the whole graph
|
|
135
|
+
rests on: **declare once at the consuming end, generate every inverse.** Every doc create or
|
|
136
|
+
update, and the `maintenance` agent's baseline pass, route there.
|
|
130
137
|
|
|
131
138
|
---
|
|
132
139
|
|
|
@@ -1,8 +1,16 @@
|
|
|
1
|
-
# Frontmatter Derivation —
|
|
1
|
+
# Frontmatter Derivation — the doc graph
|
|
2
2
|
|
|
3
|
-
Load when: creating a feature doc, updating one whose
|
|
3
|
+
Load when: creating a doc that declares an edge (a feature doc, a UX doc, a behavioral checklist), updating one whose scope moved, or running a baseline/reconcile pass over many docs.
|
|
4
4
|
|
|
5
|
-
|
|
5
|
+
**A docs tree is a graph, and every edge in it is declared in frontmatter.** Two kinds of edge exist: **doc → code** (`owns:`), and **doc → doc** (`verifies:`, `applies:`). The SessionStart hook reads them all and injects the generated indexes; there is no hand-maintained map of either kind.
|
|
6
|
+
|
|
7
|
+
## The one rule that keeps the graph honest
|
|
8
|
+
|
|
9
|
+
**An edge is declared once, at the consuming end. Every inverse is generated, never authored.**
|
|
10
|
+
|
|
11
|
+
A parent that hand-lists its children is a second thing to forget, and the moment the two directions can disagree nothing says which is right — you have doubled the staleness surface rather than halving it. So a checklist names the feature it verifies; the feature never lists its checklists. A feature names the architecture doc it obeys; the architecture doc never lists its consumers. Both inverses are derived on demand and injected, exactly as the ownership index already is.
|
|
12
|
+
|
|
13
|
+
The consuming end is also the end that **knows**. A checklist author knows what they are verifying; an architecture doc has no idea who will obey it next year.
|
|
6
14
|
|
|
7
15
|
## When to run
|
|
8
16
|
|
|
@@ -34,7 +42,21 @@ The single bounded-context label this feature belongs to, or omit it for a cross
|
|
|
34
42
|
|
|
35
43
|
`keywords:` are the discovery terms topic→doc lookup rides. `status:` is `active`, `draft`, or `deprecated` — it steers the model toward live docs and away from draft/deprecated ones.
|
|
36
44
|
|
|
37
|
-
|
|
45
|
+
## The doc → doc edges
|
|
46
|
+
|
|
47
|
+
A prose link is not an edge. It states that one doc mentions another; it never states **why**, so nothing can be derived from it — not who consumes a doctrine, not what to re-read before an edit, not what falls stale when a surface moves. A tree can carry hundreds of prose links and still have no graph. These two keys carry the relationships that matter; everything else stays prose.
|
|
48
|
+
|
|
49
|
+
**`verifies:`** — on a behavioral checklist (`docs/tests/{feature}.md`), the feature or UX doc(s) whose promises it proves. One value is the norm; several when a checklist spans a capability that two docs decide. A checklist carrying no `verifies:` is an orphan by construction: nothing implicates it when its subject changes, so it rots silently and the rot is undetectable.
|
|
50
|
+
|
|
51
|
+
**`applies:`** — on a feature or UX doc, the architecture docs it obeys. Not "docs I read" and not "docs I mention" — **obligation**: a doctrine this surface is bound by, such that a change to the doctrine implicates this doc. The narrow reading is the load-bearing one; a key that collects everything consulted degrades into a bibliography and stops meaning anything. A feature bound by nothing cross-cutting omits the key.
|
|
52
|
+
|
|
53
|
+
Cross-cutting *contracts* remain diagnosed by the `boundary` skill from source, never persisted — `applies:` records which doctrine a surface answers to, not which code it touches.
|
|
54
|
+
|
|
55
|
+
## What is not frontmatter, deliberately
|
|
56
|
+
|
|
57
|
+
**`Pinned:` stays a section-level line inside a checklist**, naming the suite tests that guard that section. It is already typed and already resolved mechanically by the `maintenance` agent. Hoisting it into frontmatter would flatten per-section detail into a doc-level list and duplicate what the sections already say — the exact double-declaration the one rule above forbids.
|
|
58
|
+
|
|
59
|
+
That edge has a property the others lack, and it is worth naming: **a `Pinned:` reference terminates.** A test file exists or it does not, so the edge is falsifiable by a resolver sweep with no judgement. An `owns:` glob is only falsifiable at the dangling end — a glob that resolves says nothing about whether the doc still describes what the code does. Terminal edges get resolver sweeps; non-terminal edges need a human or an agent to read both ends. Do not build a checker that pretends otherwise.
|
|
38
60
|
|
|
39
61
|
## Rules
|
|
40
62
|
|
|
@@ -42,3 +64,6 @@ A doc's dependencies on other docs are expressed inline in its prose (links); cr
|
|
|
42
64
|
- Use glob patterns for directories, explicit paths for individual files. At `active`, never list paths that don't exist in the codebase; a `draft`'s projected paths are confirmed at `active`.
|
|
43
65
|
- When a doc covers a deep feature with sub-specs (e.g., `editor/`), each sub-spec owns its own globs — don't duplicate a path across siblings.
|
|
44
66
|
- For baseline/reconcile with many docs, use parallel sub-agents to read source and propose `owns:` globs.
|
|
67
|
+
- **Never author an inverse.** No doc lists its verifiers, its consumers, or its dependents — those are generated. A hand-written "consumed by" table is a defect to delete, not a convention to follow.
|
|
68
|
+
- **Every edge value is a repo-relative doc path** (`docs/architecture/common/security.md`), never a bare filename and never a display title — the resolver is a path lookup, and a title changes without the file moving.
|
|
69
|
+
- **A dangling edge is a block, not a warning.** `verifies:` or `applies:` naming a doc that does not exist is a typo or a deletion; either way the graph is lying. Resolve at authoring time.
|
|
@@ -1,6 +1,23 @@
|
|
|
1
1
|
# Behavioral Checklist (docs/tests/{feature}.md)
|
|
2
2
|
|
|
3
|
-
Truth document. Use for: **how to verify one feature's promised behavior by driving the real product** — the browser, the CLI binary, HTTP against the running service. One file per feature, named for the feature doc that owns the code (`docs/features/auth.md` → `docs/tests/auth.md`).
|
|
3
|
+
Truth document. Use for: **how to verify one feature's promised behavior by driving the real product** — the browser, the CLI binary, HTTP against the running service. One file per feature, named for the feature doc that owns the code (`docs/features/auth.md` → `docs/tests/auth.md`).
|
|
4
|
+
|
|
5
|
+
**Frontmatter is two keys, and `verifies:` is the load-bearing one:**
|
|
6
|
+
|
|
7
|
+
```yaml
|
|
8
|
+
---
|
|
9
|
+
type: checklist # required tooling key — genre stamp
|
|
10
|
+
verifies: [docs/features/auth.md] # required — the doc(s) whose promises this proves
|
|
11
|
+
---
|
|
12
|
+
```
|
|
13
|
+
|
|
14
|
+
A checklist owns no code, so it carries no `owns:`. What it carries instead is the edge back to
|
|
15
|
+
its subject. **The filename convention is not the edge** — a same-named file is a coincidence a
|
|
16
|
+
resolver cannot trust, it breaks the moment a checklist spans two docs or a feature is renamed, and
|
|
17
|
+
it leaves nothing to implicate this file when its subject changes. Without `verifies:` a checklist
|
|
18
|
+
is unreachable: no change reaches it, so it goes stale and the staleness is undetectable. Several
|
|
19
|
+
values are correct where one checklist proves promises two docs decide; the inverse — which
|
|
20
|
+
checklists cover a feature — is generated, never listed in the feature doc.
|
|
4
21
|
|
|
5
22
|
**This is the driving script, and it is the source the suite is drawn from.** At the verification gate it does double duty: rung 1 drives the real surface *against these steps*, and rung 2 pins the durable subset *of these assertions* as suite tests. Writing it is therefore not a report written afterwards — it is authored or updated **before** the driving, so the gate has something to execute and the tests have something to be derived from. Which assertions earn a permanent test is decided by the `testing` skill (gate mode) § What earns a suite test, and each section records the answer on its `Pinned:` line.
|
|
6
23
|
|
|
@@ -12,6 +12,7 @@ owns: ["src/feature/**", "src/other/file.ts"] # required — code-path globs t
|
|
|
12
12
|
module: billing # optional — single bounded-context label; omit if cross-cutting
|
|
13
13
|
keywords: [invoice, pdf] # required — discovery terms
|
|
14
14
|
status: active # required — active | draft | deprecated
|
|
15
|
+
applies: [docs/architecture/common/security.md] # optional — architecture docs this surface is BOUND by (obligation, not a bibliography); omit when none
|
|
15
16
|
last-reviewed: YYYY-MM-DD # optional tooling key — stamped on substantive review/update; the maintenance agent ranks audit priority by it (metadata, never narrated in the body)
|
|
16
17
|
type: feature # required tooling key — genre stamp (generator-written or authored; enum = the template names), read by tooling (UI grouping, protected-file mapping); preserve on edits, never narrate
|
|
17
18
|
---
|
|
@@ -4,6 +4,8 @@ Record. Use for: every implementation plan. Plans are created here directly with
|
|
|
4
4
|
|
|
5
5
|
The `boundary` skill parses the **Proposed Changes** sections to check boundary impact before execution, and the `testing` skill (plan-gate mode) writes a **Test Obligations** section into the plan at the same gate. Keep that structure stable — section headings and bullet shape are load-bearing for the parsers, and the Test Obligations table is the ledger the verification gate discharges before the plan may reach `Status: Complete`.
|
|
6
6
|
|
|
7
|
+
**Both ledgers are read by a wall, so their cells obey a table's grammar.** A literal pipe inside a cell is written `\|` — the parser splits on unescaped pipes and unescapes what survives, so an escaped one is safe, and an unescaped one silently adds a column and shifts every later cell left. Prefer rephrasing (`` `install` or `update` ``) over escaping where the sentence allows it: the cell then reads the same to a person and to the wall.
|
|
8
|
+
|
|
7
9
|
**Doc Obligations is the one ledger the plan's author writes.** Deriving tests from behavior is judgment, which is why `testing` owns that section and it is marked never-hand-author; resolving Proposed Changes' file paths to the feature docs that own them is a **lookup** against the ownership index already injected at session start. Different work, different rule — fill it yourself, while the touch list is fresh.
|
|
8
10
|
|
|
9
11
|
The **`Gates:`** line carries one machine-read segment. The compliance hook greps **`Boundary:`** — implementation edits inside the plan's scope are blocked while it reads `Boundary: pending`; the `boundary` skill rewrites it to `Boundary: passed YYYY-MM-DD` or `Boundary: blocked YYYY-MM-DD`. The other two gates are enforced by **section presence**: a plan with no `## Test Obligations` or no `## Doc Obligations` section blocks the same edits — the sections are the artifacts, and the gate derives from them, not from a claim about them. Never hand-edit the line to skip a gate.
|
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
|
|
3
3
|
**Truth document.** States what a person sees and can do on a surface, and what the surface promises never to do. Present tense, like every truth document.
|
|
4
4
|
|
|
5
|
-
**`type: ux
|
|
5
|
+
**`type: ux`**, plus `applies:` — the architecture docs this surface is bound by (the state vocabulary, the routing doctrine, the information architecture it answers to). Same key and same narrow reading as a feature doc's: obligation, not a reading list.
|
|
6
6
|
|
|
7
7
|
**Why this genre exists.** A feature doc (LLD) states what a feature is, how its data flows, and which contracts it honours — all of which stay plausibly true through a rewrite of the surface. Nothing else in the repo states what a person *observes*. So a change to the wire lands, the interface absorbs it, and the absorption reads as maintenance: no test fails, no lint fires, no document is contradicted. This document is the thing a silent change contradicts.
|
|
8
8
|
|