@imfusion/web-ui 0.8.1-dev.7.g5ec2789c → 0.8.1-dev.72.g2aaa1dd3

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.
Files changed (97) hide show
  1. package/CHANGELOG.md +258 -6
  2. package/README.md +29 -18
  3. package/THIRD_PARTY_NOTICES.md +34 -0
  4. package/dist/{code-D2lwxHgd.js → code-BYkr5k55.js} +13 -13
  5. package/dist/codegen/gen-icons.d.ts +29 -4
  6. package/dist/codegen/sharpen-icon.d.ts +11 -0
  7. package/dist/components/account-card/account-card.d.ts +9 -9
  8. package/dist/components/app-shell/app-shell.d.ts +59 -34
  9. package/dist/components/avatar/avatar.d.ts +1 -1
  10. package/dist/components/button/button.d.ts +14 -7
  11. package/dist/components/callout/callout.d.ts +4 -4
  12. package/dist/components/card/card.d.ts +21 -7
  13. package/dist/components/chip/chip.cva.d.ts +1 -1
  14. package/dist/components/chip/chip.d.ts +1 -1
  15. package/dist/components/chip-link/chip-link.d.ts +1 -1
  16. package/dist/components/code/code.d.ts +1 -1
  17. package/dist/components/field/field.d.ts +5 -2
  18. package/dist/components/icon/icon.d.ts +1 -1
  19. package/dist/components/icon-button/icon-button.d.ts +19 -0
  20. package/dist/components/icon-button/icon-button.meta.d.ts +2 -0
  21. package/dist/components/icon-button/index.d.ts +2 -0
  22. package/dist/components/kbd/aria-key-shortcuts.d.ts +5 -0
  23. package/dist/components/kbd/index.d.ts +2 -0
  24. package/dist/components/kbd/kbd.d.ts +14 -0
  25. package/dist/components/kbd/kbd.meta.d.ts +2 -0
  26. package/dist/components/logo/logo.d.ts +3 -3
  27. package/dist/components/meter/index.d.ts +2 -0
  28. package/dist/components/meter/meter.d.ts +33 -0
  29. package/dist/components/meter/meter.meta.d.ts +2 -0
  30. package/dist/components/navigation-menu/subs/link.d.ts +1 -1
  31. package/dist/components/popover/popover.d.ts +3 -3
  32. package/dist/components/prose/prose.d.ts +1 -1
  33. package/dist/components/row/row.d.ts +3 -3
  34. package/dist/components/skeleton/index.d.ts +2 -0
  35. package/dist/components/skeleton/skeleton.d.ts +47 -0
  36. package/dist/components/skeleton/skeleton.meta.d.ts +2 -0
  37. package/dist/components/slider/slider.d.ts +11 -1
  38. package/dist/components/spinner/spinner.d.ts +1 -1
  39. package/dist/components/stack/stack.d.ts +3 -3
  40. package/dist/components/table/table.d.ts +16 -7
  41. package/dist/components/tabs/tabs.d.ts +1 -1
  42. package/dist/components/toggle/toggle.d.ts +7 -1
  43. package/dist/components/tooltip/tooltip.d.ts +2 -2
  44. package/dist/components/typo/typo.d.ts +21 -12
  45. package/dist/icons/catalog.gen.d.ts +3804 -0
  46. package/dist/icons/create-icon.d.ts +3 -0
  47. package/dist/icons/icon-config-context.d.ts +3 -0
  48. package/dist/icons/icon-config.d.ts +2 -2
  49. package/dist/icons/icons.gen.d.ts +1737 -1672
  50. package/dist/icons-BsK_o-Cb.js +36358 -0
  51. package/dist/icons.js +2 -2
  52. package/dist/index.d.ts +5 -0
  53. package/dist/index.js +2080 -1607
  54. package/dist/integrations/code-highlight.js +6 -4
  55. package/dist/integrations/frame-selection/frame-selection-view.d.ts +24 -0
  56. package/dist/integrations/frame-selection/frame-selection.d.ts +21 -0
  57. package/dist/integrations/frame-selection/frame-selection.meta.d.ts +2 -0
  58. package/dist/integrations/frame-selection/index.d.ts +2 -0
  59. package/dist/integrations/frame-selection.js +121 -0
  60. package/dist/integrations/image-display-options/image-display-options-view.d.ts +1 -1
  61. package/dist/integrations/image-display-options/image-display-options.d.ts +1 -1
  62. package/dist/integrations/image-display-options.js +56 -55
  63. package/dist/llms/evals/runner/config.d.ts +1 -0
  64. package/dist/llms/gen-tokens.d.ts +1 -1
  65. package/dist/{paths-Oi0v8x-w.js → paths-B5Ht3ETc.js} +2 -2
  66. package/dist/separator-lzz4A3x_.js +26 -0
  67. package/dist/slider-Cqpreglu.js +116 -0
  68. package/dist/style.css +1 -1
  69. package/dist/tabs-DRyqtS04.js +358 -0
  70. package/dist/utils/email.d.ts +7 -0
  71. package/dist/utils/status-glyphs.d.ts +4 -0
  72. package/dist/vite.js +2 -2
  73. package/dist/web-ui-cli.js +1 -1
  74. package/docs/user-guide/AgentTooling.mdx +8 -3
  75. package/package.json +38 -38
  76. package/src/docgen/doc.gen.json +1377 -215
  77. package/src/llms/icon-catalog.gen.json +5541 -1671
  78. package/src/llms/llms.gen.txt +29 -2
  79. package/src/llms/skills/imf-web-ui/SKILL.md +3 -1
  80. package/src/llms/skills/imf-web-ui-audit/SKILL.md +18 -4
  81. package/src/llms/skills/imf-web-ui-components/SKILL.md +3 -1
  82. package/src/llms/skills/imf-web-ui-conventions/templates/AUDIT_CHECKLIST.md +3 -2
  83. package/src/llms/skills/imf-web-ui-conventions/topics/authentication.md +2 -1
  84. package/src/llms/skills/imf-web-ui-conventions/topics/data.md +5 -3
  85. package/src/llms/skills/imf-web-ui-conventions/topics/git.md +2 -3
  86. package/src/llms/skills/imf-web-ui-conventions/topics/npm-project.md +3 -4
  87. package/src/llms/skills/imf-web-ui-conventions/topics/styling.md +4 -2
  88. package/src/llms/skills/imf-web-ui-conventions/topics/tooling.md +83 -42
  89. package/src/llms/skills/imf-web-ui-setup/SKILL.md +2 -0
  90. package/src/llms/skills/imf-web-ui-update/SKILL.md +42 -7
  91. package/src/llms/skills/imf-web-ui-user-profile/SKILL.md +95 -0
  92. package/src/llms/skills/imf-web-ui-ux/SKILL.md +2 -0
  93. package/src/llms/tokens.gen.json +3 -3
  94. package/dist/icons-CaGCCwG-.js +0 -78
  95. package/dist/tabs-BS6rqrrA.js +0 -398
  96. /package/dist/{meta-j-7HGrWv.js → meta-V_KyLeGn.js} +0 -0
  97. /package/dist/{chunk-DmhlhrBa.js → rolldown-runtime-Dy4uBu1J.js} +0 -0
