@imfusion/web-ui 0.5.0

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 (152) hide show
  1. package/README.md +60 -0
  2. package/bin/install-skill.js +180 -0
  3. package/dist/assets/vendors/base-ui.d.ts +8 -0
  4. package/dist/breakpoints/index.d.ts +3 -0
  5. package/dist/breakpoints/min-width.d.ts +9 -0
  6. package/dist/breakpoints/registry.d.ts +19 -0
  7. package/dist/code-qBbqAHK-.js +190 -0
  8. package/dist/codegen/gen-breakpoints-css.d.ts +6 -0
  9. package/dist/codegen/gen-css-types.d.ts +1 -0
  10. package/dist/codegen/gen-token-css.d.ts +6 -0
  11. package/dist/codegen/run.d.ts +1 -0
  12. package/dist/components/app-shell/app-shell.d.ts +66 -0
  13. package/dist/components/app-shell/app-shell.meta.d.ts +2 -0
  14. package/dist/components/app-shell/index.d.ts +2 -0
  15. package/dist/components/button/button.d.ts +30 -0
  16. package/dist/components/button/button.meta.d.ts +2 -0
  17. package/dist/components/button/index.d.ts +2 -0
  18. package/dist/components/callout/callout.d.ts +42 -0
  19. package/dist/components/callout/callout.meta.d.ts +2 -0
  20. package/dist/components/callout/index.d.ts +2 -0
  21. package/dist/components/card/card.d.ts +64 -0
  22. package/dist/components/card/card.meta.d.ts +2 -0
  23. package/dist/components/card/index.d.ts +2 -0
  24. package/dist/components/checkbox/checkbox.d.ts +56 -0
  25. package/dist/components/checkbox/checkbox.meta.d.ts +2 -0
  26. package/dist/components/checkbox/index.d.ts +2 -0
  27. package/dist/components/chip/chip.cva.d.ts +12 -0
  28. package/dist/components/chip/chip.d.ts +11 -0
  29. package/dist/components/chip/chip.meta.d.ts +2 -0
  30. package/dist/components/chip/index.d.ts +2 -0
  31. package/dist/components/chip-link/chip-link.d.ts +17 -0
  32. package/dist/components/chip-link/chip-link.meta.d.ts +2 -0
  33. package/dist/components/chip-link/index.d.ts +2 -0
  34. package/dist/components/code/code.d.ts +60 -0
  35. package/dist/components/code/code.meta.d.ts +2 -0
  36. package/dist/components/code/index.d.ts +2 -0
  37. package/dist/components/collapsible/collapsible.d.ts +57 -0
  38. package/dist/components/collapsible/collapsible.meta.d.ts +2 -0
  39. package/dist/components/collapsible/index.d.ts +2 -0
  40. package/dist/components/copy-button/copy-button.d.ts +21 -0
  41. package/dist/components/copy-button/copy-button.meta.d.ts +2 -0
  42. package/dist/components/copy-button/index.d.ts +2 -0
  43. package/dist/components/drawer/drawer.d.ts +191 -0
  44. package/dist/components/drawer/drawer.meta.d.ts +2 -0
  45. package/dist/components/drawer/index.d.ts +2 -0
  46. package/dist/components/input/index.d.ts +2 -0
  47. package/dist/components/input/input.d.ts +25 -0
  48. package/dist/components/input/input.meta.d.ts +2 -0
  49. package/dist/components/logo/imfusion/imfusion.d.ts +16 -0
  50. package/dist/components/logo/imfusion/index.d.ts +1 -0
  51. package/dist/components/logo/index.d.ts +3 -0
  52. package/dist/components/logo/logo.d.ts +15 -0
  53. package/dist/components/logo/logo.meta.d.ts +2 -0
  54. package/dist/components/navigation-menu/index.d.ts +2 -0
  55. package/dist/components/navigation-menu/navigation-menu.d.ts +20 -0
  56. package/dist/components/navigation-menu/navigation-menu.meta.d.ts +2 -0
  57. package/dist/components/navigation-menu/subs/flyout-link.d.ts +24 -0
  58. package/dist/components/navigation-menu/subs/inline-submenu.d.ts +41 -0
  59. package/dist/components/navigation-menu/subs/link.d.ts +64 -0
  60. package/dist/components/navigation-menu/subs/overlay.d.ts +75 -0
  61. package/dist/components/navigation-menu/subs/shared.d.ts +20 -0
  62. package/dist/components/navigation-menu/subs/structure.d.ts +64 -0
  63. package/dist/components/navigation-menu/subs/trigger.d.ts +47 -0
  64. package/dist/components/popover/index.d.ts +2 -0
  65. package/dist/components/popover/popover.d.ts +181 -0
  66. package/dist/components/popover/popover.meta.d.ts +2 -0
  67. package/dist/components/row/index.d.ts +2 -0
  68. package/dist/components/row/row.d.ts +28 -0
  69. package/dist/components/row/row.meta.d.ts +2 -0
  70. package/dist/components/select/index.d.ts +2 -0
  71. package/dist/components/select/select.d.ts +278 -0
  72. package/dist/components/select/select.meta.d.ts +2 -0
  73. package/dist/components/separator/index.d.ts +2 -0
  74. package/dist/components/separator/separator.d.ts +15 -0
  75. package/dist/components/separator/separator.meta.d.ts +2 -0
  76. package/dist/components/slider/index.d.ts +2 -0
  77. package/dist/components/slider/slider.d.ts +111 -0
  78. package/dist/components/slider/slider.meta.d.ts +2 -0
  79. package/dist/components/spinner/index.d.ts +2 -0
  80. package/dist/components/spinner/spinner.d.ts +19 -0
  81. package/dist/components/spinner/spinner.geometry.d.ts +37 -0
  82. package/dist/components/spinner/spinner.meta.d.ts +2 -0
  83. package/dist/components/stack/index.d.ts +2 -0
  84. package/dist/components/stack/stack.d.ts +18 -0
  85. package/dist/components/stack/stack.meta.d.ts +2 -0
  86. package/dist/components/switch/index.d.ts +2 -0
  87. package/dist/components/switch/switch.d.ts +45 -0
  88. package/dist/components/switch/switch.meta.d.ts +2 -0
  89. package/dist/components/table/index.d.ts +2 -0
  90. package/dist/components/table/table.d.ts +66 -0
  91. package/dist/components/table/table.meta.d.ts +2 -0
  92. package/dist/components/tabs/index.d.ts +2 -0
  93. package/dist/components/tabs/tabs.d.ts +91 -0
  94. package/dist/components/tabs/tabs.meta.d.ts +2 -0
  95. package/dist/components/toggle/index.d.ts +2 -0
  96. package/dist/components/toggle/toggle.d.ts +31 -0
  97. package/dist/components/toggle/toggle.meta.d.ts +2 -0
  98. package/dist/components/toggle-group/index.d.ts +2 -0
  99. package/dist/components/toggle-group/toggle-group.d.ts +30 -0
  100. package/dist/components/toggle-group/toggle-group.meta.d.ts +2 -0
  101. package/dist/components/tooltip/index.d.ts +2 -0
  102. package/dist/components/tooltip/tooltip.d.ts +164 -0
  103. package/dist/components/tooltip/tooltip.meta.d.ts +2 -0
  104. package/dist/components/typo/index.d.ts +2 -0
  105. package/dist/components/typo/typo.d.ts +100 -0
  106. package/dist/components/typo/typo.meta.d.ts +2 -0
  107. package/dist/config.d.ts +8 -0
  108. package/dist/docgen/gen-docgen.d.ts +1 -0
  109. package/dist/docgen/gen-docgen.utils.d.ts +13 -0
  110. package/dist/hooks/index.d.ts +5 -0
  111. package/dist/hooks/use-clipboard.d.ts +12 -0
  112. package/dist/hooks/use-color-scheme.d.ts +31 -0
  113. package/dist/hooks/use-media-query.d.ts +13 -0
  114. package/dist/index.d.ts +38 -0
  115. package/dist/index.js +13103 -0
  116. package/dist/integrations/code-highlight/code-highlight.d.ts +21 -0
  117. package/dist/integrations/code-highlight/code-highlight.meta.d.ts +2 -0
  118. package/dist/integrations/code-highlight/highlighter.d.ts +6 -0
  119. package/dist/integrations/code-highlight/index.d.ts +3 -0
  120. package/dist/integrations/code-highlight.js +97 -0
  121. package/dist/integrations/image-display-options/image-display-options-view.d.ts +22 -0
  122. package/dist/integrations/image-display-options/image-display-options-view.utils.d.ts +40 -0
  123. package/dist/integrations/image-display-options/image-display-options.d.ts +29 -0
  124. package/dist/integrations/image-display-options/image-display-options.meta.d.ts +2 -0
  125. package/dist/integrations/image-display-options/index.d.ts +2 -0
  126. package/dist/integrations/image-display-options.js +319 -0
  127. package/dist/llms/gen-llms.d.ts +1 -0
  128. package/dist/meta-B8C51eyL.js +74 -0
  129. package/dist/provider/index.d.ts +1 -0
  130. package/dist/provider/web-ui-provider.d.ts +6 -0
  131. package/dist/style.css +2 -0
  132. package/dist/tabs-DqBFSqq6.js +3789 -0
  133. package/dist/tokens/apply.d.ts +55 -0
  134. package/dist/tokens/control-registry.d.ts +10 -0
  135. package/dist/tokens/token-registry.d.ts +13 -0
  136. package/dist/tokens/types.d.ts +71 -0
  137. package/dist/tokens/use-token-controls.d.ts +36 -0
  138. package/dist/types/docgen.d.ts +17 -0
  139. package/dist/types/meta.d.ts +108 -0
  140. package/dist/types/theme.d.ts +3 -0
  141. package/package.json +139 -0
  142. package/src/docgen/doc.gen.json +4695 -0
  143. package/src/llms/llms.gen.txt +176 -0
  144. package/src/llms/skills/imf-web-ui/SKILL.md +46 -0
  145. package/src/llms/skills/imf-web-ui-components/SKILL.md +100 -0
  146. package/src/llms/skills/imf-web-ui-frontend-patterns/SKILL.md +67 -0
  147. package/src/llms/skills/imf-web-ui-frontend-patterns/references/react-patterns.md +94 -0
  148. package/src/llms/skills/imf-web-ui-setup/SKILL.md +30 -0
  149. package/src/llms/skills/imf-web-ui-ux/SKILL.md +103 -0
  150. package/src/llms/skills/imf-web-ui-ux/references/forms.md +48 -0
  151. package/src/llms/skills/imf-web-ui-ux/references/usability-heuristics.md +29 -0
  152. package/src/llms/skills/imf-web-ui-ux/references/visual-design.md +38 -0
