@imfusion/web-ui 0.6.4-dev.57.g664ba66a → 0.6.4-dev.58.g88c8fcaa

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 (58) hide show
  1. package/README.md +19 -54
  2. package/dist/assets/vendors/base-ui.d.ts +2 -3
  3. package/dist/breakpoints/min-width.d.ts +3 -7
  4. package/dist/breakpoints/registry.d.ts +3 -9
  5. package/dist/codegen/gen-breakpoints-css.d.ts +0 -4
  6. package/dist/codegen/gen-token-css.d.ts +0 -2
  7. package/dist/components/button/button.d.ts +1 -1
  8. package/dist/components/callout/callout.d.ts +7 -10
  9. package/dist/components/card/card.d.ts +2 -4
  10. package/dist/components/chip/chip.cva.d.ts +2 -4
  11. package/dist/components/code/code.d.ts +1 -1
  12. package/dist/components/logo/imfusion/imfusion.d.ts +1 -4
  13. package/dist/components/logo/logo.d.ts +1 -1
  14. package/dist/components/navigation-menu/subs/flyout-link.d.ts +3 -5
  15. package/dist/components/navigation-menu/subs/inline-submenu.d.ts +2 -4
  16. package/dist/components/navigation-menu/subs/trigger.d.ts +5 -7
  17. package/dist/components/number-field/number-field.d.ts +2 -3
  18. package/dist/components/select/select.d.ts +3 -3
  19. package/dist/components/stack/stack.d.ts +2 -3
  20. package/dist/components/table/table.d.ts +3 -5
  21. package/dist/components/tabs/tabs.d.ts +5 -8
  22. package/dist/components/tooltip/tooltip.d.ts +5 -8
  23. package/dist/components/typo/typo.d.ts +1 -3
  24. package/dist/docgen/gen-docgen.utils.d.ts +3 -4
  25. package/dist/hooks/use-color-scheme.d.ts +5 -11
  26. package/dist/hooks/use-media-query.d.ts +2 -7
  27. package/dist/integrations/image-display-options/image-display-options-view.utils.d.ts +0 -1
  28. package/dist/style.css +1 -1
  29. package/dist/tokens/apply.d.ts +4 -9
  30. package/dist/tokens/control-registry.d.ts +3 -6
  31. package/dist/tokens/types.d.ts +7 -24
  32. package/dist/tokens/use-token-controls.d.ts +3 -12
  33. package/dist/types/meta.d.ts +15 -32
  34. package/dist/vite/readable-css-module-names.d.ts +3 -12
  35. package/dist/web-ui-cli.js +322 -0
  36. package/docs/user-guide/AgentTooling.mdx +127 -0
  37. package/docs/user-guide/BrandAssets.mdx +25 -28
  38. package/docs/user-guide/GettingStarted.mdx +34 -19
  39. package/docs/user-guide/HowItsBuilt.mdx +92 -12
  40. package/docs/user-guide/Tokens.mdx +12 -10
  41. package/docs/user-guide/UsagePatterns.mdx +64 -21
  42. package/package.json +6 -5
  43. package/src/docgen/doc.gen.json +20 -20
  44. package/src/llms/install-templates/AGENTS.md +4 -4
  45. package/src/llms/install-templates/hooks/baseline-staleness.sh +9 -2
  46. package/src/llms/skills/imf-web-ui/SKILL.md +8 -9
  47. package/src/llms/skills/imf-web-ui-audit/SKILL.md +4 -4
  48. package/src/llms/skills/imf-web-ui-components/SKILL.md +3 -0
  49. package/src/llms/skills/imf-web-ui-conventions/templates/AUDIT_CHECKLIST.md +0 -1
  50. package/src/llms/skills/imf-web-ui-conventions/topics/agent-tooling.md +15 -10
  51. package/src/llms/skills/imf-web-ui-conventions/topics/git.md +2 -1
  52. package/src/llms/skills/imf-web-ui-conventions/topics/styling.md +1 -1
  53. package/src/llms/skills/imf-web-ui-conventions/topics/tooling.md +1 -1
  54. package/src/llms/skills/imf-web-ui-setup/SKILL.md +1 -1
  55. package/src/llms/skills/imf-web-ui-update/SKILL.md +15 -13
  56. package/bin/install.js +0 -446
  57. package/docs/user-guide/AiAgents.mdx +0 -51
  58. package/docs/user-guide/Introduction.mdx +0 -21