@@ -38,7 +38,7 @@ Persistent, in-place status message for information, success, warnings, and erro
38
38
 
39
39
  ## Card
40
40
  - category: Layout, status: stable
41
- Surface container for related content on a tonal background. Also called a panel or tile; compose it from optional image, header, content, and footer parts.
41
+ Surface container for related content on a tonal background. Also called a panel or tile; compose it from optional image, status, header, content, and footer parts.
42
42
  - props: node_modules/@imfusion/web-ui/src/docgen/doc.gen.json -> .card (jq: jq '.card' node_modules/@imfusion/web-ui/src/docgen/doc.gen.json)
43
43
 
44
44
  ## Checkbox
@@ -96,11 +96,22 @@ Semantic group for related form controls with a shared legend. Also called a for
96
96
  - props: node_modules/@imfusion/web-ui/src/docgen/doc.gen.json -> .fieldset (jq: jq '.fieldset' node_modules/@imfusion/web-ui/src/docgen/doc.gen.json)
97
97
  - further reading (usage/anatomy, not props): https://base-ui.com/react/components/fieldset.md
98
98
 
99
+ ## FrameSelection
100
+ - category: Inputs, status: experimental
101
+ Frame or slice picker bound to the focused frame of ImFusion image sets, with a focus and count readout. For a position picker not tied to the SDK, use Slider with variant="position".
102
+ - props: node_modules/@imfusion/web-ui/src/docgen/doc.gen.json -> .frame-selection (jq: jq '.frame-selection' node_modules/@imfusion/web-ui/src/docgen/doc.gen.json)
103
+ - further reading (usage/anatomy, not props): https://docs.imfusion.com/
104
+
99
105
  ## Icon
100
106
  - category: Display, status: stable
101
107
  Renders a Web UI icon with an optional semantic foreground color. The default inherits the surrounding currentColor.
102
108
  - props: node_modules/@imfusion/web-ui/src/docgen/doc.gen.json -> .icon (jq: jq '.icon' node_modules/@imfusion/web-ui/src/docgen/doc.gen.json)
103
109
 
110
+ ## IconButton
111
+ - category: Buttons, status: experimental
112
+ Square button that shows a single icon and no visible text, with its accessible name from `label`. Also called an icon-only or toolbar button. Use Button with `startIcon` or `endIcon` when a text label is visible.
113
+ - props: node_modules/@imfusion/web-ui/src/docgen/doc.gen.json -> .icon-button (jq: jq '.icon-button' node_modules/@imfusion/web-ui/src/docgen/doc.gen.json)
114
+
104
115
  ## ImageDisplayOptions
105
116
  - category: Inputs, status: experimental
106
117
  Panel and toolbar controls for an image dataset's display options, including window, level, gamma, and invert settings.
@@ -113,11 +124,22 @@ Single-line text input for form data entry. Also called a text field; it support
113
124
  - props: node_modules/@imfusion/web-ui/src/docgen/doc.gen.json -> .input (jq: jq '.input' node_modules/@imfusion/web-ui/src/docgen/doc.gen.json)
114
125
  - further reading (usage/anatomy, not props): https://base-ui.com/react/components/input.md
115
126
 
127
+ ## Kbd
128
+ - category: Display, status: experimental
129
+ Shows a keyboard key or shortcut, such as the letter that activates a button. Also called a key hint; Button and Toggle render it through their `shortcut` prop.
130
+ - props: node_modules/@imfusion/web-ui/src/docgen/doc.gen.json -> .kbd (jq: jq '.kbd' node_modules/@imfusion/web-ui/src/docgen/doc.gen.json)
131
+
116
132
  ## Logo
117
133
  - category: Display, status: stable
118
134
  Renders a logo from a URL or inline React element with consistent sizing. Also called a wordmark or brand mark.
119
135
  - props: node_modules/@imfusion/web-ui/src/docgen/doc.gen.json -> .logo (jq: jq '.logo' node_modules/@imfusion/web-ui/src/docgen/doc.gen.json)