@@ -0,0 +1,176 @@
1
+ # @imfusion/web-ui component index
2
+
3
+ Each entry below is an identity summary. Props for every component live in
4
+ `node_modules/@imfusion/web-ui/src/docgen/doc.gen.json` (a real file, not the `@imfusion/web-ui/docgen.json`
5
+ package export alias — that alias only resolves via Node's module
6
+ resolver, not via cat/jq/grep on disk), keyed by the kebab-case folder name
7
+ shown as `props:` below — extract one component with `jq` rather than
8
+ reading the whole file. `further reading` links (when present) point at
9
+ the upstream library's own docs for usage/anatomy/composition — not for
10
+ props, which always live in the docgen file above.
11
+
12
+ ## AppShell
13
+ - category: Layout, status: stable
14
+ Application layout shell — a fixed header, collapsible navbar/aside sidebars, an optional footer, and a scrolling main area. The classic dashboard frame; also called an app layout, application frame, dashboard shell, or sidebar layout. Sizing is CSS-driven and sidebars collapse to sliding overlays on small screens.
15
+ - props: node_modules/@imfusion/web-ui/src/docgen/doc.gen.json -> .app-shell (jq: jq '.app-shell' node_modules/@imfusion/web-ui/src/docgen/doc.gen.json)
16
+
17
+ ## Button
18
+ - category: Buttons, status: stable
19
+ Triggers an action — submit, confirm, cancel, navigate, or destructive operations. Six semantic variants (primary, secondary, positive, negative, outline, ghost) communicate intent across four sizes (sm, md, lg, hero). The brand's chamfered shape; hover inverts fill and label. An optional endIcon slot aligns the label left and pins the icon right. Also called a CTA or action.
20
+ - props: node_modules/@imfusion/web-ui/src/docgen/doc.gen.json -> .button (jq: jq '.button' node_modules/@imfusion/web-ui/src/docgen/doc.gen.json)
21
+ - further reading (usage/anatomy, not props): https://base-ui.com/react/components/button.md
22
+
23
+ ## Callout
24
+ - category: Display, status: stable
25
+ Inline status banner — a persistent, non-interactive message that sits in the content flow to convey info, success, warning, or error state. Composed from slots: Callout.Root wraps a Callout.Icon (status glyph), an optional Callout.Title, and a Callout.Description. Tonal `variant` (info/positive/warning/negative) tints the surface and colours the icon and text. Also called an alert, callout, or inline notice. Not a Toast (transient) or Alert Dialog (modal).
26
+ - props: node_modules/@imfusion/web-ui/src/docgen/doc.gen.json -> .callout (jq: jq '.callout' node_modules/@imfusion/web-ui/src/docgen/doc.gen.json)
27
+
28
+ ## Card
29
+ - category: Layout, status: stable
30
+ Surface container — groups related content on a tonal background. Composed from slots: Card.Root wraps an optional edge-to-edge Card.Image plus padded Card.Header, Card.Content, and Card.Footer. Tonal or coloured `variant`, opt-in shadow and radius, and a `density` scale. Also called a panel, tile, or paper.
31
+ - 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)
32
+
33
+ ## Checkbox
34
+ - category: Inputs, status: stable
35
+ Binary form control for opt-in choices — accept terms, select table rows, pick list items. Supports an indeterminate state for parent/child selection. Also called a check box or tick box; for immediate on/off preferences, prefer Switch.
36
+ - props: node_modules/@imfusion/web-ui/src/docgen/doc.gen.json -> .checkbox (jq: jq '.checkbox' node_modules/@imfusion/web-ui/src/docgen/doc.gen.json)
37
+ - further reading (usage/anatomy, not props): https://base-ui.com/react/components/checkbox.md
38
+
39
+ ## Chip
40
+ - category: Display, status: stable
41
+ Compact inline label for tags, status, categories, counts, or metadata. Also known as a badge, tag, or pill. Two dimensions — a color variant for semantic role and a shape variant for visual appearance, including an inline form that sits naturally in flowing body text.
42
+ - props: node_modules/@imfusion/web-ui/src/docgen/doc.gen.json -> .chip (jq: jq '.chip' node_modules/@imfusion/web-ui/src/docgen/doc.gen.json)
43
+
44
+ ## ChipLink
45
+ - category: Buttons, status: stable
46
+ Inline link styled as a chip — a small labeled anchor that auto-appends a directional icon. Use for external doc references and source attribution (opens in a new tab) or in-app navigation badges (stays in the current tab). Also called a link chip or link badge.
47
+ - props: node_modules/@imfusion/web-ui/src/docgen/doc.gen.json -> .chip-link (jq: jq '.chip-link' node_modules/@imfusion/web-ui/src/docgen/doc.gen.json)
48
+
49
+ ## Code
50
+ - category: Display, status: stable
51
+ Displays source code — Code.Inline for a fragment in running text, Code.Block for a fenced block with an optional language label and copy button. Also called a code snippet or code block.
52
+ - props: node_modules/@imfusion/web-ui/src/docgen/doc.gen.json -> .code (jq: jq '.code' node_modules/@imfusion/web-ui/src/docgen/doc.gen.json)
53
+
54
+ ## CodeHighlight
55
+ - category: Display, status: experimental
56
+ Syntax-highlighted drop-in for the Code parts — the same Code.Block and Code.Inline, with TanStack Highlight token coloring that follows the color scheme. Imported from @imfusion/web-ui/integrations/code-highlight; requires the @tanstack/highlight peer.
57
+ - props: node_modules/@imfusion/web-ui/src/docgen/doc.gen.json -> .code-highlight (jq: jq '.code-highlight' node_modules/@imfusion/web-ui/src/docgen/doc.gen.json)
58
+
59
+ ## Collapsible
60
+ - category: Display, status: stable
61
+ Toggleable show/hide region for progressive disclosure — FAQ entries, expandable settings, detail toggles. A trigger button drives an animated open/close panel; multiple stacked form an accordion. Also called a disclosure or expand/collapse.
62
+ - props: node_modules/@imfusion/web-ui/src/docgen/doc.gen.json -> .collapsible (jq: jq '.collapsible' node_modules/@imfusion/web-ui/src/docgen/doc.gen.json)
63
+ - further reading (usage/anatomy, not props): https://base-ui.com/react/components/collapsible.md
64
+
65
+ ## CopyButton
66
+ - category: Buttons, status: stable
67
+ Button that copies a value to the clipboard and shows a transient confirmation. Also called a copy-to-clipboard button. Composes Button; commonly paired with Code.Block.
68
+ - props: node_modules/@imfusion/web-ui/src/docgen/doc.gen.json -> .copy-button (jq: jq '.copy-button' node_modules/@imfusion/web-ui/src/docgen/doc.gen.json)
69
+
70
+ ## Drawer
71
+ - category: Layout, status: stable
72
+ Off-canvas panel that slides in from a screen edge. Use for mobile navigation, secondary nav, settings trays, filter sidebars, or any side sheet. Also called a sidebar, side panel, off-canvas, or sheet.
73
+ - props: node_modules/@imfusion/web-ui/src/docgen/doc.gen.json -> .drawer (jq: jq '.drawer' node_modules/@imfusion/web-ui/src/docgen/doc.gen.json)
74
+ - further reading (usage/anatomy, not props): https://base-ui.com/react/components/drawer.md
75
+
76
+ ## ImageDisplayOptions
77
+ - category: Inputs, status: experimental
78
+ A panel or toolbar of controls bound to an image dataset's display options.
79
+ - props: node_modules/@imfusion/web-ui/src/docgen/doc.gen.json -> .image-display-options (jq: jq '.image-display-options' node_modules/@imfusion/web-ui/src/docgen/doc.gen.json)
80
+ - further reading (usage/anatomy, not props): https://docs.imfusion.com/
81
+
82
+ ## Input
83
+ - category: Inputs, status: stable
84
+ Single-line text input for form data entry. Also called a text field or input field. Supports controlled and uncontrolled modes, and integrates with Base UI's Field context for validation state (valid, invalid, dirty, touched, filled, focused).
85
+ - 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)
86
+ - further reading (usage/anatomy, not props): https://base-ui.com/react/components/input.md
87
+
88
+ ## Logo
89
+ - category: Display, status: stable
90
+ Brand mark display primitive — renders a logo from a URL or inline React element with consistent sizing. Also called a wordmark, brand icon, or logotype.
91
+ - 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)
92
+
93
+ ## NavigationMenu
94
+ - category: Display, status: experimental
95
+ Navigation menu — a horizontal (or vertical) strip of triggers that open flat, anchored flyout panels for site or app wayfinding, with multi-column mega-menu content and a viewport-responsive inline master/detail submenu. Composed from slots: NavigationMenu.Root, List, Item, Trigger, Icon, Content, Link, FlyoutLink, LinkList, LinkCard, InlineSubmenu, Portal, Positioner, Popup, Viewport, Arrow, Backdrop. Also called a nav bar, menu bar, or mega menu.
96
+ - props: node_modules/@imfusion/web-ui/src/docgen/doc.gen.json -> .navigation-menu (jq: jq '.navigation-menu' node_modules/@imfusion/web-ui/src/docgen/doc.gen.json)
97
+ - further reading (usage/anatomy, not props): https://base-ui.com/react/components/navigation-menu.md
98
+
99
+ ## Popover
100
+ - category: Display, status: stable
101
+ Floating panel anchored to a trigger element. Use for contextual menus, tooltips-with-actions, rich hover cards, quick-edit forms, or any non-modal detail overlay. Also called a popup, flyout, or floating menu.
102
+ - props: node_modules/@imfusion/web-ui/src/docgen/doc.gen.json -> .popover (jq: jq '.popover' node_modules/@imfusion/web-ui/src/docgen/doc.gen.json)
103
+ - further reading (usage/anatomy, not props): https://base-ui.com/react/components/popover.md
104
+
105
+ ## Row
106
+ - category: Layout, status: stable
107
+ Horizontal layout primitive — children are arranged left-to-right with configurable spacing, alignment, and optional wrapping. Also called hstack, horizontal stack, flex row.
108
+ - props: node_modules/@imfusion/web-ui/src/docgen/doc.gen.json -> .row (jq: jq '.row' node_modules/@imfusion/web-ui/src/docgen/doc.gen.json)
109
+
110
+ ## Select
111
+ - category: Inputs, status: stable
112
+ Single-choice dropdown — pick one value from a known list. Keyboard-accessible listbox with a labelled trigger and a portalled popup. Best for short, fixed option sets (status, role, country). Also called a dropdown or picker.
113
+ - props: node_modules/@imfusion/web-ui/src/docgen/doc.gen.json -> .select (jq: jq '.select' node_modules/@imfusion/web-ui/src/docgen/doc.gen.json)
114
+ - further reading (usage/anatomy, not props): https://base-ui.com/react/components/select.md
115
+
116
+ ## Separator
117
+ - category: Layout, status: stable
118
+ Thin line that visually divides content into groups — section break, list item rule, sidebar division. Also called a divider, hr, or horizontal / vertical rule.
119
+ - 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)
120
+ - further reading (usage/anatomy, not props): https://base-ui.com/react/components/separator.md
121
+
122
+ ## Slider
123
+ - category: Inputs, status: stable
124
+ Drag a thumb along a track to pick a numeric value or range. Use for continuous or stepped numeric input where magnitude matters — volume, brightness, opacity, price ranges. Also called a range input.
125
+ - 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)
126
+ - further reading (usage/anatomy, not props): https://base-ui.com/react/components/slider.md
127
+
128
+ ## Spinner
129
+ - category: Display, status: stable
130
+ Loading indicator built from the animated ImFusion glyph. Also called a loader, progress spinner, or activity indicator; signals indeterminate loading.
131
+ - props: node_modules/@imfusion/web-ui/src/docgen/doc.gen.json -> .spinner (jq: jq '.spinner' node_modules/@imfusion/web-ui/src/docgen/doc.gen.json)
132
+
133
+ ## Stack
134
+ - category: Layout, status: stable
135
+ Vertical layout primitive — children stack top-to-bottom with configurable spacing and alignment. Use it instead of writing flex column layouts by hand. Also called a vstack or column.
136
+ - props: node_modules/@imfusion/web-ui/src/docgen/doc.gen.json -> .stack (jq: jq '.stack' node_modules/@imfusion/web-ui/src/docgen/doc.gen.json)
137
+
138
+ ## Switch
139
+ - category: Inputs, status: stable
140
+ Two-state toggle for immediate on/off preferences — enable a feature, mute audio, toggle dark mode. Takes effect right away (no submit step); for form-submission booleans, a checkbox is more conventional. Also called a toggle.
141
+ - props: node_modules/@imfusion/web-ui/src/docgen/doc.gen.json -> .switch (jq: jq '.switch' node_modules/@imfusion/web-ui/src/docgen/doc.gen.json)
142
+ - further reading (usage/anatomy, not props): https://base-ui.com/react/components/switch.md
143
+
144
+ ## Table
145
+ - category: Display, status: stable
146
+ Styled, static building blocks for tabular data — Root, Header, Body, Row, HeaderCell, Cell, HeaderButton, SortableHeaderCell. Also called a data grid anatomy. Purely presentational with no data logic; for a full data grid, drive these parts with a headless table library (TanStack Table recommended) that you install yourself.
147
+ - props: node_modules/@imfusion/web-ui/src/docgen/doc.gen.json -> .table (jq: jq '.table' node_modules/@imfusion/web-ui/src/docgen/doc.gen.json)
148
+
149
+ ## Tabs
150
+ - category: Display, status: stable
151
+ Tabbed navigation — switches between panels of content within one view via a horizontal (or vertical) strip of labels with a sliding active-state underline. Composed from slots: Tabs.Root, Tabs.List, Tabs.Tab, Tabs.Indicator, Tabs.Panel. Also called a tab strip or tab bar.
152
+ - props: node_modules/@imfusion/web-ui/src/docgen/doc.gen.json -> .tabs (jq: jq '.tabs' node_modules/@imfusion/web-ui/src/docgen/doc.gen.json)
153
+ - further reading (usage/anatomy, not props): https://base-ui.com/react/components/tabs.md
154
+
155
+ ## Toggle
156
+ - category: Inputs, status: experimental
157
+ A two-state button that can be on or off. Compose several inside a ToggleGroup for a segmented control.
158
+ - props: node_modules/@imfusion/web-ui/src/docgen/doc.gen.json -> .toggle (jq: jq '.toggle' node_modules/@imfusion/web-ui/src/docgen/doc.gen.json)
159
+ - further reading (usage/anatomy, not props): https://base-ui.com/react/components/toggle.md
160
+
161
+ ## ToggleGroup
162
+ - category: Inputs, status: experimental
163
+ A set of connected Toggle buttons sharing one value: single-select by default (a segmented control), or multi-select with `multiple`. Compose one Toggle per segment, each with a value. Also called a segmented control or segmented button.
164
+ - props: node_modules/@imfusion/web-ui/src/docgen/doc.gen.json -> .toggle-group (jq: jq '.toggle-group' node_modules/@imfusion/web-ui/src/docgen/doc.gen.json)
165
+ - further reading (usage/anatomy, not props): https://base-ui.com/react/components/toggle-group.md
166
+
167
+ ## Tooltip
168
+ - category: Display, status: stable
169
+ Hover- or focus-triggered floating label giving terse contextual help for a control or term. Use for icon-button descriptions, truncated-text reveals, and field hints. Also called a hint, hovercard, or info bubble; for click-triggered panels with actions use Popover instead.
170
+ - props: node_modules/@imfusion/web-ui/src/docgen/doc.gen.json -> .tooltip (jq: jq '.tooltip' node_modules/@imfusion/web-ui/src/docgen/doc.gen.json)
171
+ - further reading (usage/anatomy, not props): https://base-ui.com/react/components/tooltip.md
172
+
173
+ ## Typo
174
+ - category: Display, status: stable
175
+ Typographic primitives — a family of heading (H1–H4), paragraph (P, Lead), and inline accent (InlineCode, Highlight, Link) components. Most support a color role — main, support, or minor — plus the standard HTML attributes for its element; InlineCode is a fixed neutral chip (it renders Code.Inline).
176
+ - props: node_modules/@imfusion/web-ui/src/docgen/doc.gen.json -> .typo (jq: jq '.typo' node_modules/@imfusion/web-ui/src/docgen/doc.gen.json)
@@ -0,0 +1,46 @@
1
+ ---
2
+ name: imf-web-ui
3
+ description:
4
+ "Entry point for UI work in a project that depends on @imfusion/web-ui. Decides whether guidance is needed at all, then
5
+ routes to the right companion skill — component reference, UX guidance, or frontend patterns. Load when adding or editing
6
+ UI in a consumer repo."
7
+ ---
8
+
9
+ # imf-web-ui
10
+
11
+ `@imfusion/web-ui` ships a small family of skills. This one is the map — it costs almost nothing to load and tells you which
12
+ companion to open, or that you need none at all. Don't load a companion speculatively: route first, zoom second.
13
+
14
+ ## Row zero — is help needed at all?
15
+
16
+ Before routing, check whether this task needs guidance in the first place. It does **not** when:
17
+
18
+ - The request is explicit and small ("make the button say Save", "add a column for email"), or
19
+ - You're repeating a pattern that already exists nearby in the codebase — copy it, and
20
+ - The components involved are already imported and used correctly.
21
+
22
+ In that case: just do the work. At most, do a silent props lookup via `imf-web-ui-components` if you're unsure of an API.
23
+ Guidance skills exist to fill gaps, not to add ceremony to clear tasks.
24
+
25
+ ## Routing
26
+
27
+ | The task at hand | Open |
28
+ | ---------------------------------------------------------------------------------------------------- | ------------------------------ |
29
+ | Using a specific component; checking props, sub-components, or defaults | `imf-web-ui-components` |
30
+ | First-time setup, or components rendering unstyled/broken | `imf-web-ui-setup` |
31
+ | Building/reshaping a screen or flow; choosing between components; layout, density, hierarchy, states | `imf-web-ui-ux` |
32
+ | Writing wrappers or custom UI around the library; styling beyond defaults; state or code structure | `imf-web-ui-frontend-patterns` |
33
+
34
+ Tasks routinely span two: building a screen usually means `imf-web-ui-ux` for the shape and `imf-web-ui-components` for the
35
+ APIs. That's normal — open both, in that order.
36
+
37
+ ## When to interview the human
38
+
39
+ `imf-web-ui-ux` contains a short per-feature interview. Run it **only** when both hold:
40
+
41
+ 1. The request is foggy — you couldn't say what the primary action of the screen is, who uses it, or what data it shows.
42
+ 2. A human is available to answer.
43
+
44
+ Never interview when a spec, mockup, or clear instruction exists — asking questions the conversation already answered is
45
+ worse than not asking at all. When in doubt and no human is around, make the conservative choice, and say which assumptions
46
+ you made.
@@ -0,0 +1,100 @@
1
+ ---
2
+ name: imf-web-ui-components
3
+ description:
4
+ "Look up @imfusion/web-ui component APIs without reading their source: the two-hop lookup (identity index -> prop data),
5
+ compound components, and integrations. Load when you need the props, sub-components, or defaults of a specific component —
6
+ not for choosing between components (imf-web-ui-ux) or first-time setup (imf-web-ui-setup)."
7
+ ---
8
+
9
+ # imf-web-ui-components
10
+
11
+ `@imfusion/web-ui` ships two generated files inside `node_modules` so an agent can discover and use its components without
12
+ reading source or checking out the library's repo:
13
+
14
+ - **`node_modules/@imfusion/web-ui/src/llms/llms.gen.txt`** — an identity index: every component's name, category, status,
15
+ and a one-sentence description of what it's for and what else it's called.
16
+ - **`node_modules/@imfusion/web-ui/src/docgen/doc.gen.json`** — full prop tables (name, type, default, description) for every
17
+ component, keyed by kebab-case folder name.
18
+
19
+ Neither file is reachable through the package's pretty import paths (`@imfusion/web-ui/llms.txt`,
20
+ `@imfusion/web-ui/docgen.json`) — those are Node module-resolution aliases, meaningless to `cat`/`jq`/`grep` reading files
21
+ off disk. Use the `node_modules/...` paths above directly.
22
+
23
+ ## The lookup, in two hops
24
+
25
+ **Hop 1 — find the component.** Read the whole index; it's small (~13KB for the full library) and safe to load in full:
26
+
27
+ ```sh
28
+ cat node_modules/@imfusion/web-ui/src/llms/llms.gen.txt
29
+ ```
30
+
31
+ Each entry looks like this:
32
+
33
+ ```
34
+ ## Button
35
+ - category: Buttons, status: stable
36
+ Triggers an action — submit, confirm, cancel, navigate, or destructive operations. Six semantic variants ...
37
+ - props: node_modules/@imfusion/web-ui/src/docgen/doc.gen.json -> .button (jq: jq '.button' node_modules/@imfusion/web-ui/src/docgen/doc.gen.json)
38
+ - further reading (usage/anatomy, not props): https://base-ui.com/react/components/button.md
39
+ ```
40
+
41
+ **Hop 2 — pull that component's props.** Don't read the whole docgen file (~500KB across all components) — slice out just the
42
+ one entry with the exact command the index gave you:
43
+
44
+ ```sh
45
+ jq '.button' node_modules/@imfusion/web-ui/src/docgen/doc.gen.json
46
+ ```
47
+
48
+ That returns `{ root: { name, description, props: [...] }, subComponents: [...] }`. `root` is the primary export (`Button`);
49
+ `subComponents` holds compound parts (e.g. `Drawer.Root`, `Drawer.Trigger`, `Drawer.Content` all live under the `drawer`
50
+ key). Match the sub-component you need by its dotted `name`.
51
+
52
+ **`jq` may not be installed.** Check with `which jq` before relying on it. If it's missing, do **not** fall back to reading
53
+ the whole `doc.gen.json` file — that defeats the entire point of the two-hop design (~500KB across all components vs. one
54
+ ~9KB entry) and will burn your context budget for no reason. Use whatever's actually available instead:
55
+
56
+ ```sh
57
+ node -e "console.log(JSON.stringify(JSON.parse(require('fs').readFileSync('node_modules/@imfusion/web-ui/src/docgen/doc.gen.json','utf8')).button, null, 2))"
58
+ ```
59
+
60
+ (Node ships everywhere this package can be installed, so this always works as a fallback.) Or ask the user to install `jq` if
61
+ you expect to look up several components in one session.
62
+
63
+ **"Further reading" links, if present, are not a props source.** They point at the upstream library's (usually Base UI's) own
64
+ documentation for composition, anatomy, keyboard/focus behavior, and accessibility notes docgen can't express. Props always
65
+ come from `doc.gen.json` — never treat the linked page's prop table as authoritative for a web-ui component; web-ui may add,
66
+ remove, or default differently.
67
+
68
+ ## A component not found in the index?
69
+
70
+ The index is regenerated on every `@imfusion/web-ui` release; it should be exhaustive. If a component you expect is missing,
71
+ don't guess at an API — that's a real gap to report, not something to work around by inventing props. Tell the web-ui
72
+ maintainer, or file it in the [WEBSDK Jira project](https://imfusion.atlassian.net/browse/WEBSDK) if you have access. If the
73
+ gap is about _which_ component to use rather than a missing one, that's a design question: open `imf-web-ui-ux`.
74
+
75
+ ## Compound components
76
+
77
+ A component whose docgen entry has a non-empty `subComponents` array is used as a namespace, not a single import — e.g.
78
+ `import { Drawer } from "@imfusion/web-ui"` then `<Drawer.Root>`, `<Drawer.Trigger>`, `<Drawer.Content>`. The index's
79
+ category/description covers the whole family; look at `subComponents` in the docgen entry to see which parts exist and what
80
+ each one's own props are.
81
+
82
+ ## Integrations (own-entry components)
83
+
84
+ A description mentioning "Imported from `@imfusion/web-ui/integrations/<name>`" is a signal this component isn't in the
85
+ default import — e.g.:
86
+
87
+ ```tsx
88
+ import { Code } from "@imfusion/web-ui/integrations/code-highlight";
89
+ ```
90
+
91
+ These exist because their behavior depends on an optional peer dependency (e.g. `@tanstack/highlight` for `CodeHighlight`)
92
+ that most consumers shouldn't be forced to install. Check the component's description for which peer to add, and add it
93
+ explicitly to your own `package.json` — web-ui does not install it for you.
94
+
95
+ ## Data grids (Table + a headless library)
96
+
97
+ For a data grid, drive the styled `Table` parts with a headless table library you install yourself. **TanStack Table**
98
+ (`@tanstack/react-table`) is recommended. Map your `useReactTable` instance onto `Table.Root` / `Table.Header` / `Table.Row`
99
+ / `Table.Cell`, and use `Table.SortableHeaderCell` for sortable columns — it carries the `aria-sort` state and the sort
100
+ indicator. See the Table primitive's Storybook docs for the pairing.
@@ -0,0 +1,67 @@
1
+ ---
2
+ name: imf-web-ui-frontend-patterns
3
+ description:
4
+ "Raise the quality of frontend code written around @imfusion/web-ui — including quickly vibe-coded frontends. Library
5
+ boundary contract (tokens, CSS layers, type derivation), component roles, state placement, effects discipline, and stack
6
+ defaults. Load when writing wrapper components, custom UI, or styling beyond the defaults."
7
+ ---
8
+
9
+ # imf-web-ui-frontend-patterns
10
+
11
+ One guard, once: **if the host project already has a convention — a styling system, a state library, a folder shape — the
12
+ project wins.** These defaults fill vacuums. They are not a license to refactor a consumer codebase toward this document.
13
+
14
+ Everything else below is how to build.
15
+
16
+ ## Stay behind the library
17
+
18
+ Never import Base UI (or any other upstream this library wraps) directly — no upstream stylesheets, no upstream components,
19
+ even when upstream docs show it that way. Everything a component needs ships in `@imfusion/web-ui`. If the library is missing
20
+ something upstream has, report the gap (see `imf-web-ui-components`); don't reach around it.
21
+
22
+ ## Style through the sanctioned seams
23
+
24
+ All library styles live in the `imf-ui.components` CSS layer, so **any plain selector you write wins** — that's the whole
25
+ override contract:
26
+
27
+ - Target the stable hooks: `data-imf-ui-component` attributes and your own classes/wrappers.
28
+ - Never target the library's internal class names — they are generated and change without notice.
29
+ - Never `!important` — if you think you need it, you're targeting the wrong thing.
30
+
31
+ ## Build custom UI from tokens
32
+
33
+ Anything you build that the library doesn't cover — a stat widget, a custom panel — uses `--imf-ui-*` variables for color,
34
+ spacing, radius, and type instead of hardcoded values. That's what makes custom UI look native next to library components,
35
+ and what keeps it correct when the theme changes. A hex code or a magic `px` next to a concept the tokens already name is a
36
+ defect.
37
+
38
+ ## Derive types, don't import them
39
+
40
+ Prop types come from the components themselves: `React.ComponentProps<typeof Button>`. The library deliberately exports no
41
+ `Props` types — don't look for them, and don't re-declare prop shapes by hand.
42
+
43
+ ## Integrations own their peers
44
+
45
+ Components under `@imfusion/web-ui/integrations/*` depend on optional peers (e.g. `@tanstack/highlight` for `CodeHighlight`).
46
+ Add the peer explicitly to the consumer's `package.json` — never rely on hoisting.
47
+
48
+ ## React patterns
49
+
50
+ The full treatment — component roles with an example, state placement, effects discipline, and the react.dev sources to
51
+ consult while building — lives in [references/react-patterns.md](references/react-patterns.md). Read it before writing new
52
+ screens or wrappers. The core in one breath:
53
+
54
+ - **Three roles.** Dumb components own how things look, layout components own arrangement, smart containers own data and
55
+ logic. Styling never lives in containers.
56
+ - **State lives where its truth lives.** URL → query cache → context → store → local state; walk the list, stop at the first
57
+ match.
58
+ - **Effects are a last resort**, and always extracted into purpose-named hooks.
59
+ - **Compose, don't configure.** If a component's prop list reads like a settings page, it wanted to be two or three
60
+ components.
61
+
62
+ ## Starting a frontend from scratch
63
+
64
+ When the consumer app is greenfield, default to the TanStack suite: **Router** (URL state, type-safe search params),
65
+ **Query** (server state), **Form** (form state), and **Table** for data grids, which you pair with web-ui's styled `Table`
66
+ parts (`Table.SortableHeaderCell` carries the sort glue). Documentation is available straight from the terminal via
67
+ `npx tanstack`. This is the stack the state ladder assumes.
@@ -0,0 +1,94 @@
1
+ # React patterns
2
+
3
+ The house defaults for the React code around `@imfusion/web-ui`, in full. The links throughout are for **you, the agent**:
4
+ consult them while building — they are the authoritative source when a case here is ambiguous. Hand them to the human only if
5
+ asked.
6
+
7
+ ## Component roles
8
+
9
+ Dumb/smart separation is standard React practice (it traces back to Dan Abramov's
10
+ ["Presentational and Container Components"](https://medium.com/@dan_abramov/smart-and-dumb-components-7ca2f9a7c7d0) and
11
+ survives in [Thinking in React](https://react.dev/learn/thinking-in-react)). The house version has three roles:
12
+
13
+ - **Dumb components** own how things _look_. They style and compose library primitives, receive plain data and callbacks as
14
+ props, and know nothing about fetching, routing, or business logic. All non-layout styling lives here — and only here.
15
+ - **Layout components** own _arrangement_ — and nothing else. `Stack`- and `Row`-based wrappers with token gaps, a page grid,
16
+ a section frame. They exist because smart containers are styleless: when a container needs two panels side by side, that
17
+ arrangement is a layout component, not an inline style.
18
+ - **Smart containers** own how things _work_. Routes (or explicit container components) fetch data, hold orchestration logic,
19
+ and wire the other two together. Zero styling — the moment a container wants CSS, extract a layout component.
20
+
21
+ ```tsx
22
+ // Dumb — renders what it's given
23
+ function UserCard({ name, role, onEdit }: { name: string; role: string; onEdit: () => void }) {
24
+ return (
25
+ <Card.Root>
26
+ <Card.Content>
27
+ <Typo>{name}</Typo>
28
+ <Chip>{role}</Chip>
29
+ </Card.Content>
30
+ <Card.Footer>
31
+ <Button onClick={onEdit}>Edit</Button>
32
+ </Card.Footer>
33
+ </Card.Root>
34
+ );
35
+ }
36
+
37
+ // Smart — knows where data comes from, renders the dumb component
38
+ function UserCardContainer({ userId }: { userId: string }) {
39
+ const { data } = useUserQuery(userId);
40
+ const openEditor = useEditorNavigation(userId);
41
+ return <UserCard name={data.name} role={data.role} onEdit={openEditor} />;
42
+ }
43
+ ```
44
+
45
+ Why it matters here: dumb components are the layer where `@imfusion/web-ui` lives. Keeping them free of logic keeps every
46
+ screen restylable, testable with plain props, and resilient to library updates. The one web-ui-specific addition: wrap
47
+ `experimental` components (marked in the identity index) in a dumb component once per app even if you add nothing yet — a
48
+ breaking upstream change then lands in one file instead of every call site.
49
+
50
+ ## Compose, don't configure
51
+
52
+ Build screen-level pieces by composing primitives (`Stack`, `Row`, `Card`, your dumb components) rather than growing one
53
+ component with a dozen boolean props. If a component's prop list reads like a settings page, it wanted to be two or three
54
+ components. When state must be shared between siblings, lift it to the nearest common parent —
55
+ [Sharing State Between Components](https://react.dev/learn/sharing-state-between-components) — rather than syncing copies.
56
+
57
+ ## Put state where its truth lives
58
+
59
+ Work down this list and stop at the first match:
60
+
61
+ 1. **Shareable via URL?** (filters, sort, pagination, active tab) → router search params. Back button and copied links are UX
62
+ features you get for free.
63
+ 2. **Comes from an API?** → the data-fetching layer's cache (e.g. TanStack Query). Never copy server data into `useState` —
64
+ that's how stale-UI bugs are born.
65
+ 3. **Scoped to a subtree, resets on leave?** (wizard progress) → React context.
66
+ 4. **App-wide and persistent?** → a client store, and only now.
67
+ 5. **Local to one component?** (input value, open/closed) → `useState`.
68
+
69
+ Most frontends need far less of tier 4 than they think; tiers 1–2 usually dissolve the "we need a store" instinct. For
70
+ structuring the state itself, [Choosing the State Structure](https://react.dev/learn/choosing-the-state-structure) is the
71
+ reference — especially its rules on avoiding redundant and duplicated state.
72
+
73
+ ## Effects: last resort, and named
74
+
75
+ Before writing `useEffect`, check: derived values belong in render (or `useMemo`), responses to user actions belong in the
76
+ event handler, and server synchronization belongs in the data-fetching layer. Effects are for synchronizing with systems
77
+ _outside_ React. The definitive catalog of effect misuses — read it before every effect you're tempted to write — is
78
+ [You Might Not Need an Effect](https://react.dev/learn/you-might-not-need-an-effect).
79
+
80
+ When an effect is genuinely needed, extract it into a custom hook named for its purpose — `useSyncedScroll`,
81
+ `useDocumentTitle`, `useHotkey` — never an anonymous `useEffect` block inline in a component. The name documents intent, the
82
+ hook isolates the dependency array, and the component body stays declarative. Pattern reference:
83
+ [Reusing Logic with Custom Hooks](https://react.dev/learn/reusing-logic-with-custom-hooks).
84
+
85
+ ## Reading list
86
+
87
+ Consult while building; each is the authority for its topic:
88
+
89
+ - [Thinking in React](https://react.dev/learn/thinking-in-react) — decomposition and one-way data flow
90
+ - [Keeping Components Pure](https://react.dev/learn/keeping-components-pure) — why dumb components stay dumb
91
+ - [Choosing the State Structure](https://react.dev/learn/choosing-the-state-structure) — shaping state without duplication
92
+ - [Sharing State Between Components](https://react.dev/learn/sharing-state-between-components) — lifting state
93
+ - [You Might Not Need an Effect](https://react.dev/learn/you-might-not-need-an-effect) — the effect misuse catalog
94
+ - [Reusing Logic with Custom Hooks](https://react.dev/learn/reusing-logic-with-custom-hooks) — named effects live here
@@ -0,0 +1,30 @@
1
+ ---
2
+ name: imf-web-ui-setup
3
+ description:
4
+ "One-time wiring of @imfusion/web-ui into a consumer project: the styles import and the WebUIProvider wrapper. Load when
5
+ installing the library for the first time, or when its components render unstyled or without theme context."
6
+ ---
7
+
8
+ # imf-web-ui-setup
9
+
10
+ Every consumer entry point needs exactly two lines, in this order:
11
+
12
+ ```tsx
13
+ import "@imfusion/web-ui/styles.css";
14
+ import { WebUIProvider, Button } from "@imfusion/web-ui";
15
+ ```
16
+
17
+ Wrap the app root in `<WebUIProvider>` once. Components rendered outside it won't have the theme/CSS-variable context they
18
+ expect.
19
+
20
+ Never import a Base UI (or other upstream) stylesheet or component directly — everything a web-ui component needs is already
21
+ inside `styles.css` and the package's own exports; reaching around web-ui to the upstream library is always wrong, even if
22
+ the upstream docs show it that way.
23
+
24
+ ## Symptoms of a broken setup
25
+
26
+ - **Components render but look unstyled** — the `styles.css` import is missing from the entry point.
27
+ - **Components render but ignore the theme (wrong colors, no CSS variables resolving)** — they're mounted outside
28
+ `<WebUIProvider>`.
29
+ - **An integration component throws on import** — its optional peer dependency isn't installed; check the component's
30
+ description in the docgen index (`imf-web-ui-components`) for which peer to add to your `package.json`.
@@ -0,0 +1,103 @@
1
+ ---
2
+ name: imf-web-ui-ux
3
+ description:
4
+ "UX guidance for building screens with @imfusion/web-ui when no designer is around: pick the right component for an
5
+ interaction, lay out common screen types, handle empty/loading/error states. Load when building or reshaping a screen,
6
+ flow, or feature UI — not for prop lookups (that's imf-web-ui-components)."
7
+ ---
8
+
9
+ # imf-web-ui-ux
10
+
11
+ Most teams consuming `@imfusion/web-ui` don't have a designer on call. This skill stands in: it encodes the library authors'
12
+ UX experience — the whole experience of a screen, its visual design, and the usability where both meet. Follow it by default;
13
+ deviate when the product has a real reason to. Code-level patterns (tokens, layers, wrappers) live in
14
+ `imf-web-ui-frontend-patterns`; project wiring lives in `imf-web-ui-setup`.
15
+
16
+ Component names below are real — verify any API against the docgen index (`imf-web-ui-components`) before use. Never invent a
17
+ component this library doesn't ship.
18
+
19
+ ## Before recommending or building: the interview
20
+
21
+ If — and only if — the request is foggy and a human is available, ask what the conversation hasn't already answered, from
22
+ this list, and nothing more. This applies to recommendation questions, not just build tasks: when someone asks "which
23
+ component for X?" and the choice hinges on facts you don't have (how many controls, how often used, how much data), **ask
24
+ those questions first and recommend after** — don't recommend and then list caveats, because the caveats _are_ the interview,
25
+ inverted.
26
+
27
+ 1. Who uses this screen, and how often? (daily power-user tool vs. occasional visit changes density and shortcuts)
28
+ 2. What is the **one** primary action? (a screen with three primary buttons has zero)
29
+ 3. What data does it show — shape and volume? (5 rows or 5,000 decides table vs. cards vs. search-first)
30
+ 4. What happens when it's empty, loading, or failing?
31
+ 5. Where does it live — full page, or a step inside another flow?
32
+
33
+ If no human is around: make the conservative choice, and state your assumptions in the handoff.
34
+
35
+ ## Choosing the surface
36
+
37
+ - **Full page** — the default. Reach for an overlay only when context must be preserved behind the task.
38
+ - **`Drawer`** — a focused sub-task that interrupts the page: edit-details, multi-field create, confirm-with-context. This
39
+ library ships no modal `Dialog`; `Drawer` is the blocking surface. If a true centered dialog is genuinely required, raise
40
+ it upstream — don't hand-roll one.
41
+ - **`Popover`** — light, dismissable, contextual: a small form, a filter panel, extra actions. If it needs a heading and
42
+ three fields, it wanted to be a `Drawer`.
43
+ - **`Tooltip`** — hints only. Never essential information, never interactive content.
44
+ - **`Collapsible`** — progressive disclosure inside the page: advanced options, long secondary content.
45
+ - **`Tabs`** — parallel views of the same subject. If users must complete all of them, it's a flow, not tabs.
46
+
47
+ ## Choosing between look-alikes
48
+
49
+ - **`Button` vs. `ChipLink` vs. `Chip`** — does it _do_ something (`Button`), _go_ somewhere (`ChipLink`), or _label_
50
+ something (`Chip`)?
51
+ - **`Table` alone vs. `Table` + a table library** — static, small data reads fine as bare `Table` parts; the moment sorting,
52
+ pagination, or column logic appears, drive the parts with a headless table library (TanStack Table recommended) you install
53
+ yourself, using `Table.SortableHeaderCell` for the sort glue.
54
+ - **`Callout` vs. transient feedback** — `Callout` is for persistent, in-place status (errors, warnings, empty-state hints).
55
+ The library ships no `Toast`; for fire-and-forget confirmations prefer inline feedback near the trigger, and raise the
56
+ toast need upstream rather than hand-rolling one.
57
+ - **`Input`/`Select`/`Checkbox`/`Switch`/`Slider`** — `Switch` for instant effect, `Checkbox` for submitted forms; `Select`
58
+ beyond ~5 options, radio-style choices below that; `Slider` only when the _relative_ position means more than the exact
59
+ number.
60
+
61
+ ## Layout and hierarchy
62
+
63
+ - Frame the app with **`AppShell`**; inside it, compose **`Stack`** and **`Row`** with token-based gaps instead of
64
+ hand-written flex containers with magic-number margins. **`Separator`** over border hacks.
65
+ - Text hierarchy comes from **`Typo`** — pick levels by role (page title, section, body, caption), don't skip levels for
66
+ visual effect, don't style raw HTML headings next to it.
67
+ - **One primary action per view.** Everything else uses the quieter `Button` variants (see its docgen entry for the semantic
68
+ variant list). If two things compete for primary, decide which one the screen is _for_.
69
+ - Density follows the interview: power-user + high volume → compact tables, visible shortcuts; occasional use + low volume →
70
+ generous spacing, explanatory text.
71
+
72
+ ## States are part of the screen
73
+
74
+ Every screen ships four states, not one:
75
+
76
+ - **Empty** — say what this screen _will_ show and what to do next; an empty `Table` with no explanation is a bug.
77
+ - **Loading** — `Spinner`, or skeletons for known layouts; keep the frame stable so content doesn't jump in.
78
+ - **Error** — `Callout` with what failed and what the user can do; never a blank region, never only a console log.
79
+ - **Loaded** — the one you were going to build anyway.
80
+
81
+ ## Looking native
82
+
83
+ Custom UI the library doesn't cover should be indistinguishable from library UI: build it from `--imf-ui-*` tokens and
84
+ compose it with library primitives. The goal lives here; the mechanics (tokens, layers, wrappers) live in
85
+ `imf-web-ui-frontend-patterns`.
86
+
87
+ ## Experimental components
88
+
89
+ The identity index marks each component `stable` or `experimental`. Experimental ones are fine to use, but expect API
90
+ movement across releases — prefer wrapping them once (see `imf-web-ui-frontend-patterns`) so a breaking change lands in one
91
+ file, not forty call sites.
92
+
93
+ ## Deep dives
94
+
95
+ The 80/20 fundamentals behind this skill's advice, distilled from authoritative sources, live in child files. Read the one
96
+ that matches the work — they are for you, the agent, while designing; hand the source links to the human only on request:
97
+
98
+ - [references/usability-heuristics.md](references/usability-heuristics.md) — Nielsen's ten heuristics, applied to web-ui
99
+ screens. Read when reviewing or reworking an existing flow.
100
+ - [references/visual-design.md](references/visual-design.md) — hierarchy, grouping, alignment, whitespace. Read when a screen
101
+ is functionally complete but looks wrong and you can't say why.
102
+ - [references/forms.md](references/forms.md) — form layout, labels, validation timing, error wording. Read before building
103
+ any form beyond two fields.