@@ -65,7 +65,7 @@
65
65
  "button": {
66
66
  "root": {
67
67
  "name": "Button",
68
- "description": "Button component",
68
+ "description": "Button",
69
69
  "props": [
70
70
  {
71
71
  "name": "chamfer",
@@ -165,7 +165,7 @@
165
165
  "callout": {
166
166
  "root": {
167
167
  "name": "Callout.Root",
168
- "description": "Callout.Root — the banner container. Sets the `variant` (which tints the\nsurface and colours the icon and text) and lays out a leading `Callout.Icon`\nbeside a text region of `Callout.Title` / `Callout.Description`. `maxWidth`\ncaps the banner so it reads as a block region rather than stretching full\ncontainer width. A persistent element in the content flow — not a transient\nToast, not a modal Alert Dialog.",
168
+ "description": "Callout.Root — the banner container. Sets `variant` (tints surface, icon, and text) and lays\nout a leading `Callout.Icon` beside `Callout.Title` / `Callout.Description`. `maxWidth` caps\nthe banner so it reads as a block region, not full container width. A persistent content-flow\nelement — not a transient Toast, not a modal Alert Dialog.",
169
169
  "props": [
170
170
  {
171
171
  "name": "maxWidth",
@@ -191,7 +191,7 @@
191
191
  },
192
192
  {
193
193
  "name": "Callout.Icon",
194
- "description": "Callout.Icon — the leading status glyph. With no children it renders the\nvariant's default local icon; pass a custom icon as children to override.\n`aria-hidden` (the variant is conveyed by copy, not the glyph) and inherits\nthe status colour via `currentColor`.",
194
+ "description": "Callout.Icon — the leading status glyph. Renders the variant's default icon when no children\nare passed; pass a custom icon as children to override. `aria-hidden` (variant is conveyed by\ncopy) and inherits colour via `currentColor`.",
195
195
  "props": []
196
196
  },
197
197
  {
@@ -204,7 +204,7 @@
204
204
  "card": {
205
205
  "root": {
206
206
  "name": "Card.Root",
207
- "description": "Card.Root — a surface container composed of slots: an optional `Card.Image`\n(bleeds edge-to-edge, no padding), then `Card.Header` / `Card.Content` /\n`Card.Footer`. `density` sets one scale that drives both each slot's padding\nand the gap between slots. `variant` picks the look — neutral tonal surfaces\n(`main`/`support`/`minor`) carry a hairline border; coloured intent fills\n(`primary`/`brand`) flip to contrast text and drop the border. `shadow` and\n`radius` layer on top. Also called a panel, tile, or paper.\n\nThe image is always the first entry in the stack, so `orientation` just\nswitches the stack between a column and a row without reordering slots.\n\nThe ImFusion brand ships flat (`shadow=\"none\"`), but the shadow scale is a\nfirst-class opt-in axis for third-party consumers. `shadow` picks the elevation\nlevel only — how hard or spread that shadow reads is a global lighting decision,\nowned by the `--imf-ui-shadow-hardness` / `--imf-ui-shadow-spread` tokens.",
207
+ "description": "Card.Root — a surface container composed of slots: an optional `Card.Image`\n(bleeds edge-to-edge, no padding), then `Card.Header` / `Card.Content` /\n`Card.Footer`. `density` sets one scale that drives both each slot's padding\nand the gap between slots. `variant` picks the look — neutral tonal surfaces\n(`main`/`support`/`minor`) carry a hairline border; coloured intent fills\n(`primary`/`brand`) flip to contrast text and drop the border. `shadow` and\n`radius` layer on top. Also called a panel, tile, or paper.\n\nThe image is always the first entry in the stack, so `orientation` just\nswitches the stack between a column and a row without reordering slots.\n\n`shadow` defaults to `lg`; `shadow=\"none\"` gives the flat surface. It picks the elevation level only: how hard or\nspread the shadow reads is global, set by `--imf-ui-shadow-hardness` and `--imf-ui-shadow-spread`.",
208
208
  "props": [
209
209
  {
210
210
  "name": "density",
@@ -602,7 +602,7 @@
602
602
  },
603
603
  {
604
604
  "name": "Code.InlineLink",
605
- "description": "Code.InlineLink — the inline-code chip rendered as a link: the same hairline\nbox, with an optional directional arrow behind the separator instead of a copy button.\nSibling of `Code.Inline`, sharing its chip visual (`.inline`) — never both a\ncopy button and a link on the same chip. Mirrors `ChipLink`'s shape (anchor\nis the chip root, trailing icon nudges on hover, `data-kind` picks the icon).",
605
+ "description": "Code.InlineLink — the inline-code chip rendered as a link: the same hairline\nbox, with an optional directional arrow behind the separator instead of a copy button.\nSibling of `Code.Inline`, sharing its chip visual (`.inline`). Never both a\ncopy button and a link on the same chip. Mirrors `ChipLink`'s shape (anchor\nis the chip root, trailing icon nudges on hover, `data-kind` picks the icon).",
606
606
  "props": [
607
607
  {
608
608
  "name": "kind",
@@ -2097,7 +2097,7 @@
2097
2097
  "required": true,
2098
2098
  "type": "ReactNode",
2099
2099
  "defaultValue": null,
2100
- "description": "Logo source — an image URL or an inline SVG node. Required; this primitive carries no brand default (see `ImFusionLogo` for our own mark)."
2100
+ "description": "Logo source — an image URL or inline SVG node. No brand default; see `ImFusionLogo` for the ImFusion mark."
2101
2101
  },
2102
2102
  {
2103
2103
  "name": "variant",
@@ -2313,7 +2313,7 @@
2313
2313
  },
2314
2314
  {
2315
2315
  "name": "NavigationMenu.FlyoutLink",
2316
- "description": "NavigationMenu.FlyoutLink — a quiet text link inside a flyout `Content`, the\nlightweight alternative to a `LinkCard` when a card is too heavy. Renders an\n`<a>`. A trailing `ArrowRight` slides in on hover/focus and the label nudges to\nmeet it; the current page is marked in primary. When a custom `render` is\nsupplied the icon is omitted — the consumer's element owns its content.",
2316
+ "description": "NavigationMenu.FlyoutLink — a quiet text link inside a flyout `Content`, the lightweight\nalternative to `LinkCard`. Renders an `<a>`; a trailing `ArrowRight` slides in on hover/focus,\nand the current page is marked in primary. A custom `render` omits the icon.",
2317
2317
  "props": [
2318
2318
  {
2319
2319
  "name": "active",
@@ -2395,7 +2395,7 @@
2395
2395
  },
2396
2396
  {
2397
2397
  "name": "NavigationMenu.InlineSubmenu",
2398
- "description": "NavigationMenu.InlineSubmenu — a master/detail submenu that stays inside one\nflyout: a category rail beside (or, on narrow viewports, above) its detail.\n\nA curated partial over the namespace's own primitives (a nested vertical\n`Root` without a `Portal`, plus the rail/detail layout). Drop it directly\ninside a `NavigationMenu.Content`. It bakes in Base UI's viewport\nresponsiveness: the nested Root flips `orientation` at `md` via `useMediaQuery`\nand the CSS flips the rail from a horizontal tab strip to a side rail at the\nsame breakpoint — no work for the consumer, no container queries.",
2398
+ "description": "NavigationMenu.InlineSubmenu — a master/detail submenu that stays inside one\nflyout: a category rail beside (or, on narrow viewports, above) its detail.\n\nA curated partial over the namespace's own primitives (a nested vertical\n`Root` without a `Portal`, plus the rail/detail layout). Drop it directly\ninside a `NavigationMenu.Content`. Switches from a tab strip to a side rail\nat `md` — no work for the consumer, no container queries.",
2399
2399
  "props": [
2400
2400
  {
2401
2401
  "name": "defaultValue",
@@ -2824,14 +2824,14 @@
2824
2824
  },
2825
2825
  {
2826
2826
  "name": "NavigationMenu.Trigger",
2827
- "description": "NavigationMenu.Trigger — opens an item's flyout on hover or click. Renders a\n`<button>`. Ships a built-in `ChevronDown` (rotates when open) so consumers\ndon't hand-author an indicator; pass `hideChevron` to supply a custom `Icon`,\nand `nested` when the trigger opens a submenu from inside another flyout.",
2827
+ "description": "NavigationMenu.Trigger — opens an item's flyout on hover or click. Renders a\n`<button>` with a built-in `ChevronDown` that rotates when open; pass\n`hideChevron` for a custom `Icon`, and `nested` for a trigger inside a flyout.",
2828
2828
  "props": [
2829
2829
  {
2830
2830
  "name": "active",
2831
2831
  "required": false,
2832
2832
  "type": "boolean",
2833
2833
  "defaultValue": "false",
2834
- "description": "Marks this section as the current page so it shows the active treatment even\nwhen its flyout is closed — the \"active trail\" anchor for a nav where the\nopen section isn't the current one. Base UI's Trigger has no active state of\nits own, so this stamps `data-active`."
2834
+ "description": "Marks this section as the current page, showing the active treatment even when its\nflyout is closed. Base UI's Trigger has no active state of its own, so this stamps\n`data-active`."
2835
2835
  },
2836
2836
  {
2837
2837
  "name": "className",
@@ -3519,7 +3519,7 @@
3519
3519
  "required": false,
3520
3520
  "type": "ReactNode",
3521
3521
  "defaultValue": null,
3522
- "description": "Content rendered above the field as a drag handle: pressing it and moving\nsideways changes the value. Usually the field's label. The scrub cursor is\nsupplied automatically."
3522
+ "description": "Drag handle rendered above the field: press and move sideways to change the value, usually\nthe field's label. The scrub cursor is supplied automatically."
3523
3523
  },
3524
3524
  {
3525
3525
  "name": "size",
@@ -4276,7 +4276,7 @@
4276
4276
  "select": {
4277
4277
  "root": {
4278
4278
  "name": "Select.Root",
4279
- "description": "Select.Root — accessible select / listbox primitive.\n\nRenders a thin wrapper div so that a sibling Select.Label stacks above the\nSelect.Trigger regardless of the parent's layout. Select.Portal is unaffected\n(it renders to document.body).",
4279
+ "description": "Select.Root — accessible select / listbox primitive.\n\nWraps children in a div so a sibling Select.Label stacks above Select.Trigger\nregardless of the parent's layout. Select.Portal is unaffected (it renders to\ndocument.body).",
4280
4280
  "props": [
4281
4281
  {
4282
4282
  "name": "actionsRef",
@@ -5774,7 +5774,7 @@
5774
5774
  "stack": {
5775
5775
  "root": {
5776
5776
  "name": "Stack",
5777
- "description": "Stack — vertical layout primitive.\n\nCopied and adapted from Mantine's Stack; no upstream runtime\ndependency. Pure column flex container with token-driven gap and constrained\nalign/justify unions.",
5777
+ "description": "Stack — vertical layout primitive.\n\nAdapted from Mantine's Stack, no upstream runtime dependency: a pure column\nflex container with token-driven gap and constrained align/justify unions.",
5778
5778
  "props": [
5779
5779
  {
5780
5780
  "name": "align",
@@ -6003,7 +6003,7 @@
6003
6003
  },
6004
6004
  {
6005
6005
  "name": "Table.SortableHeaderCell",
6006
- "description": "Table.SortableHeaderCell — a partial: a header cell whose label is a sort\ntoggle, pre-composing HeaderCell + HeaderButton so the `aria-sort` state and\ndirection indicator don't get re-derived per consumer app. Headless-upstream-\nagnostic: feed it `sortDirection` and `onToggle` (e.g. from a TanStack\ncolumn). Omit `onToggle` and it renders a plain non-sortable header cell.",
6006
+ "description": "Table.SortableHeaderCell — a header cell whose label is a sort toggle,\npre-composing HeaderCell + HeaderButton so `aria-sort` and the direction\nindicator aren't re-derived per consumer. Omit `onToggle` for a plain cell.",
6007
6007
  "props": [
6008
6008
  {
6009
6009
  "name": "sortDirection",
@@ -6082,7 +6082,7 @@
6082
6082
  "subComponents": [
6083
6083
  {
6084
6084
  "name": "Tabs.Indicator",
6085
- "description": "Tabs.Indicator — the bordered box marking the active tab, overlapping the\nshared hairline border to visually fuse the active tab with the panel\nframe beneath it. Positioned via the `--active-tab-*` CSS custom\nproperties Base UI writes onto it; render once per Tabs.List, after the\nTabs.Tab list.",
6085
+ "description": "Tabs.Indicator — the bordered box marking the active tab, positioned via\nthe `--active-tab-*` CSS custom properties Base UI writes onto it. Render\nonce per Tabs.List, after the Tabs.Tab list.",
6086
6086
  "props": [
6087
6087
  {
6088
6088
  "name": "className",
@@ -6226,7 +6226,7 @@
6226
6226
  },
6227
6227
  {
6228
6228
  "name": "Tabs.PanelViewport",
6229
- "description": "Tabs.PanelViewport — the shared frame Tabs.Panel elements render inside.\nNo Base UI equivalent exists (upstream leaves this as a plain wrapper div\nin its own reference); we surface it as a named part since its hairline\nborder is what Tabs.Indicator visually fuses into.",
6229
+ "description": "Tabs.PanelViewport — the shared frame Tabs.Panel elements render inside.\nNo Base UI equivalent exists; it's surfaced as a named part since its\nhairline border is what Tabs.Indicator visually fuses into.",
6230
6230
  "props": []
6231
6231
  },
6232
6232
  {
@@ -7237,7 +7237,7 @@
7237
7237
  },
7238
7238
  {
7239
7239
  "name": "Tooltip.Positioner",
7240
- "description": "Tooltip.Positioner — positions the popup relative to the trigger via\nfloating-point layout.\n\n`sideOffset` defaults to `--arrow-size` (tooltip.module.css) + 4px — enough\ngap for the arrow to bridge with a few px of breathing room past its tip,\nrather than landing flush on the trigger. Keep the two in sync if either\nchanges.",
7240
+ "description": "Tooltip.Positioner — positions the popup relative to the trigger via\nfloating-point layout.\n\n`sideOffset` defaults to `--arrow-size` (tooltip.module.css) + 4px, for\ngap past the arrow tip. Keep the two values in sync.",
7241
7241
  "props": [
7242
7242
  {
7243
7243
  "name": "align",
@@ -7410,7 +7410,7 @@
7410
7410
  "required": false,
7411
7411
  "type": "number",
7412
7412
  "defaultValue": "250",
7413
- "description": "Milliseconds to wait before opening on hover. Defaults to a snappier value\nthan Base UI's 600ms — a deliberate imf default per \"make the correct\nchoice the easy one\". Grouped triggers under a `Tooltip.Provider` open\ninstantly after the first regardless of this value."
7413
+ "description": "Milliseconds to wait before opening on hover. Defaults to less than Base\nUI's 600ms, deliberately. Grouped triggers under a `Tooltip.Provider` open instantly\nafter the first, regardless of this value."
7414
7414
  },
7415
7415
  {
7416
7416
  "name": "disabled",
@@ -7746,7 +7746,7 @@
7746
7746
  },
7747
7747
  {
7748
7748
  "name": "Typo.InlineCode",
7749
- "description": "Typo.InlineCode — inline code fragment. Thin wrapper over `Code.Inline`, which\nowns the inline-code styling; the rendered `<code>` carries the `Code.Inline`\nidentity. Unlike other Typo members it has no color-`variant` axis — inline\ncode is a fixed neutral chip.",
7749
+ "description": "Typo.InlineCode — inline code fragment. Thin wrapper over `Code.Inline`, which\nowns the styling and identity. No color-`variant` axis — it's a fixed neutral chip.",
7750
7750
  "props": [
7751
7751
  {
7752
7752
  "name": "children",
@@ -8054,7 +8054,7 @@
8054
8054
  },
8055
8055
  {
8056
8056
  "name": "CodeHighlight.InlineLink",
8057
- "description": "Code.InlineLink — the inline-code chip rendered as a link: the same hairline\nbox, with an optional directional arrow behind the separator instead of a copy button.\nSibling of `Code.Inline`, sharing its chip visual (`.inline`) — never both a\ncopy button and a link on the same chip. Mirrors `ChipLink`'s shape (anchor\nis the chip root, trailing icon nudges on hover, `data-kind` picks the icon).",
8057
+ "description": "Code.InlineLink — the inline-code chip rendered as a link: the same hairline\nbox, with an optional directional arrow behind the separator instead of a copy button.\nSibling of `Code.Inline`, sharing its chip visual (`.inline`). Never both a\ncopy button and a link on the same chip. Mirrors `ChipLink`'s shape (anchor\nis the chip root, trailing icon nudges on hover, `data-kind` picks the icon).",
8058
8058
  "props": [
8059
8059
  {
8060
8060
  "name": "kind",
@@ -20,11 +20,11 @@ or suggesting a command.
20
20
 
21
21
  <The installer owns only the fenced block below. It refreshes that block on every install; the rest belongs to the project.>
22
22
 
23
- <!-- imf-web-ui:begin — managed by `npx web-ui-install`; edits inside the fence are overwritten -->
23
+ <!-- imf-web-ui:begin — managed by `npx web-ui install`; edits inside the fence are overwritten -->
24
24
 
25
- `.agents/skills/imf-web-ui-*` is vendored from `@imfusion/web-ui` and resynced with `npx web-ui-install`. Do not edit the
26
- vendored copy or put project-specific conventions there. Load the matching skill before changing UI, styles, data, tests, or
27
- docs.
25
+ `.agents/skills/imf-web-ui-*` is vendored from `@imfusion/web-ui` and resynced with `npx web-ui install skills`. Do not edit
26
+ the vendored copy or put project-specific conventions there. Load the matching skill before changing UI, styles, data, tests,
27
+ or docs.
28
28
 
29
29
  <!-- imf-web-ui:end -->
30
30
 
@@ -6,11 +6,18 @@ PKG=node_modules/@imfusion/web-ui/package.json
6
6
  [ -f "$PKG" ] || exit 0
7
7
  CURRENT=$(node -p "require('./$PKG').version" 2>/dev/null) || exit 0
8
8
 
9
- for marker in .agents/skills/imf-web-ui-*/.imf-web-ui-skill-version.json; do
9
+ # .claude/skills may be a symlink to .agents/skills; skip markers already read.
10
+ seen=""
11
+ for marker in .agents/skills/imf-web-ui*/.imf-web-ui-skill-version.json .claude/skills/imf-web-ui*/.imf-web-ui-skill-version.json; do
10
12
  [ -f "$marker" ] || continue
13
+ real=$(cd "$(dirname "$marker")" && pwd -P)/$(basename "$marker")
14
+ case " $seen " in
15
+ *" $real "*) continue ;;
16
+ esac
17
+ seen="$seen $real"
11
18
  INSTALLED=$(node -p "require('./$marker').version" 2>/dev/null) || continue
12
19
  if [ "$INSTALLED" != "$CURRENT" ]; then
13
- echo "imf-web-ui skills are stale ($INSTALLED installed, package is $CURRENT) — run: npx web-ui-install"
20
+ echo "imf-web-ui skills are stale ($INSTALLED installed, package is $CURRENT) — run /imf-web-ui-update, or: npx web-ui install skills && npx web-ui install hooks"
14
21
  break
15
22
  fi
16
23
  done
@@ -42,15 +42,14 @@ one-file edit.
42
42
 
43
43
  Read only the matching page under `node_modules/@imfusion/web-ui/docs/user-guide/` in the consumer project:
44
44
 
45
- | Question | Page |
46
- | --------------------------------------------------------------- | -------------------- |
47
- | What the library provides | `Introduction.mdx` |
48
- | Installation, stylesheet, and provider wiring | `GettingStarted.mdx` |
49
- | Favicons, social sharing images, and static brand files | `BrandAssets.mdx` |
50
- | Composition, CSS overrides, state attributes, and color schemes | `UsagePatterns.mdx` |
51
- | Token families and customization | `Tokens.mdx` |
52
- | Agent skills and their installation | `AiAgents.mdx` |
53
- | Library boundaries and implementation choices | `HowItsBuilt.mdx` |
45
+ | Question | Page |
46
+ | ------------------------------------------------------------------------ | -------------------- |
47
+ | What the library provides, installation, stylesheet, and provider wiring | `GettingStarted.mdx` |
48
+ | Favicons, social sharing images, and static brand files | `BrandAssets.mdx` |
49
+ | Composition, CSS overrides, state attributes, and color schemes | `UsagePatterns.mdx` |
50
+ | Token families and customization | `Tokens.mdx` |
51
+ | Agent skills, hooks, and their installation | `AgentTooling.mdx` |
52
+ | Library boundaries and implementation choices | `HowItsBuilt.mdx` |
54
53
 
55
54
  Read MDX as text. Its imports, JSX previews, and Storybook navigation are presentation, not instructions to install or run
56
55
  Storybook in the consumer. Cite the packaged page when answering a library question. Use `imf-web-ui-components` for exact
@@ -13,11 +13,11 @@ allowed-tools: Read Glob Grep
13
13
  This is a read-only audit. Its job is to align a project with its conventions: compare the project against the selected
14
14
  `imf-web-ui-conventions` topics, report evidence, and end with work the human can approve.
15
15
 
16
- A gap against a convention is high severity. The project agreed to those conventions, so the finding carries no argument
17
- about whether it matters, and a deliberate reason to differ is the only thing that lowers it. Say what that reason is.
16
+ A gap against a convention is high severity: the project agreed to the conventions. Only a deliberate, stated reason to
17
+ differ lowers it.
18
18
 
19
- Anything else you notice belongs under `Suggestions`: what running the code revealed, what an investigation turned up, what a
20
- reader would tidy on the way past. Report it, keep it low, and do not let it crowd the sections a consumer has to act on.
19
+ Anything else belongs under `Suggestions`: findings from running the code, investigating, or reading through. Report it, keep
20
+ it low, and do not let it crowd the sections a consumer has to act on.
21
21
 
22
22
  ## Workflow
23
23
 
@@ -39,6 +39,9 @@ Use the generated package indexes. They are smaller and more reliable than readi
39
39
  Use `doc.gen.json` for Web UI props. A linked upstream page is useful for behavior, composition, and accessibility, but its
40
40
  prop table is not authoritative for this package.
41
41
 
42
+ A `variant` value belongs to the component that defines it; one component's list is not a global one. `brand` means identity
43
+ color and `primary` means the action color, even where they look alike.
44
+
42
45
  ## If the component is missing
43
46
 
44
47
  Treat a missing identity-index entry as a real gap. Do not invent an API or silently import the upstream component. Report
@@ -37,7 +37,6 @@ sections one to one — change a topic's sections and this file follows in the s
37
37
  - [ ] Compose, don't configure
38
38
  - [ ] Put state where its truth lives
39
39
  - [ ] Effects: last resort, and named
40
- - [ ] Reading list
41
40
 
42
41
  ## Components — `components`
43
42
 
@@ -1,33 +1,38 @@
1
1
  # Agent tooling
2
2
 
3
- `npx web-ui-install` manages the Web UI skills and optional lifecycle hooks in a consumer project. This topic explains the
4
- choices around that installer.
3
+ `npx web-ui install` manages the Web UI skills and optional lifecycle hooks in a consumer project.
5
4
 
6
5
  ## The skill bundle
7
6
 
8
- Run:
7
+ Run, on a first install:
9
8
 
10
9
  ```sh
11
- npx web-ui-install
10
+ npx web-ui install skills --harness=claude
12
11
  ```
13
12
 
14
13
  It installs or refreshes the `imf-web-ui-*` skills, updates the managed `AGENTS.md` fence, and removes skills that the
15
- package no longer ships. The installer remembers `.claude/skills/`, `.agents/skills/`, or both. Use `--target claude|agents`
16
- to choose explicitly and `--reconfigure` to choose again.
14
+ package no longer ships. The skills always live in `.agents/skills/`. `--harness` selects `claude`, which also links each
15
+ skill into `.claude/skills/`, `codex`, or `all`; without it, the command prompts and remembers the choice. Pass
16
+ `--reconfigure` to choose again. On a project that already has an install, re-running `install skills` without `--harness`
17
+ reuses the remembered harness instead of narrowing it.
17
18
 
18
19
  Skill version markers (`.imf-web-ui-skill-version.json`) show which package version installed each skill. Refresh them with
19
20
  the installer; do not hand-edit the vendored files.
20
21
 
21
22
  ## The hooks
22
23
 
23
- Install the optional lifecycle hooks with:
24
+ `install hooks` requires the skills to already be installed for the target harness; without them, it errors and tells you to
25
+ run `install skills` first:
24
26
 
25
27
  ```sh
26
- npx web-ui-install --hooks
28
+ npx web-ui install skills --harness=claude
29
+ npx web-ui install hooks --harness=claude
27
30
  ```
28
31
 
29
- The installer owns the scripts under `.agents/hooks/imf-web-ui/` and merges its registrations into Claude Code and Codex
30
- settings. It refreshes scripts and removes retired registrations without replacing unrelated entries.
32
+ The installer owns the scripts under `.agents/hooks/imf-web-ui/` and merges its registrations into the registration file for
33
+ the chosen harness only: Claude Code's `.claude/settings.json`, Codex's `.codex/hooks.json`, or both with `--harness=all`. It
34
+ refreshes scripts and removes retired registrations without replacing unrelated entries, and removes its registrations from a
35
+ harness that is not selected.
31
36
 
32
37
  The shipped events are:
33
38
 
@@ -27,4 +27,5 @@ The scripts under `scripts/verify/` own the step lists. Hooks and npm scripts on
27
27
  ## Staleness at commit time
28
28
 
29
29
  Pre-commit also runs advisory checks for vendored skill markers and documentation drift. If a staged change makes a doc
30
- stale, update the doc in the same commit. For an outdated installed skill, run `npx web-ui-install` in the consumer project.
30
+ stale, update the doc in the same commit. For an outdated installed skill, run `npx web-ui install skills` (also
31
+ `npx web-ui install hooks` if the project uses hooks) with the project's existing `--harness` in the consumer project.
@@ -45,7 +45,7 @@ Do not target generated CSS Module class names and do not use `!important` to fi
45
45
  hook, not a state flag.
46
46
 
47
47
  ```css
48
- [data-imf-ui-component="Switch"][data-checked] {
48
+ [data-imf-ui-component="Switch.Root"][data-checked] {
49
49
  outline: var(--imf-ui-border-size-2) solid var(--imf-ui-color-fg-positive);
50
50
  }
51
51
  ```
@@ -1,6 +1,6 @@
1
1
  # Tooling
2
2
 
3
- Read this topic before adding a dependency or configuring a tool. Use the tool's current documentation rather than memory.
3
+ Use the tool's current documentation rather than memory.
4
4
 
5
5
  ## Topic-to-tool map
6
6
 
@@ -50,7 +50,7 @@ The plan describes the exact starter files. It does not copy a generic starter p
50
50
 
51
51
  ## Installer steps
52
52
 
53
- For `agent-tooling`, list the `npx web-ui-install` commands as steps for the human. Read existing registrations first and do
53
+ For `agent-tooling`, list the `npx web-ui install` commands as steps for the human. Read existing registrations first and do
54
54
  not stack a hook on an event the project already covers. Include the Codex trust review when hooks are part of the plan.
55
55
 
56
56
  ## Safety
@@ -18,12 +18,11 @@ Never overwrite user changes or commit without fresh approval.
18
18
  1. Work from the frontend package root. In a monorepo, find the package that owns the Web UI dependency.
19
19
  2. Read its `package.json`, lockfile, and repository instructions. npm with `package-lock.json` is the expected setup; stop
20
20
  if another lockfile is the active one.
21
- 3. Record `git status --short`, the installed Web UI version, the installed skill targets, hooks, registrations, and
21
+ 3. Record `git status --short`, the installed Web UI version, the installed skill harness(es), hooks, registrations, and
22
22
  `AGENTS.md` fence.
23
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, rather than deciding it falls outside this workflow's paths. What the update touches is not
25
- knowable until it runs, and the person can commit, stash, or wave it through in one reply. Never reset, clean, restore, or
26
- hide their work.
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.
27
26
  5. With `--dry-run`, stop after reporting what would happen. Do not install, format, stage, commit, or ask for commit
28
27
  approval.
29
28
 
@@ -41,22 +40,25 @@ whether to use `latest` or `dev` before proceeding. Resolve the selected tag or
41
40
  registry lookup fails. Report "already current" only when the pre-update version matches this resolved target; npm's "up to
42
41
  date" message alone does not prove that.
43
42
 
44
- Install the resolved version, then refresh the existing installer target:
43
+ Install the resolved version, then refresh the existing installer harness (run `install hooks` too only if the project
44
+ already has hooks installed):
45
45
 
46
46
  ```sh
47
47
  npm install @imfusion/web-ui@<resolved-version>
48
- npx web-ui-install
49
- npx web-ui-install --hooks
48
+ npx web-ui install skills
49
+ npx web-ui install hooks
50
50
  ```
51
51
 
52
- Stop on install failure. Preserve the installer's existing target. Do not use `--force` or `--legacy-peer-deps`.
52
+ Both commands reuse the recorded harness. An install from the old `web-ui-install` has no record: pass the project's existing
53
+ harness once, e.g. `--harness=all`. Stop on install failure. Do not use `--force` or `--legacy-peer-deps`.
53
54
 
54
- The installer owns the vendored skills, its `AGENTS.md` fence, and hook scripts. Run both installer commands after the
55
- package update even when the existing registrations look complete: they refresh scripts, prune retired registrations, and
56
- merge installer-owned entries idempotently into `.claude/settings.json` and `.codex/hooks.json`. Stop on malformed settings
57
- or installer conflicts. Read existing host registrations first and do not stack an event the project already covers.
55
+ The installer owns the vendored skills, its `AGENTS.md` fence, and hook scripts. Run the installer commands after the package
56
+ update even when the existing registrations look complete: they refresh scripts, prune retired registrations, and merge
57
+ installer-owned entries idempotently into the registration file for the chosen harness (`.claude/settings.json`,
58
+ `.codex/hooks.json`, or both). Stop on malformed settings or installer conflicts. Read existing host registrations first and
59
+ do not stack an event the project already covers.
58
60
 
59
- After both installer commands, inspect the installed skill diffs and briefly report any guidance changes; version-marker
61
+ After the installer command, inspect the installed skill diffs and briefly report any guidance changes; version-marker
60
62
  changes alone do not count. Re-read changed skills and references relevant to the remaining work, including this update skill
61
63
  if it changed. Continue from the current step using the updated guidance, keeping the original baseline, user choices, and
62
64
  completed changes in mind. Check for newly required steps without repeating completed mutations or expanding the approved