120
136
 
137
+ ## Meter
138
+ - category: Display, status: experimental
139
+ Read-only bar for a measured amount within a known range, such as seats in use or storage used. Also called a gauge or usage bar. Use Slider when the user sets the value.
140
+ - props: node_modules/@imfusion/web-ui/src/docgen/doc.gen.json -> .meter (jq: jq '.meter' node_modules/@imfusion/web-ui/src/docgen/doc.gen.json)
141
+ - further reading (usage/anatomy, not props): https://base-ui.com/react/components/meter.md
142
+
121
143
  ## NavigationMenu
122
144
  - category: Display, status: experimental
123
145
  Navigation menu with horizontal or vertical triggers and anchored flyout panels. Also called a menu bar or mega menu; it supports links, rich cards, and nested navigation.
@@ -158,9 +180,14 @@ Line that divides content horizontally or vertically. Also called a divider or r
158
180
  - props: node_modules/@imfusion/web-ui/src/docgen/doc.gen.json -> .separator (jq: jq '.separator' node_modules/@imfusion/web-ui/src/docgen/doc.gen.json)
159
181
  - further reading (usage/anatomy, not props): https://base-ui.com/react/components/separator.md
160
182
 
183
+ ## Skeleton
184
+ - category: Display, status: experimental
185
+ Loading placeholder that stands in for data at the size it will take, so nothing shifts when it lands. Also called a skeleton loader or ghost. Use Spinner when the layout is unknown.
186
+ - props: node_modules/@imfusion/web-ui/src/docgen/doc.gen.json -> .skeleton (jq: jq '.skeleton' node_modules/@imfusion/web-ui/src/docgen/doc.gen.json)
187
+
161
188
  ## Slider
162
189
  - category: Inputs, status: stable
163
- Numeric input for choosing one value or a range by dragging a thumb. Also called a range input; use it when relative magnitude matters.
190
+ Numeric input for choosing one value or a range by dragging a thumb. Also called a range input; use it when relative magnitude matters. The position variant is a scrubber for picking one slice or frame.
164
191
  - props: node_modules/@imfusion/web-ui/src/docgen/doc.gen.json -> .slider (jq: jq '.slider' node_modules/@imfusion/web-ui/src/docgen/doc.gen.json)
165
192
  - further reading (usage/anatomy, not props): https://base-ui.com/react/components/slider.md
166
193
 
@@ -11,6 +11,8 @@ description:
11
11
  Start here for UI work and library questions in a project that uses `@imfusion/web-ui`. This skill is a map, not a second
12
12
  copy of every convention.
13
13
 
14
+ Invoke `imf-web-ui-user-profile` first and explain at its levels throughout.
15
+
14
16
  ## 1. Decide whether guidance is needed
15
17
 
16
18
  Skip a companion when the task is explicit and small, an existing local pattern already solves it in the file being changed,
@@ -60,7 +62,7 @@ props and the conventions `tokens` topic for exact token names and defaults.
60
62
  The host project's existing conventions win. The companion skills fill gaps; they do not justify refactoring a working
61
63
  styling system, state library, or folder structure.
62
64
 
63
- When a task needs TanStack Router, Query, Form, Table, or Store and the project has no incumbent, open
65
+ When a task needs TanStack Router, Query, Form, Table, Store, or Hotkeys and the project has no incumbent, open
64
66
  `imf-web-ui-conventions` for the house position on that layer, then read the library's current documentation with
65
67
  `npx @tanstack/cli` before using it. The recommendation lives in the conventions topics, not here.
66
68
 
@@ -1,11 +1,11 @@
1
1
  ---
2
2
  name: imf-web-ui-audit
3
3
  description:
4
- "Audit an existing ImFusion frontend against the @imfusion/web-ui conventions without changing files. Use this for a
5
- project health check, a pre-setup review, or one named topic. Report broken and missing pieces, working deviations,
4
+ "Audit an existing ImFusion frontend against the @imfusion/web-ui conventions without changing project files. Use this for
5
+ a project health check, a pre-setup review, or one named topic. Report broken and missing pieces, working deviations,
6
6
  evidence, and an ordered plan."
7
7
  argument-hint: "[full|<topic>]"
8
- allowed-tools: Read Glob Grep
8
+ allowed-tools: Read Glob Grep Skill
9
9
  ---
10
10
 
11
11
  # Audit a consumer project
@@ -21,6 +21,8 @@ it low, and do not let it crowd the sections a consumer has to act on.
21
21
 
22
22
  ## Workflow
23
23
 
24
+ Invoke `imf-web-ui-user-profile` first and explain at its levels throughout.
25
+
24
26
  1. Resolve the argument. Bare means `full`; an unknown topic is an error, not a reason to widen the scope.
25
27
  2. Enter plan mode unless this audit is being called as verification by another skill or the host has no plan mode.
26
28
  3. Read the report template and existing reviewer notes, then dispatch one investigator per in-scope topic. Tell each
@@ -28,7 +30,8 @@ it low, and do not let it crowd the sections a consumer has to act on.
28
30
  section in that topic and writes nothing. Once dispatch starts, the host performs no repository inspection: the returned
29
31
  reports are the evidence, and the host merges them without reading or searching the files again. Gathering the evidence
30
32
  twice spends context on the second pass and reports what the host still remembers. Inspect a topic inline only after its
31
- dispatch has been tried and refused, and say which attempt failed.
33
+ dispatch has been tried and refused, and say which attempt failed. A `full` audit also dispatches one marker investigator;
34
+ a named-topic audit gives that search to the topic's investigator. See [Deferred-work markers](#deferred-work-markers).
32
35
  4. Merge the evidence into the shared report format in
33
36
  [`templates/REPORT.md`](../imf-web-ui-conventions/templates/REPORT.md). Before presenting or writing it, check that every
34
37
  Broken, Missing, Deviation, and Unverified entry has a severity, evidence, impact, and next action; do not compact
@@ -66,6 +69,17 @@ Read the corresponding topic and the matching block in
66
69
  [`templates/AUDIT_CHECKLIST.md`](../imf-web-ui-conventions/templates/AUDIT_CHECKLIST.md). The audit is incomplete until every
67
70
  in-scope box has evidence.
68
71
 
72
+ ## Deferred-work markers
73
+
74
+ Comments that mark unfinished work are evidence the code itself admits. Search the frontend sources, styles, stories, tests,
75
+ and frontend config for `TODO`, `FIXME`, `HACK`, `XXX`, and phrases like "temporary", "workaround", "for now", or "remove
76
+ once". Skip `node_modules`, build output, generated files, and vendored code. A named-topic audit keeps only the markers that
77
+ bear on that topic.
78
+
79
+ Read each marker with its surrounding code. One that admits a convention gap, such as a hand-rolled control waiting for a Web
80
+ UI component or a hard-coded color waiting for a token, is evidence for that topic's finding. Every other marker goes under
81
+ `Suggestions` with its `path:line` and what it defers; group repeats of one cause into a single entry.
82
+
69
83
  ## Agent tooling checks
70
84
 
71
85
  For `agent-tooling`, compare the declared version in `package.json`, the installed
@@ -4,13 +4,15 @@ description:
4
4
  "Look up @imfusion/web-ui component APIs, compound parts, defaults, and icon glyphs without reading source. Use this
5
5
  whenever a consumer task names a Web UI component or icon and you need to choose a prop, part, default, or glyph. Do not
6
6
  use it to choose between components or bootstrap a project."
7
- allowed-tools: Bash
7
+ allowed-tools: Bash Skill
8
8
  ---
9
9
 
10
10
  # Look up components
11
11
 
12
12
  Use the generated package indexes. They are smaller and more reliable than reading the library source.
13
13
 
14
+ Invoke `imf-web-ui-user-profile` first and explain at its levels throughout.
15
+
14
16
  ## Component lookup
15
17
 
16
18
  1. Read the identity index first, even when you already know the component's name: it gives the docgen key and the status.
@@ -103,8 +103,9 @@ sections one to one — change a topic's sections and this file follows in the s
103
103
  - [ ] When a library owns a layer
104
104
  - [ ] Devtools
105
105
  - [ ] Docs over memory
106
- - [ ] Prettier
107
- - [ ] ESLint and TypeScript
106
+ - [ ] Vite+
107
+ - [ ] Oxfmt
108
+ - [ ] Oxlint and TypeScript
108
109
  - [ ] Pre-commit checks
109
110
  - [ ] Vite plugins
110
111
 
@@ -19,7 +19,8 @@ Use one server-backed current-user query as the identity source:
19
19
 
20
20
  - Put it in `api/auth/queries.ts` and define its key and schema with the [data.md](data.md) pattern.
21
21
  - Expose query options as `context.api.auth.getUser()`.
22
- - Call `ensureQueryData` in a loader or a query hook in a component.
22
+ - Call `queryClient.query({ ...options, staleTime: "static" })` in a loader (see [data.md](data.md)) or a query hook in a
23
+ component.
23
24
  - Keep credentials and access tokens out of React state.
24
25
  - Do not infer authentication from local storage, decoded tokens, route flags, or permission-gated UI.
25
26
 
@@ -85,9 +85,11 @@ export function getDetails(options?: QueryOptions<User>) {
85
85
  }
86
86
  ```
87
87
 
88
- Callers choose `ensureQueryData`, `useSuspenseQuery`, or another Query API. Mutation factories likewise return
89
- `mutationOptions`, own their mutation key and parsing, and are passed to `useMutation`; do not inline those options at the
90
- call site.
88
+ Callers choose `queryClient.query`, `useSuspenseQuery`, or another Query API. A router loader reads the cache with
89
+ `queryClient.query({ ...options, staleTime: "static" })`, not the deprecated `ensureQueryData` or `fetchQuery`. Keep
90
+ `"static"`: without it the factory's `staleTime` applies (default 0), so every loader run waits on the network and the page's
91
+ `useQuery` refetches on mount. Mutation factories likewise return `mutationOptions`, own their mutation key and parsing, and
92
+ are passed to `useMutation`; do not inline those options at the call site.
91
93
 
92
94
  ## Router context access
93
95
 
@@ -18,11 +18,10 @@ The hooks are tracked in `.githooks/`. Check both the Git setting and the direct
18
18
 
19
19
  There are two scopes:
20
20
 
21
- - **commit**: `verify:staged`, run by pre-commit. It checks whole-repository lint and formatting, then runs project checks
22
- for staged inputs.
21
+ - **commit**: the pre-commit hook, which runs `vp staged` as `tooling.md` describes under Pre-commit checks.
23
22
  - **full**: `verify:full`, the build and complete verification used by CI.
24
23
 
25
- The scripts under `scripts/verify/` own the step lists. Hooks and npm scripts only launch them.
24
+ The `staged` block and the scripts under `scripts/verify/` own the step lists. Hooks and npm scripts only launch them.
26
25
 
27
26
  ## Staleness at commit time
28
27
 
@@ -17,12 +17,11 @@ Use the same names for the same checks where the project supports them:
17
17
  | ------------------ | --------------------------------------- |
18
18
  | `dev` | Start local development. |
19
19
  | `build` | Create a production build. |
20
- | `verify:format` | Check Prettier. |
21
- | `verify:lint` | Check ESLint. |
20
+ | `verify:format` | Run `vp fmt --check`. |
21
+ | `verify:lint` | Run `vp lint`. |
22
22
  | `verify:typecheck` | Run TypeScript without emitting. |
23
- | `verify:tests` | Run tests once. |
23
+ | `verify:tests` | Run `vp test run`. |
24
24
  | `verify:knip` | Check dead code and unused exports. |
25
- | `verify:staged` | Run the pre-commit scope. |
26
25
  | `verify:full` | Run the CI scope. |
27
26
  | `format` | Rewrite formatting. |
28
27
  | `lint` | Rewrite fixable lint issues. |
@@ -7,6 +7,8 @@ Use native CSS and Web UI's public seams. The library's CSS Modules and token na
7
7
  - Use CSS Modules with native nesting. Do not add Sass, CSS-in-JS, or a utility-class framework for ordinary component
8
8
  styles.
9
9
  - Nest states, pseudo-elements, and child selectors under the root.
10
+ - Write declarations before nested rules; browsers before Chrome 130, Firefox 132, and Safari 18 move later ones above them.
11
+ - Do not nest under a selector list whose selectors differ in specificity. The nested rule takes the highest one.
10
12
  - Lift repeated values into custom properties, especially when a state or variant changes several descendants.
11
13
  - Keep structurally different rules explicit; not every repeated value needs an abstraction.
12
14
 
@@ -85,8 +87,8 @@ Foreground roles are for text, icons, borders, and focus rings. Background roles
85
87
 
86
88
  ## Browser floor
87
89
 
88
- The library targets Safari 16.2 or newer. `color-mix(in oklch, …)` is available at that floor. Relative color syntax needs a
89
- guarded fallback for older Safari:
90
+ The library targets Safari 17.5, Chrome 123, and Firefox 120 or newer, the first versions with native `light-dark()`.
91
+ `color-mix(in oklch, …)` is available at that floor. Relative color syntax needs a guarded fallback for older Safari:
90
92
 
91
93
  ```css
92
94
  .subtle {
@@ -4,27 +4,28 @@ Use the tool's current documentation rather than memory.
4
4
 
5
5
  ## Topic-to-tool map
6
6
 
7
- | Need | Default |
8
- | --------------------- | -------------------------------------------- |
9
- | Build | Vite |
10
- | Routing and URL state | TanStack Router |
11
- | Server state | TanStack Query |
12
- | Forms | TanStack Form |
13
- | Data grids | TanStack Table plus Web UI `Table` parts |
14
- | App-wide client state | TanStack Store, after URL/server/local state |
15
- | Schema validation | Zod at the boundary |
16
- | Tests | Vitest |
17
- | Format | Prettier |
18
- | Lint | ESLint flat config |
19
- | Types | `tsc --noEmit` |
20
- | Pre-commit checks | Whole-repository lint and format checks |
21
- | Dead code | Knip via `verify:knip` |
7
+ | Need | Default | Docs |
8
+ | --------------------- | -------------------------------------------------------------- | ----------------------------------------- |
9
+ | Toolchain | Vite+ (`vite-plus`), driven through `vp` | https://viteplus.dev/guide |
10
+ | Routing and URL state | TanStack Router | `npx @tanstack/cli`, library `router` |
11
+ | Server state | TanStack Query | `npx @tanstack/cli`, library `query` |
12
+ | Forms | TanStack Form | `npx @tanstack/cli`, library `form` |
13
+ | Data grids | TanStack Table plus Web UI `Table` parts | `npx @tanstack/cli`, library `table` |
14
+ | App-wide client state | TanStack Store, after URL/server/local state | `npx @tanstack/cli`, library `store` |
15
+ | Keyboard shortcuts | TanStack Hotkeys; show the key with Web UI `shortcut` or `Kbd` | `npx @tanstack/cli`, library `hotkeys` |
16
+ | Schema validation | Zod at the boundary | https://zod.dev |
17
+ | Tests | Vitest through `vp test` | https://vitest.dev |
18
+ | Format | Oxfmt through `vp fmt` | https://oxc.rs/docs/guide/usage/formatter |
19
+ | Lint | Oxlint through `vp lint`, type-aware | https://oxc.rs/docs/guide/usage/linter |
20
+ | Types | `tsc --noEmit` | https://www.typescriptlang.org/docs |
21
+ | Pre-commit checks | `vp staged` against the staged state | https://viteplus.dev/guide |
22
+ | Dead code | Knip via `verify:knip` | https://knip.dev |
22
23
 
23
24
  ## When a library owns a layer
24
25
 
25
26
  Use the library that already owns the problem. Adopt Form for form rules, Query for caching and refetching, Router for URL
26
- state, and Table for sorting and pagination instead of rebuilding those layers. Keep an existing project choice when it
27
- works.
27
+ state, Table for sorting and pagination, and Hotkeys for keyboard shortcuts instead of rebuilding those layers. Web UI only
28
+ shows a key; the app binds it. Keep an existing project choice when it works.
28
29
 
29
30
  ## Devtools
30
31
 
@@ -33,50 +34,90 @@ devtools package whenever a new TanStack dependency is added.
33
34
 
34
35
  ## Docs over memory
35
36
 
36
- Use `npx @tanstack/cli` for TanStack documentation. If TanStack Intent is configured, use it for the Agent Skills the
37
- TanStack package provides.
37
+ Use `npx @tanstack/cli` for TanStack documentation, with the library id from the map: `search-docs "<query>" --library <id>`
38
+ finds a page, and `doc <id> <path>` prints it, for example
39
+ `npx @tanstack/cli doc hotkeys framework/react/reference/functions/useHotkey`. If TanStack Intent is configured, use it for
40
+ the Agent Skills the TanStack package provides.
38
41
 
39
- ## Prettier
42
+ ## Vite+
40
43
 
41
- Use a config file. The repo's values are:
44
+ Vite+ runs development, build, tests, format, lint, and staged checks through one `vp` binary configured in `vite.config.ts`.
45
+ Pin `vite-plus` exactly, alias `vite` to `npm:@voidzero-dev/vite-plus-core@<vite-plus version>`, pin `vitest` to the version
46
+ `vp toolchain vitest` reports, and repeat both pins under `overrides`. Import `defineConfig` from `vite-plus` and Vitest APIs
47
+ from `vite-plus/test`. It needs Node `^22.22.1 || ^24.11 || >=26` and Git 2.32 or later.
48
+
49
+ `vp <command>` is a built-in; `vp run <script>` runs a package script.
50
+
51
+ Move an existing Vite, Vitest, ESLint, or Prettier project with `vp migrate --no-hooks` (`vp help migrate` lists its
52
+ options), then check the result against this topic. The hook lives in `.githooks/`, as `git.md` describes.
53
+
54
+ ## Oxfmt
55
+
56
+ Configure formatting in the `fmt` block of `vite.config.ts`. The repo's values:
42
57
 
43
58
  ```ts
44
- import type { Config } from "prettier";
45
-
46
- const config: Config = {
47
- printWidth: 125,
48
- tabWidth: 2,
49
- useTabs: false,
50
- trailingComma: "none",
51
- arrowParens: "avoid",
52
- semi: true,
53
- singleQuote: false,
54
- proseWrap: "always"
55
- };
56
-
57
- export default config;
59
+ export default defineConfig({
60
+ fmt: {
61
+ printWidth: 125,
62
+ tabWidth: 2,
63
+ useTabs: false,
64
+ trailingComma: "none",
65
+ arrowParens: "avoid",
66
+ semi: true,
67
+ singleQuote: false,
68
+ proseWrap: "always",
69
+ sortPackageJson: false
70
+ }
71
+ });
58
72
  ```
59
73
 
60
- ## ESLint and TypeScript
74
+ ## Oxlint and TypeScript
61
75
 
62
- Use flat ESLint config with type-aware rules and the repo's ignore file. The baseline bans `as` and non-null `!` outside
63
- tests, requires the `#/` alias instead of parent-relative imports, and uses project-service type information.
76
+ Configure linting in the `lint` block with type-aware rules on. The baseline bans `as` and non-null `!` outside tests and
77
+ requires the `#/` alias instead of parent-relative imports:
78
+
79
+ ```ts
80
+ export default defineConfig({
81
+ lint: {
82
+ options: { typeAware: true },
83
+ overrides: [
84
+ {
85
+ files: ["src/**/*.{ts,tsx}"],
86
+ rules: {
87
+ "typescript/consistent-type-assertions": ["error", { assertionStyle: "never" }],
88
+ "typescript/no-non-null-assertion": "error",
89
+ "no-restricted-imports": [
90
+ "error",
91
+ { patterns: [{ group: ["../*"], message: "Use the #/ alias for anything outside the current folder." }] }
92
+ ]
93
+ }
94
+ },
95
+ {
96
+ files: ["**/*.test.{ts,tsx}"],
97
+ rules: { "typescript/consistent-type-assertions": "off", "typescript/no-non-null-assertion": "off" }
98
+ }
99
+ ]
100
+ }
101
+ });
102
+ ```
64
103
 
65
104
  Use strict TypeScript with bundler module resolution, `verbatimModuleSyntax`, unused-value checks, and `#/` paths. Keep
66
105
  `import type` for type-only imports.
67
106
 
68
107
  ## Pre-commit checks
69
108
 
70
- The pre-commit hook checks the whole repository with ESLint and Prettier, then runs project checks for staged inputs that can
71
- affect generated files, types, dependencies, or TeamCity configuration. It does not rewrite files during a commit; use
72
- `npm run format` to apply Prettier changes explicitly.
109
+ `.githooks/pre-commit` runs `vp staged --hide-unstaged --fail-on-changes --revert --diff-filter=ACMRD` with `set -e`. Those
110
+ flags make the checks see only the staged state, include deletion-only commits, fail the commit when a check would change a
111
+ file, and restore the tree afterwards, so the hook never rewrites or stages files. The `staged` block in `vite.config.ts` is
112
+ a function returning path-free commands such as `npm run --silent verify:lint`, so each project-wide check runs once. Use
113
+ `npm run format` to apply formatting explicitly.
73
114
 
74
115
  ## Vite plugins
75
116
 
76
117
  Register Web UI's Vite plugins in the application configuration:
77
118
 
78
119
  ```ts
79
- import { defineConfig } from "vite";
120
+ import { defineConfig } from "vite-plus";
80
121
  import react from "@vitejs/plugin-react";
81
122
  import { imfusionBrandAssets, readableCssModuleNames } from "@imfusion/web-ui/vite";
82
123
 
@@ -15,6 +15,8 @@ working choices.
15
15
 
16
16
  ## Workflow
17
17
 
18
+ Invoke `imf-web-ui-user-profile` first and explain at its levels throughout.
19
+
18
20
  1. Resolve the scope. A named topic limits the assessment to that topic. A bare invocation means `full`, unless the request
19
21
  is about one topic, in which case that topic is the scope: answer what was asked and offer the wider sweep rather than
20
22
  running it. If the argument is unknown, list the supported topics and point to `imf-web-ui-audit`.
@@ -5,7 +5,7 @@ description:
5
5
  lifecycle hooks. Refresh the base first, verify it, then audit any consumer migration separately. Preserve user work and
6
6
  get approval before each commit."
7
7
  argument-hint: "[--dry-run] [optional version or reason]"
8
- allowed-tools: Bash Read Grep
8
+ allowed-tools: Bash Read Grep Skill
9
9
  ---
10
10
 
11
11
  # Update Web UI
@@ -13,6 +13,22 @@ allowed-tools: Bash Read Grep
13
13
  This workflow has two possible commits: the package/tooling update, then an optional consumer migration. Keep them separate.
14
14
  Never overwrite user changes or commit without fresh approval.
15
15
 
16
+ ## Before you start
17
+
18
+ Invoke `imf-web-ui-user-profile` first and explain at its levels throughout.
19
+
20
+ Open with a short orientation, before any command runs, so the person knows the route and when they will be asked:
21
+
22
+ 1. **Preflight**: check the project and stop on uncommitted work.
23
+ 2. **Base update**: install the new package, refresh the skills and hooks, verify, then ask to commit.
24
+ 3. **Migration check**: read what the new releases changed and report what this project needs; changes and their separate
25
+ commit wait for approval.
26
+ 4. **Full audit**: offer `imf-web-ui-audit full`, a read-only check of the whole project against the conventions, wider than
27
+ what this release changed.
28
+
29
+ Name the decision points up front: `latest` or `dev` when the installed version is a prerelease, the base commit, the
30
+ migration commit, and the audit offer. With `--dry-run`, say the run stops after preflight and changes nothing.
31
+
16
32
  ## Preflight
17
33
 
18
34
  1. Work from the frontend package root. In a monorepo, find the package that owns the Web UI dependency.
@@ -20,9 +36,22 @@ Never overwrite user changes or commit without fresh approval.
20
36
  if another lockfile is the active one.
21
37
  3. Record `git status --short`, the installed Web UI version, the installed skill harness(es), hooks, registrations, and
22
38
  `AGENTS.md` fence.
23
- 4. Check for another npm process and stop on a conflict. Uncommitted work is also a conflict: report it and stop before the
24
- first mutating command, even if it looks unrelated to this workflow: what the update touches is only known once it runs,
25
- and the person can commit, stash, or wave it through in one reply. Never reset, clean, restore, or hide it.
39
+ 4. Check for another npm process in this package and stop on a conflict:
40
+
41
+ ```sh
42
+ pgrep npm # process IDs only
43
+ lsof -a -d cwd -p <pid> -Fn # the folder a process runs in
44
+ ps -o args= -p <pid> # its command, only when that folder is this package
45
+ ```
46
+
47
+ A running install, update, or `ci` in this package is a conflict; a long-running `npm exec` server is not. Full process
48
+ listings such as `pgrep -fl` or `ps aux` print every program's arguments, secrets included, so keep them out of the
49
+ transcript.
50
+
51
+ Uncommitted work is also a conflict: report it and stop before the first mutating command, even if it looks unrelated to
52
+ this workflow: what the update touches is only known once it runs, and the person can commit, stash, or wave it through in
53
+ one reply. Never reset, clean, restore, or hide it.
54
+
26
55
  5. With `--dry-run`, stop after reporting what would happen. Do not install, format, stage, commit, or ask for commit
27
56
  approval.
28
57
 
@@ -87,12 +116,13 @@ Update files : <paths>
87
116
  Held back : <paths or none>
88
117
  Conflicts : <paths or none>
89
118
  Commit : <message or not proposed>
119
+ Next : migration check, then the optional full audit
90
120
  ```
91
121
 
92
122
  Ask: **Approve these update-owned changes and commit them?** Stage only approved update paths and follow the repository's
93
123
  commit workflow.
94
124
 
95
- ## Audit the consumer migration
125
+ ## Check the consumer migration
96
126
 
97
127
  Start this phase only after the base update commit exists. Read `node_modules/@imfusion/web-ui/CHANGELOG.md`: every release
98
128
  section after the pre-update version, up to and including the new one. Each section's highlights, migration guide, and
@@ -114,12 +144,17 @@ releases read, then report separately:
114
144
  - existing uses affected by a changed API or documented behavior;
115
145
  - suggestions: new features from the highlights and `Added` entries that fit what the project already builds, each with the
116
146
  project code it would serve; a suggestion stays a proposal until the person asks for it;
117
- - custom components that overlap with a current Web UI primitive, with evidence and any behavior to preserve.
147
+ - custom components that overlap with a current Web UI primitive, with evidence and any behavior to preserve;
148
+ - icons: project-local icons (inline SVGs, icon components, a third-party icon set) that a catalog icon now covers, above all
149
+ the ImFusion icons (`"origin": "imfusion"`). Search `node_modules/@imfusion/web-ui/src/llms/icon-catalog.gen.json` by
150
+ meaning, compare the drawing, and report each with the replacement export; a replacement stays a proposal until the person
151
+ asks for it.
118
152
 
119
153
  Do not infer a replacement from a name. Inspect the implementation, styles, and call sites. If there are no findings, say so
120
154
  and do not make an empty migration commit.
121
155
 
122
- Ask whether to run `imf-web-ui-audit full`. Run it only after an explicit yes.
156
+ Offer `imf-web-ui-audit full` as the next step: the migration check covered what the releases changed, the audit checks the
157
+ whole project against the conventions and changes nothing. Run it only after an explicit yes.
123
158
 
124
159
  For approved migration work, ask: **Approve these consumer migration changes and commit them separately?** Then stage only
125
160
  the approved paths, verify again, and use a separate imperative commit message.
@@ -0,0 +1,95 @@
1
+ ---
2
+ name: imf-web-ui-user-profile
3
+ description:
4
+ "Read or create the person's profile: technical background, experience, how they want things explained, and how they like
5
+ to work. Invoke it first in every Web UI skill, and when the person asks to change their profile or how the agent explains
6
+ or paces work."
7
+ user-invocable: false
8
+ allowed-tools: Bash Read Write
9
+ ---
10
+
11
+ # Fit the work to the person
12
+
13
+ The profile records who the person is and how they learn, so every Web UI workflow explains what they need and paces the work
14
+ the way they like. Read it once per session; later skills in the same session reuse what is already loaded.
15
+
16
+ ## Read the profile
17
+
18
+ Resolve the profile path with the shell, then read that exact path:
19
+
20
+ ```sh
21
+ printf '%s\n' "${XDG_CONFIG_HOME:-$HOME/.config}/imfusion/web-ui/consumer-profile.md"
22
+ ```
23
+
24
+ The profile sits outside the project: it belongs to the person, never to the repository, so read-only promises such as the
25
+ audit's still hold when this skill writes it.
26
+
27
+ When the file exists, apply it and return to the calling workflow without comment. When it is missing, run the interview
28
+ before the workflow starts. When the router skips companions for a small task, do the task first and offer the interview
29
+ afterwards.
30
+
31
+ ## Interview
32
+
33
+ Open with one question: may you ask six short questions and save the answers to the profile path, so every later workflow
34
+ fits them and they are never asked again? Mention that they can decline any single question. On no, use the defaults below
35
+ for this session and do not offer the interview again in it.
36
+
37
+ On yes, ask one question per message, in plain prose, and wait for each answer:
38
+
39
+ 1. What is your name?
40
+ 2. What is your technical background: the languages and tools you work with?
41
+ 3. How much have you built for the web, for example with React, HTML, and CSS?
42
+ 4. Beyond Git, how comfortable are you with npm and the terminal?
43
+ 5. How much explanation do you want: just the results, a short gloss for new terms, or the reasoning behind each step?
44
+ 6. How do you like to work: pause after every step, pause after each finished piece, or work freely and stop only before a
45
+ commit?
46
+
47
+ Derive the levels from the answers; ask a short follow-up only when an answer fits no level. The person can decline any
48
+ question: its field stays out of the file, and its default applies: `some`, `comfortable`, `terms`, `slice`.
49
+
50
+ ## The file
51
+
52
+ Show the profile below before writing it. The person can correct or remove any line, or reject the whole profile; on a
53
+ rejection, save nothing and use the defaults for this session. After they confirm, write it and name its path so they can
54
+ edit or delete it later:
55
+
56
+ ```markdown
57
+ ---
58
+ name: <their name>
59
+ frontend: none | some | seasoned
60
+ tooling: new | comfortable
61
+ explanation: results | terms | reasoning
62
+ pace: step | slice | commit
63
+ ---
64
+
65
+ ## Background
66
+
67
+ <their answer to question 2, in their words>
68
+
69
+ ## Notes
70
+
71
+ - <lasting preferences learned later>
72
+ ```
73
+
74
+ When the write fails, keep the answers for this session. When the person later states a lasting preference about how to work
75
+ with them, such as a language, a term they want avoided, or a tool they already know, add it under `Notes` and tell them.
76
+ When they ask to change their profile, run the interview again with the current answers as defaults.
77
+
78
+ ## Apply the profile
79
+
80
+ The fields apply independently.
81
+
82
+ - **Name**: address the person by name.
83
+ - **Background**: explain by analogy to what they already know, such as a component compared to a class for a Java developer.
84
+ - **Frontend `none` or `some`**: give a one-line gloss the first time a frontend term appears, such as component, prop,
85
+ design token, CSS layer, or Storybook. For `none`, also say what a finding means for the running app.
86
+ - **Tooling `new`**: gloss tooling terms on first use, such as lockfile, dist-tag, prerelease, hook, harness, or the
87
+ `AGENTS.md` fence; say in one plain sentence what each command does before it runs, read-only checks included; and before
88
+ an approval question, say what yes changes and how to undo it.
89
+ - **Explanation**: `results` adds nothing beyond what the experience levels call for; `terms` glosses every new term;
90
+ `reasoning` also says why each step happens, and after a report block, what happened and what comes next.
91
+ - **Pace**: `step` ends the reply after each step or phase of the calling workflow and waits for a go-ahead; `slice` pauses
92
+ after each working piece; `commit` runs freely between the workflow's own approval points.
93
+
94
+ Pace adds pauses on top of the calling workflow's approval gates and keeps every one of them. Put explanations around report
95
+ blocks and approval questions, never inside them.
@@ -10,6 +10,8 @@ description:
10
10
  Use this skill for screen-level decisions. Verify component APIs with `imf-web-ui-components`; put code and styling rules in
11
11
  `imf-web-ui-conventions`.
12
12
 
13
+ Invoke `imf-web-ui-user-profile` first and explain at its levels throughout.
14
+
13
15
  The identity index marks components as stable or experimental. Experimental components are usable, but prefer wrapping one
14
16
  when it is used across many call sites so API movement stays local.
15
17