@gunkin/uiify 0.0.14-alpha → 0.0.16-alpha

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 (165) hide show
  1. package/README.md +46 -1
  2. package/agents/components.md +80 -0
  3. package/agents/index.md +179 -0
  4. package/agents/reference/components/accordion.md +35 -0
  5. package/agents/reference/components/alert-modal.md +63 -0
  6. package/agents/reference/components/breadcrumb.md +72 -0
  7. package/agents/reference/components/button.md +40 -0
  8. package/agents/reference/components/candle-chart.md +107 -0
  9. package/agents/reference/components/carousel.md +274 -0
  10. package/agents/reference/components/checkbox.md +32 -0
  11. package/agents/reference/components/collapsible.md +26 -0
  12. package/agents/reference/components/color-picker.md +33 -0
  13. package/agents/reference/components/combobox.md +193 -0
  14. package/agents/reference/components/context-menu.md +129 -0
  15. package/agents/reference/components/drawer.md +215 -0
  16. package/agents/reference/components/dropdown-menu.md +178 -0
  17. package/agents/reference/components/field.md +76 -0
  18. package/agents/reference/components/file-upload.md +131 -0
  19. package/agents/reference/components/form.md +28 -0
  20. package/agents/reference/components/header.md +44 -0
  21. package/agents/reference/components/hover-card.md +54 -0
  22. package/agents/reference/components/input.md +29 -0
  23. package/agents/reference/components/line-chart.md +104 -0
  24. package/agents/reference/components/modal.md +106 -0
  25. package/agents/reference/components/number-field.md +60 -0
  26. package/agents/reference/components/otp-input.md +68 -0
  27. package/agents/reference/components/pagination.md +112 -0
  28. package/agents/reference/components/popup.md +111 -0
  29. package/agents/reference/components/radio-group.md +37 -0
  30. package/agents/reference/components/rating.md +43 -0
  31. package/agents/reference/components/segmented-control.md +51 -0
  32. package/agents/reference/components/select.md +60 -0
  33. package/agents/reference/components/skeleton.md +29 -0
  34. package/agents/reference/components/slider.md +71 -0
  35. package/agents/reference/components/spinner.md +34 -0
  36. package/agents/reference/components/switch.md +27 -0
  37. package/agents/reference/components/table-of-contents.md +185 -0
  38. package/agents/reference/components/table.md +189 -0
  39. package/agents/reference/components/tabs.md +42 -0
  40. package/agents/reference/components/tags-input.md +123 -0
  41. package/agents/reference/components/textarea.md +31 -0
  42. package/agents/reference/components/toast.md +151 -0
  43. package/agents/reference/components/toggle-group.md +50 -0
  44. package/agents/reference/components/toggle.md +26 -0
  45. package/agents/reference/components/toolbar.md +69 -0
  46. package/agents/reference/components/tooltip.md +76 -0
  47. package/agents/reference/components/virtual-scroll.md +97 -0
  48. package/agents/reference/elements/choice.md +55 -0
  49. package/agents/reference/elements/details.md +45 -0
  50. package/agents/reference/elements/dialog.md +43 -0
  51. package/agents/reference/elements/invoker.md +28 -0
  52. package/agents/reference/elements/popover.md +53 -0
  53. package/dist/components/alert-modal/AlertModalParts.js +1 -1
  54. package/dist/components/alert-modal/AlertModalParts.js.map +1 -1
  55. package/dist/components/button/Button.d.ts.map +1 -1
  56. package/dist/components/button/Button.js +5 -3
  57. package/dist/components/button/Button.js.map +1 -1
  58. package/dist/components/button/index.d.ts +1 -1
  59. package/dist/components/button/index.d.ts.map +1 -1
  60. package/dist/components/button/index.js.map +1 -1
  61. package/dist/components/button/types.d.ts +5 -4
  62. package/dist/components/button/types.d.ts.map +1 -1
  63. package/dist/components/carousel/CarouselMarkup.d.ts.map +1 -1
  64. package/dist/components/carousel/CarouselMarkup.js +8 -0
  65. package/dist/components/carousel/CarouselMarkup.js.map +1 -1
  66. package/dist/components/dropdown-menu/DropdownMenu.d.ts.map +1 -1
  67. package/dist/components/dropdown-menu/DropdownMenu.js +0 -2
  68. package/dist/components/dropdown-menu/DropdownMenu.js.map +1 -1
  69. package/dist/components/dropdown-menu/types.d.ts +0 -1
  70. package/dist/components/dropdown-menu/types.d.ts.map +1 -1
  71. package/dist/components/index.d.ts +1 -0
  72. package/dist/components/index.d.ts.map +1 -1
  73. package/dist/components/index.js +1 -0
  74. package/dist/components/index.js.map +1 -1
  75. package/dist/components/internal/choice-family/ChoiceGroup.d.ts.map +1 -1
  76. package/dist/components/internal/choice-family/ChoiceGroup.js +2 -3
  77. package/dist/components/internal/choice-family/ChoiceGroup.js.map +1 -1
  78. package/dist/components/internal/choice-family/types.d.ts +2 -2
  79. package/dist/components/internal/choice-family/types.d.ts.map +1 -1
  80. package/dist/components/pagination/Pagination.d.ts.map +1 -1
  81. package/dist/components/pagination/Pagination.js +11 -0
  82. package/dist/components/pagination/Pagination.js.map +1 -1
  83. package/dist/components/pagination/PaginationShell.d.ts.map +1 -1
  84. package/dist/components/pagination/PaginationShell.js +26 -1
  85. package/dist/components/pagination/PaginationShell.js.map +1 -1
  86. package/dist/components/segmented-control/SegmentedControl.d.ts.map +1 -1
  87. package/dist/components/segmented-control/SegmentedControl.js +1 -0
  88. package/dist/components/segmented-control/SegmentedControl.js.map +1 -1
  89. package/dist/components/segmented-control/client/SegmentedControlClient.d.ts.map +1 -1
  90. package/dist/components/segmented-control/client/SegmentedControlClient.js +1 -0
  91. package/dist/components/segmented-control/client/SegmentedControlClient.js.map +1 -1
  92. package/dist/components/table-of-contents/TableOfContents.d.ts +22 -0
  93. package/dist/components/table-of-contents/TableOfContents.d.ts.map +1 -0
  94. package/dist/components/table-of-contents/TableOfContents.js +142 -0
  95. package/dist/components/table-of-contents/TableOfContents.js.map +1 -0
  96. package/dist/components/table-of-contents/client/TableOfContentsClient.d.ts +18 -0
  97. package/dist/components/table-of-contents/client/TableOfContentsClient.d.ts.map +1 -0
  98. package/dist/components/table-of-contents/client/TableOfContentsClient.js +140 -0
  99. package/dist/components/table-of-contents/client/TableOfContentsClient.js.map +1 -0
  100. package/dist/components/table-of-contents/client/TableOfContentsClientParts.d.ts +7 -0
  101. package/dist/components/table-of-contents/client/TableOfContentsClientParts.d.ts.map +1 -0
  102. package/dist/components/table-of-contents/client/TableOfContentsClientParts.js +48 -0
  103. package/dist/components/table-of-contents/client/TableOfContentsClientParts.js.map +1 -0
  104. package/dist/components/table-of-contents/client/index.d.ts +5 -0
  105. package/dist/components/table-of-contents/client/index.d.ts.map +1 -0
  106. package/dist/components/table-of-contents/client/index.js +23 -0
  107. package/dist/components/table-of-contents/client/index.js.map +1 -0
  108. package/dist/components/table-of-contents/client/table-of-contents-context.d.ts +3 -0
  109. package/dist/components/table-of-contents/client/table-of-contents-context.d.ts.map +1 -0
  110. package/dist/components/table-of-contents/client/table-of-contents-context.js +7 -0
  111. package/dist/components/table-of-contents/client/table-of-contents-context.js.map +1 -0
  112. package/dist/components/table-of-contents/client/table-of-contents-interactions.d.ts +3 -0
  113. package/dist/components/table-of-contents/client/table-of-contents-interactions.d.ts.map +1 -0
  114. package/dist/components/table-of-contents/client/table-of-contents-interactions.js +144 -0
  115. package/dist/components/table-of-contents/client/table-of-contents-interactions.js.map +1 -0
  116. package/dist/components/table-of-contents/client/table-of-contents-pointer.d.ts +3 -0
  117. package/dist/components/table-of-contents/client/table-of-contents-pointer.d.ts.map +1 -0
  118. package/dist/components/table-of-contents/client/table-of-contents-pointer.js +94 -0
  119. package/dist/components/table-of-contents/client/table-of-contents-pointer.js.map +1 -0
  120. package/dist/components/table-of-contents/client.d.ts +1 -0
  121. package/dist/components/table-of-contents/client.js +1 -0
  122. package/dist/components/table-of-contents/index.d.ts +3 -0
  123. package/dist/components/table-of-contents/index.d.ts.map +1 -0
  124. package/dist/components/table-of-contents/index.js +21 -0
  125. package/dist/components/table-of-contents/index.js.map +1 -0
  126. package/dist/components/table-of-contents/scrollspy-selection.d.ts +4 -0
  127. package/dist/components/table-of-contents/scrollspy-selection.d.ts.map +1 -0
  128. package/dist/components/table-of-contents/scrollspy-selection.js +31 -0
  129. package/dist/components/table-of-contents/scrollspy-selection.js.map +1 -0
  130. package/dist/components/table-of-contents/scrollspy.d.ts +4 -0
  131. package/dist/components/table-of-contents/scrollspy.d.ts.map +1 -0
  132. package/dist/components/table-of-contents/scrollspy.js +178 -0
  133. package/dist/components/table-of-contents/scrollspy.js.map +1 -0
  134. package/dist/components/table-of-contents/types.d.ts +123 -0
  135. package/dist/components/table-of-contents/types.d.ts.map +1 -0
  136. package/dist/components/table-of-contents/types.js +1 -0
  137. package/dist/components/table-of-contents/types.js.map +1 -0
  138. package/dist/components/table-of-contents.d.ts +1 -0
  139. package/dist/components/table-of-contents.js +1 -0
  140. package/dist/components/toggle/Toggle.d.ts.map +1 -1
  141. package/dist/components/toggle/Toggle.js +12 -1
  142. package/dist/components/toggle/Toggle.js.map +1 -1
  143. package/dist/components/toggle-group/ToggleGroup.d.ts +1 -1
  144. package/dist/components/toggle-group/ToggleGroup.d.ts.map +1 -1
  145. package/dist/components/toggle-group/ToggleGroup.js +6 -1
  146. package/dist/components/toggle-group/ToggleGroup.js.map +1 -1
  147. package/dist/components/toggle-group/client/ToggleGroupClient.d.ts +1 -1
  148. package/dist/components/toggle-group/client/ToggleGroupClient.d.ts.map +1 -1
  149. package/dist/components/toggle-group/client/ToggleGroupClient.js +19 -6
  150. package/dist/components/toggle-group/client/ToggleGroupClient.js.map +1 -1
  151. package/dist/components/toggle-group/types.d.ts +3 -3
  152. package/dist/components/toggle-group/types.d.ts.map +1 -1
  153. package/dist/components/toolbar/ToolbarShell.d.ts.map +1 -1
  154. package/dist/components/toolbar/ToolbarShell.js +5 -2
  155. package/dist/components/toolbar/ToolbarShell.js.map +1 -1
  156. package/dist/components/toolbar/types.d.ts +2 -1
  157. package/dist/components/toolbar/types.d.ts.map +1 -1
  158. package/dist/core/render-native-invoker.d.ts +1 -1
  159. package/dist/core/render-native-invoker.d.ts.map +1 -1
  160. package/dist/core/render-native-invoker.js.map +1 -1
  161. package/dist/styles/index.css +1 -1
  162. package/package.json +4 -2
  163. package/skills/uiify/SKILL.md +167 -0
  164. package/skills/uiify/scripts/lint.mjs +56 -0
  165. package/skills/uiify/scripts/static.mjs +95 -0
package/README.md CHANGED
@@ -7,7 +7,7 @@ Native-first, accessible React 19 components that work before hydration.
7
7
  ## Install
8
8
 
9
9
  ```bash
10
- npm install @gunkin/uiify@alpha react react-dom
10
+ npm install @gunkin/uiify react react-dom
11
11
  ```
12
12
 
13
13
  ## Use
@@ -32,6 +32,51 @@ export function SaveButton() {
32
32
  Use focused `@gunkin/uiify/components/*`, `@gunkin/uiify/elements/*`, `@gunkin/uiify/core/*`, or `@gunkin/uiify/hooks` imports in
33
33
  Server Components so client boundaries remain explicit.
34
34
 
35
+ ## AI coding agents
36
+
37
+ `@gunkin/uiify` ships rules, a component index and per-component references that match the
38
+ installed version. Add one line to your project's `AGENTS.md`, or to `CLAUDE.md` for Claude Code
39
+ (it does not read `AGENTS.md`):
40
+
41
+ ```text
42
+ For @gunkin/uiify, read node_modules/@gunkin/uiify/agents/index.md
43
+ ```
44
+
45
+ In a monorepo with hoisted dependencies, point to the nearest `node_modules/@gunkin/uiify`.
46
+
47
+ ### `/uiify` page-building skill
48
+
49
+ The package also includes the `/uiify` AI skill. Use it when an agent is creating or improving a
50
+ web page with UIify: it maps the brief to available components, plans the page in `DESIGN.md`,
51
+ implements the page in `src/App.tsx` when that file exists, and reports the checks it could run.
52
+ It uses the installed package's component references and follows UIify's public styling and
53
+ accessibility contracts. Invoke it explicitly so it runs only for page-building work.
54
+
55
+ Install the skill into the directory your agent reads:
56
+
57
+ ```bash
58
+ # Cross-tool Agent Skills location (Codex, Copilot, Cursor, and compatible tools)
59
+ mkdir -p .agents/skills/uiify
60
+ cp -R node_modules/@gunkin/uiify/skills/uiify/. .agents/skills/uiify/
61
+
62
+ # For Claude Code, use this location instead
63
+ mkdir -p .claude/skills/uiify
64
+ cp -R node_modules/@gunkin/uiify/skills/uiify/. .claude/skills/uiify/
65
+ ```
66
+
67
+ Then invoke `/uiify <page brief>` in Claude Code, or use the explicit skill invocation supported by
68
+ your agent. Add `--auto` to run all stages without confirmation gates. Interactive runs pause at
69
+ each stage so you can stop before implementation. The skill writes its design state to `DESIGN.md`
70
+ and page code under `src/`; it does not create a page when `src/App.tsx` is absent.
71
+
72
+ ### Keeping the skill current when developing UIify
73
+
74
+ When changing a UIify component, update its public component reference and example when its API or
75
+ usage changes, and update the harness catalog when its coverage or gap status changes. Then run
76
+ `npm run checks:fix` from the repository root. This regenerates the consumer AI docs and `/uiify`
77
+ skill, then checks their tests and freshness. Review and commit generated changes with the component
78
+ change. `npm run check:ai-harness` runs the focused tests and freshness checks without rewriting files.
79
+
35
80
  Documentation: https://uiify.gunkin.dev/
36
81
 
37
82
  MIT © Anton Gunkin
@@ -0,0 +1,80 @@
1
+ <!-- Generated from the package source. Do not edit by hand. -->
2
+ # @gunkin/uiify — component index
3
+
4
+ Rules and anti-patterns: [index.md](./index.md). Each entry links to a generated reference with
5
+ its exports, props and shapes; exact types are in the `.d.ts` file listed in the Types column.
6
+
7
+ ## Tiers
8
+
9
+ | Tier | Meaning | Client JavaScript | Without JavaScript |
10
+ | --- | --- | --- | --- |
11
+ | 0 | RSC — zero client JavaScript | 0 kB | full |
12
+ | 1 | RSC shell + thin client island | <= 1 kB | degraded-documented |
13
+ | 2 | Client component — pre-hydration SSR | n/a | pre-hydration-only |
14
+
15
+ ## State sources
16
+
17
+ | Source | Meaning |
18
+ | --- | --- |
19
+ | S1 | Native element state — browser owns it and updates the accessibility tree itself |
20
+ | S2 | Hidden input + :has() propagation — CSS-readable, ARIA needs a client island |
21
+ | none | Stateless markup |
22
+
23
+ ## Components
24
+
25
+ | Component | Import | Tier | State | Native element | Types | Notes |
26
+ | --- | --- | --- | --- | --- | --- | --- |
27
+ | [accordion](./reference/components/accordion.md) | `@gunkin/uiify/components/accordion` | 0 | S1 | `details[name]` | `dist/components/accordion.d.ts` | Native details/summary disclosure; name groups single-open items. Built on @gunkin/uiify/elements/details. |
28
+ | [alert-modal](./reference/components/alert-modal.md) | `@gunkin/uiify/components/alert-modal` | 0 | S1 | `dialog[role=alertdialog] + command=show-modal` | `dist/components/alert-modal.d.ts` | Native modal alertdialog via show-modal; Cancel/Action are request-close invokers. Baseline Chrome 139 / Firefox 147 / Safari 26.2; below it UIEnhance's invoker fallback runs the command after hydration. |
29
+ | [breadcrumb](./reference/components/breadcrumb.md) | `@gunkin/uiify/components/breadcrumb` | 0 | none | `nav>ol` | `dist/components/breadcrumb.d.ts` | Ellipsis expand/collapse is a native details/summary disclosure, built on @gunkin/uiify/elements/details. |
30
+ | [button](./reference/components/button.md) | `@gunkin/uiify/components/button` | 0 | none | `button` | `dist/components/button.d.ts` | |
31
+ | [candle-chart](./reference/components/candle-chart.md) | `@gunkin/uiify/components/candle-chart` | 0 | none | `figure>ol>li` | `dist/components/candle-chart.d.ts` | Static OHLC geometry is computed during render and expressed as percentage CSS custom properties; the decorative candle glyphs have an accessible table fallback. |
32
+ | [line-chart](./reference/components/line-chart.md) | `@gunkin/uiify/components/line-chart` | 0 | none | `figure>ol>li` | `dist/components/line-chart.d.ts` | Static line segments are computed during render and expressed as percentage CSS custom properties; the decorative CSS line has an accessible table fallback. |
33
+ | [carousel](./reference/components/carousel.md) | `@gunkin/uiify/components/carousel` | 2 | none | `section > div[scroll-snap]` | `dist/components/carousel.d.ts` | The documented interactive carousel uses /client and requires hydration for synchronized controls. The base entry remains a native no-JS scroller with CSS Scroll Snap and fragment navigation; /fade adds client-driven CSS transitions. |
34
+ | [checkbox](./reference/components/checkbox.md) | `@gunkin/uiify/components/checkbox` | 0 | S1 | `input[type=checkbox]` | `dist/components/checkbox.d.ts` | Native checkbox + label; default entry ships controlled callbacks with use client. |
35
+ | [collapsible](./reference/components/collapsible.md) | `@gunkin/uiify/components/collapsible` | 0 | S1 | `details` | `dist/components/collapsible.d.ts` | Native details/summary disclosure. Built on @gunkin/uiify/elements/details. |
36
+ | [modal](./reference/components/modal.md) | `@gunkin/uiify/components/modal` | 0 | S1 | `dialog + command=show-modal` | `dist/components/modal.d.ts` | True modal via show-modal/request-close; the browser owns inertness, Escape and focus return. Controlled/initially open state lives in @gunkin/uiify/components/modal/client. Trigger/Close built on @gunkin/uiify/elements/dialog. Backdrop tap and swipe-down are optional UIEnhance improvements; without them the modal still closes by icon, Escape and (Chrome/Firefox) backdrop tap. |
37
+ | [drawer](./reference/components/drawer.md) | `@gunkin/uiify/components/drawer` | 0 | S1 | `dialog + command=show-modal` | `dist/components/drawer.d.ts` | DrawerPanel native shell + compound Drawer.* client API; snap-point drag on client entry. |
38
+ | [field](./reference/components/field.md) | `@gunkin/uiify/components/field` | 0 | none | `div:has(input)` | `dist/components/field.d.ts` | :user-invalid + :has() reveals the error message |
39
+ | [form](./reference/components/form.md) | `@gunkin/uiify/components/form` | 0 | none | `form` | `dist/components/form.d.ts` | |
40
+ | [input](./reference/components/input.md) | `@gunkin/uiify/components/input` | 0 | S1 | `input` | `dist/components/input.d.ts` | |
41
+ | [pagination](./reference/components/pagination.md) | `@gunkin/uiify/components/pagination` | 0 | none | `nav>ol>a` | `dist/components/pagination.d.ts` | |
42
+ | [popup](./reference/components/popup.md) | `@gunkin/uiify/components/popup` | 0 | S1 | `[popover]+popovertarget` | `dist/components/popup.d.ts` | Native parts anchor to their invoker (implicit anchor) and carry no aria-expanded; Chromium exposes expanded through the accessibility tree, other engines are unmeasured. The legacy Popup.Root compound keeps UIEnhance for its DOM attribute. Trigger/Content/Close built on @gunkin/uiify/elements/popover. |
43
+ | [radio-group](./reference/components/radio-group.md) | `@gunkin/uiify/components/radio-group` | 0 | S1 | `input[type=radio]` | `dist/components/radio-group.d.ts` | Data-driven native radio group; browser owns selection. Built on @gunkin/uiify/elements/choice. |
44
+ | [rating](./reference/components/rating.md) | `@gunkin/uiify/components/rating` | 0 | S1 | `input[type=radio]` | `dist/components/rating.d.ts` | Native radio group; hover preview and persisted selection are pure CSS (:checked/:hover sibling rules), no JS. Controlled value/onValueChange lives in the separate rating/client entry. Built on @gunkin/uiify/elements/choice. |
45
+ | [segmented-control](./reference/components/segmented-control.md) | `@gunkin/uiify/components/segmented-control` | 0 | S1 | `input[type=radio]` | `dist/components/segmented-control.d.ts` | Built on @gunkin/uiify/elements/choice. |
46
+ | [select](./reference/components/select.md) | `@gunkin/uiify/components/select` | 0 | S1 | `select` | `dist/components/select.d.ts` | Native text-only select; appearance:base-select is a Chrome+Safari cosmetic enhancement and Firefox keeps the OS picker. |
47
+ | [skeleton](./reference/components/skeleton.md) | `@gunkin/uiify/components/skeleton` | 0 | none | `div` | `dist/components/skeleton.d.ts` | |
48
+ | [slider](./reference/components/slider.md) | `@gunkin/uiify/components/slider` | 0 | S1 | `input[type=range]` | `dist/components/slider.d.ts` | |
49
+ | [spinner](./reference/components/spinner.md) | `@gunkin/uiify/components/spinner` | 0 | none | `div` | `dist/components/spinner.d.ts` | |
50
+ | [switch](./reference/components/switch.md) | `@gunkin/uiify/components/switch` | 0 | S1 | `input[type=checkbox]` | `dist/components/switch.d.ts` | |
51
+ | [table](./reference/components/table.md) | `@gunkin/uiify/components/table` | 0 | none | `table` | `dist/components/table.d.ts` | Native semantic Table parts; selection, sorting and expansion use the explicit /client entry. |
52
+ | [textarea](./reference/components/textarea.md) | `@gunkin/uiify/components/textarea` | 0 | S1 | `textarea` | `dist/components/textarea.d.ts` | field-sizing:content replaces the auto-grow JS. Baseline since Firefox 152. |
53
+ | [toggle](./reference/components/toggle.md) | `@gunkin/uiify/components/toggle` | 0 | S1 | `input[type=checkbox]` | `dist/components/toggle.d.ts` | Native checkbox + label toggle; browser owns pressed state. |
54
+ | [toggle-group](./reference/components/toggle-group.md) | `@gunkin/uiify/components/toggle-group` | 0 | S1 | `input[type=radio\|checkbox]` | `dist/components/toggle-group.d.ts` | Built on @gunkin/uiify/elements/choice. |
55
+ | [tooltip](./reference/components/tooltip.md) | `@gunkin/uiify/components/tooltip` | 1 | S1 | `[popover]` | `dist/components/tooltip.d.ts` | |
56
+ | [hover-card](./reference/components/hover-card.md) | `@gunkin/uiify/components/hover-card` | 1 | S1 | `[popover]` | `dist/components/hover-card.d.ts` | |
57
+ | [toast](./reference/components/toast.md) | `@gunkin/uiify/components/toast` | 1 | S1 | `[popover] + aria-live` | `dist/components/toast.d.ts` | |
58
+ | [number-field](./reference/components/number-field.md) | `@gunkin/uiify/components/number-field` | 1 | S1 | `input[type=number]` | `dist/components/number-field.d.ts` | |
59
+ | [toolbar](./reference/components/toolbar.md) | `@gunkin/uiify/components/toolbar` | 1 | none | `div[role=toolbar]` | `dist/components/toolbar.d.ts` | |
60
+ | [file-upload](./reference/components/file-upload.md) | `@gunkin/uiify/components/file-upload` | 1 | S1 | `input[type=file]` | `dist/components/file-upload.d.ts` | |
61
+ | [header](./reference/components/header.md) | `@gunkin/uiify/components/header` | 0 | S1 | `header` | `dist/components/header.d.ts` | Semantic header root; compose native navigation with Modal. Full functionality without JavaScript; optional header/client adds scroll hide/reveal. |
62
+ | [tabs](./reference/components/tabs.md) | `@gunkin/uiify/components/tabs` | 0 | S1 | `input[type=radio]` | `dist/components/tabs.d.ts` | Data-driven native radio switcher; CSS-only panels. Built on @gunkin/uiify/elements/choice. |
63
+ | [dropdown-menu](./reference/components/dropdown-menu.md) | `@gunkin/uiify/components/dropdown-menu` | 2 | S2 | `[popover]+commandfor` | `dist/components/dropdown-menu.d.ts` | |
64
+ | [combobox](./reference/components/combobox.md) | `@gunkin/uiify/components/combobox` | 2 | S2 | `input+listbox` | `dist/components/combobox.d.ts` | |
65
+ | [context-menu](./reference/components/context-menu.md) | `@gunkin/uiify/components/context-menu` | 2 | S2 | `[popover]` | `dist/components/context-menu.d.ts` | |
66
+ | [tags-input](./reference/components/tags-input.md) | `@gunkin/uiify/components/tags-input` | 2 | none | `input` | `dist/components/tags-input.d.ts` | |
67
+ | [otp-input](./reference/components/otp-input.md) | `@gunkin/uiify/components/otp-input` | 2 | none | `input` | `dist/components/otp-input.d.ts` | |
68
+ | [color-picker](./reference/components/color-picker.md) | `@gunkin/uiify/components/color-picker` | 1 | S1 | `input[type=color]` | `dist/components/color-picker.d.ts` | |
69
+ | [virtual-scroll](./reference/components/virtual-scroll.md) | `@gunkin/uiify/components/virtual-scroll` | 2 | none | `div[overflow]` | `dist/components/virtual-scroll.d.ts` | |
70
+ | [table-of-contents](./reference/components/table-of-contents.md) | `@gunkin/uiify/components/table-of-contents` | 2 | S1 | `nav + button[popovertarget] + [popover] + a[href]` | `dist/components/table-of-contents.d.ts` | Base entry is a server-pure native navigation shell; /client adds enhancements. Native links and popover invocation/dismissal work without JavaScript. |
71
+
72
+ ## Elements
73
+
74
+ | Element | Import | Native mechanism | Parts | Used by | Types |
75
+ | --- | --- | --- | --- | --- | --- |
76
+ | [invoker](./reference/elements/invoker.md) | `@gunkin/uiify/elements/invoker` | command/commandfor attributes | `Invoker` | dialog | `dist/elements/invoker.d.ts` |
77
+ | [dialog](./reference/elements/dialog.md) | `@gunkin/uiify/elements/dialog` | dialog + command=show-modal | `Dialog.Trigger`, `Dialog.Content`, `Dialog.Close` | modal, alert-modal, drawer | `dist/elements/dialog.d.ts` |
78
+ | [popover](./reference/elements/popover.md) | `@gunkin/uiify/elements/popover` | [popover] + popovertarget | `Popover.Trigger`, `Popover.Surface`, `Popover.Close` | popup | `dist/elements/popover.d.ts` |
79
+ | [details](./reference/elements/details.md) | `@gunkin/uiify/elements/details` | details/summary | `Details.Root`, `Details.Summary`, `Details.Content` | accordion, collapsible, breadcrumb | `dist/elements/details.d.ts` |
80
+ | [choice](./reference/elements/choice.md) | `@gunkin/uiify/elements/choice` | input[type=radio\|checkbox] + label | `Choice.Group`, `Choice.Item` | radio-group, tabs, toggle-group, segmented-control, rating | `dist/elements/choice.d.ts` |
@@ -0,0 +1,179 @@
1
+ # @gunkin/uiify — rules for AI coding agents
2
+
3
+ This file ships inside the installed package, so it always matches the version in `node_modules`.
4
+ Read it before writing code that imports `@gunkin/uiify`.
5
+
6
+ - Component list, tiers and import paths: [components.md](./components.md)
7
+ - Per-component exports, props and shapes: the reference file linked from `components.md`
8
+ - Exact types: the `.d.ts` file listed for each entry in `components.md`
9
+ - Docs site: https://uiify.gunkin.dev/
10
+
11
+ ## What you will probably get wrong
12
+
13
+ Models trained on Radix, shadcn/ui and similar libraries reach for their idioms. These do not
14
+ exist here.
15
+
16
+ | You are about to write | Write this instead | Why |
17
+ | --- | --- | --- |
18
+ | `asChild` | `as="a"` or `render={...}` | There is no Slot. Polymorphism is `as` or `render`. |
19
+ | `cva(...)` or another class-string builder | `variant` / `size` props, and CSS on `[data-variant]` / `[data-size]` | Props only write a `data-*` attribute; the rules live in CSS. |
20
+ | `className={(state) => ...}` | A plain string `className`; select state with `[data-state]`, `[data-disabled]` and friends | `className` is never a function. |
21
+ | `contentClassName`, `triggerClassName`, `itemClassName`, `contentStyle` | `className` / `style` on the part itself | Every public part takes its own `className`. |
22
+ | `onChange={(value) => ...}` on a root or control | `onValueChange`, `onOpenChange`, `onCheckedChange`, `onPageChange` | `onChange` is the native DOM `change` event and receives the event. |
23
+ | `isOpen`, `isDisabled`, `isChecked` | `open`, `disabled`, `checked` | No `is` prefix. |
24
+ | `placement="bottom-start"` | `side="bottom" align="start"` | One vocabulary for popups. |
25
+ | `data-open` | `data-state="open"` | Open state is `data-state`; there is no `data-open`. |
26
+ | React context or child cloning to connect parts | The shared id you pass to each part: `fieldId`, `target` | Server-compatible parts are wired by ids, not context. |
27
+
28
+ ## Vocabulary
29
+
30
+ | Concept | Props | Attribute |
31
+ | --- | --- | --- |
32
+ | Controlled value | `value`, `defaultValue`, `onValueChange(value)` | |
33
+ | Open state | `open`, `defaultOpen`, `onOpenChange(open)` | `data-state="open"` or `"closed"` |
34
+ | Checked state | `checked`, `defaultChecked`, `onCheckedChange` | `data-state="checked"`, `"unchecked"` or `"indeterminate"` on controlled checkboxes and switches; style uncontrolled inputs with `:checked` |
35
+ | Current page | `page`, `defaultPage`, `onPageChange(page)` | |
36
+ | Visual style | `variant` (omit for the default solid style) | `data-variant` |
37
+ | Scale | `size` | `data-size` |
38
+ | Direction | `orientation` | `data-orientation` |
39
+ | Popup placement | `side`, `align` | `data-side`, `data-align` |
40
+ | Form flags | `disabled`, `required`, `readOnly`, `invalid` | `data-disabled`, `data-required`, `data-readonly`, `data-invalid` |
41
+
42
+ Other state attributes: `data-highlighted`, `data-selected`, `data-positioning`, and
43
+ `data-active` on the active slot of the OTP input. Every public root and standalone part carries an
44
+ identity marker, for example `data-uiify-button`; compound parts carry a kebab-case `data-part`. The values of `variant` and
45
+ `size` differ per component: read the component's reference file.
46
+
47
+ ## Examples
48
+
49
+ Variants and sizes are props that write attributes:
50
+
51
+ ```tsx
52
+ import { Button } from "@gunkin/uiify/components/button";
53
+
54
+ export function RemoveButton() {
55
+ return (
56
+ <Button variant="destructive" size="sm" type="button">
57
+ Remove
58
+ </Button>
59
+ );
60
+ }
61
+ ```
62
+
63
+ `as` swaps the rendered element and keeps the component's behavior:
64
+
65
+ ```tsx
66
+ import { Button } from "@gunkin/uiify/components/button";
67
+
68
+ export function BillingLink() {
69
+ return (
70
+ <Button as="a" href="/billing" variant="link">
71
+ Billing
72
+ </Button>
73
+ );
74
+ }
75
+ ```
76
+
77
+ Native server parts do not share React context. Each part names its root with an id you choose:
78
+
79
+ ```tsx
80
+ import { Field } from "@gunkin/uiify/components/field";
81
+
82
+ export function EmailField({ invalid }: { readonly invalid: boolean }) {
83
+ return (
84
+ <Field.Root id="email" invalid={invalid} required>
85
+ <Field.Label fieldId="email" required>
86
+ Email
87
+ </Field.Label>
88
+ <Field.Control as="input" fieldId="email" type="email" invalid={invalid} required />
89
+ <Field.Description fieldId="email">We only use it to send receipts.</Field.Description>
90
+ <Field.Error fieldId="email" invalid={invalid}>
91
+ Enter a valid email address
92
+ </Field.Error>
93
+ </Field.Root>
94
+ );
95
+ }
96
+ ```
97
+
98
+ A trigger and its close button reference the dialog by `id` and `target`:
99
+
100
+ ```tsx
101
+ import { Modal, ModalClose } from "@gunkin/uiify/components/modal";
102
+
103
+ export function DeleteProject() {
104
+ return (
105
+ <Modal
106
+ id="delete-project"
107
+ title="Delete project?"
108
+ description="This cannot be undone."
109
+ trigger="Delete project"
110
+ footer={<ModalClose target="delete-project">Cancel</ModalClose>}
111
+ >
112
+ <p>All files in the project will be removed.</p>
113
+ </Modal>
114
+ );
115
+ }
116
+ ```
117
+
118
+ This is the wrong version of the second example:
119
+
120
+ ```tsx wrong
121
+ <Button asChild className={cva("px-4", { variants: {} })}>
122
+ <a href="/billing">Billing</a>
123
+ </Button>
124
+ ```
125
+
126
+ ## Style with attributes
127
+
128
+ Components ship behavior CSS only; the theme is optional. Load both from one stylesheet and
129
+ declare the layer order on its first line:
130
+
131
+ ```css
132
+ @layer reset, tokens, base, demo, components, utilities, theme, ui, app;
133
+ @import "@gunkin/uiify/components/behavior.css";
134
+ @import "@gunkin/uiify/styles/reset";
135
+ @import "@gunkin/uiify/styles/tokens";
136
+ @import "@gunkin/uiify/styles";
137
+ ```
138
+
139
+ `behavior.css` declares `ui.reset, ui.behavior, ui.tokens, ui.theme, app` and the theme declares
140
+ `reset, tokens, base, demo, components, utilities, theme`. Layers rank by first declaration, so
141
+ the statement above only works if nothing loads `behavior.css` earlier: do not also import it from
142
+ JavaScript. Unlayered rules beat every layer.
143
+
144
+ With that order in place, rules in the `app` layer win over the library:
145
+
146
+ ```css
147
+ @layer app {
148
+ [data-uiify-button][data-variant="destructive"] {
149
+ text-transform: uppercase;
150
+ }
151
+ }
152
+ ```
153
+
154
+ ## Imports
155
+
156
+ - `@gunkin/uiify/components/<name>`: components (names in `components.md`)
157
+ - `@gunkin/uiify/elements/<name>`: native-element primitives for building your own anatomy
158
+ - `@gunkin/uiify/hooks`: hooks
159
+ - `@gunkin/uiify/core/<name>`: React-agnostic stores and render helpers
160
+ - `@gunkin/uiify/components/behavior.css`: required behavior CSS, no visual styles
161
+ - `@gunkin/uiify/styles`: optional theme; also `styles/tokens`, `styles/reset`, `styles/tailwind`
162
+
163
+ ## Server Components and hydration
164
+
165
+ Check a component's tier in `components.md` before importing it into a Server Component.
166
+
167
+ - Tier 0 renders with zero client JavaScript and works without JavaScript.
168
+ - Tier 1 is a server shell with a small client island.
169
+ - Tier 2 is a client component. It renders native-first markup before hydration, but keyboard
170
+ behavior and ARIA sync need hydration.
171
+
172
+ Some components also have sub-entries such as `@gunkin/uiify/components/modal/client` for
173
+ controlled state. They are listed under **Sub-entries** in the component's reference file.
174
+
175
+ TableOfContents has a server-pure base entry for native popover buttons and fragment links.
176
+ Import `@gunkin/uiify/components/table-of-contents/client` for scrollspy, hover opening,
177
+ pinning and controlled `value`/`open`. Provide unique `Content.id` and matching `Trigger.target`,
178
+ label the navigation and trigger, and match each `Indicator.value` to a target heading ID.
179
+ The client Root owns context for its parts. A permanent list omits Trigger and Content.
@@ -0,0 +1,35 @@
1
+ <!-- Generated from the package source. Do not edit by hand. -->
2
+ # accordion
3
+
4
+ - Import: `@gunkin/uiify/components/accordion`
5
+ - Tier 0 (RSC — zero client JavaScript); state source S1; native element `details[name]`
6
+ - Without JavaScript: full
7
+ - Types file: `dist/components/accordion.d.ts`
8
+ - Note: Native details/summary disclosure; name groups single-open items. Built on @gunkin/uiify/elements/details.
9
+
10
+ ## Exports
11
+
12
+ - Runtime: `Accordion`
13
+ - Types: `AccordionItem`, `AccordionProps`, `AccordionType`
14
+
15
+ ## Values
16
+
17
+ - `AccordionType`: `"single" | "multiple"`
18
+
19
+ ## Props and shapes
20
+
21
+ ### AccordionItem
22
+
23
+ Extends: `ChoicePanelItem`
24
+
25
+ No own members.
26
+
27
+ ### AccordionProps
28
+
29
+ | Member | Type | Required | Description |
30
+ | --- | --- | --- | --- |
31
+ | `id` | `string` | yes | |
32
+ | `items` | `readonly AccordionItem[]` | yes | |
33
+ | `type` | `AccordionType` | no | |
34
+ | `defaultValue` | `string \| readonly string[]` | no | |
35
+ | `className` | `string` | no | |
@@ -0,0 +1,63 @@
1
+ <!-- Generated from the package source. Do not edit by hand. -->
2
+ # alert-modal
3
+
4
+ - Import: `@gunkin/uiify/components/alert-modal`
5
+ - Tier 0 (RSC — zero client JavaScript); state source S1; native element `dialog[role=alertdialog] + command=show-modal`
6
+ - Without JavaScript: full
7
+ - Types file: `dist/components/alert-modal.d.ts`
8
+ - Note: Native modal alertdialog via show-modal; Cancel/Action are request-close invokers. Baseline Chrome 139 / Firefox 147 / Safari 26.2; below it UIEnhance's invoker fallback runs the command after hydration.
9
+
10
+ ## Exports
11
+
12
+ - Runtime: `AlertModal`, `AlertModalAction`, `AlertModalCancel`, `AlertModalContent`, `AlertModalTrigger`
13
+ - Types: `AlertModalActionOwnProps`, `AlertModalActionProps`, `AlertModalCancelOwnProps`, `AlertModalCancelProps`, `AlertModalContentOwnProps`, `AlertModalContentProps`, `AlertModalProps`, `AlertModalTriggerOwnProps`, `AlertModalTriggerProps`
14
+
15
+ ## Props and shapes
16
+
17
+ ### AlertModalProps
18
+
19
+ | Member | Type | Required | Description |
20
+ | --- | --- | --- | --- |
21
+ | `id` | `string` | yes | |
22
+ | `trigger` | `ReactNode` | yes | |
23
+ | `title` | `ReactNode` | yes | |
24
+ | `description` | `ReactNode` | no | |
25
+ | `children` | `ReactNode` | no | |
26
+ | `actionLabel` | `ReactNode` | no | |
27
+ | `cancelLabel` | `ReactNode` | no | |
28
+ | `className` | `string` | no | |
29
+
30
+ ### AlertModalTriggerOwnProps
31
+
32
+ | Member | Type | Required | Description |
33
+ | --- | --- | --- | --- |
34
+ | `children` | `ReactNode` | no | |
35
+ | `target` | `string` | yes | `id` of the `AlertModalContent` this button opens. |
36
+
37
+ ### AlertModalActionOwnProps
38
+
39
+ | Member | Type | Required | Description |
40
+ | --- | --- | --- | --- |
41
+ | `children` | `ReactNode` | no | |
42
+ | `target` | `string` | yes | |
43
+
44
+ ### AlertModalCancelOwnProps
45
+
46
+ | Member | Type | Required | Description |
47
+ | --- | --- | --- | --- |
48
+ | `children` | `ReactNode` | no | |
49
+ | `target` | `string` | yes | |
50
+
51
+ ### AlertModalContentOwnProps
52
+
53
+ | Member | Type | Required | Description |
54
+ | --- | --- | --- | --- |
55
+ | `children` | `ReactNode` | no | |
56
+ | `id` | `string` | yes | |
57
+
58
+ ## Other types
59
+
60
+ - `AlertModalTriggerProps<TAs>`: `NativeButtonProps<TAs, AlertModalTriggerOwnProps>`
61
+ - `AlertModalActionProps<TAs>`: `NativeButtonProps<TAs, AlertModalActionOwnProps>`
62
+ - `AlertModalCancelProps<TAs>`: `NativeButtonProps<TAs, AlertModalCancelOwnProps>`
63
+ - `AlertModalContentProps`: `AlertModalContentOwnProps & Omit<ComponentPropsWithRef<"dialog">, keyof AlertModalContentOwnProps | "open" | "popover" | "role">` — `<dialog role="alertdialog">`; `role`, `open` and `popover` belong to the part.
@@ -0,0 +1,72 @@
1
+ <!-- Generated from the package source. Do not edit by hand. -->
2
+ # breadcrumb
3
+
4
+ - Import: `@gunkin/uiify/components/breadcrumb`
5
+ - Tier 0 (RSC — zero client JavaScript); state source none; native element `nav>ol`
6
+ - Without JavaScript: full
7
+ - Types file: `dist/components/breadcrumb.d.ts`
8
+ - Note: Ellipsis expand/collapse is a native details/summary disclosure, built on @gunkin/uiify/elements/details.
9
+
10
+ ## Exports
11
+
12
+ - Runtime: `Breadcrumb`, `BreadcrumbEllipsis`, `BreadcrumbItem`, `BreadcrumbLink`, `BreadcrumbList`, `BreadcrumbRoot`, `BreadcrumbSeparator`
13
+ - Types: `BreadcrumbItemData`, `BreadcrumbItemProps`, `BreadcrumbLinkOwnProps`, `BreadcrumbLinkProps`, `BreadcrumbListOwnProps`, `BreadcrumbListProps`, `BreadcrumbRootOwnProps`, `BreadcrumbRootProps`, `BreadcrumbSeparatorOwnProps`, `BreadcrumbSeparatorProps`
14
+
15
+ ## Props and shapes
16
+
17
+ ### BreadcrumbRootOwnProps
18
+
19
+ | Member | Type | Required | Description |
20
+ | --- | --- | --- | --- |
21
+ | `"aria-label"` | `string` | no | |
22
+
23
+ ### BreadcrumbItemData
24
+
25
+ One logical breadcrumb entry. Used by `BreadcrumbList`'s `items` prop — the data-driven alternative to `children` that `maxItems` collapsing requires (see BreadcrumbList's own doc comment for why).
26
+
27
+ | Member | Type | Required | Description |
28
+ | --- | --- | --- | --- |
29
+ | `key` | `string` | yes | |
30
+ | `current` | `boolean` | no | |
31
+ | `href` | `string` | no | |
32
+ | `label` | `ReactNode` | yes | |
33
+
34
+ ### BreadcrumbListOwnProps
35
+
36
+ | Member | Type | Required | Description |
37
+ | --- | --- | --- | --- |
38
+ | `children` | `ReactNode` | no | |
39
+ | `items` | `readonly BreadcrumbItemData[]` | no | Data-driven items, required to use `maxItems`. Filtering children by element type (`isValidElement` + a type check) can't see through a Fragment-free `.map()` over route data into a custom wrapper component — a real element only becomes visible to a parent's child introspection once React actually renders it, which hasn't happened yet when `BreadcrumbList` itself runs. An explicit array has no such blind spot. |
40
+ | `itemsAfterCollapse` | `number` | no | |
41
+ | `itemsBeforeCollapse` | `number` | no | |
42
+ | `maxItems` | `number` | no | |
43
+ | `separator` | `ReactNode` | no | |
44
+
45
+ ### BreadcrumbLinkOwnProps
46
+
47
+ | Member | Type | Required | Description |
48
+ | --- | --- | --- | --- |
49
+ | `children` | `ReactNode` | no | |
50
+ | `current` | `boolean` | no | |
51
+ | `href` | `string` | no | |
52
+
53
+ ### BreadcrumbSeparatorOwnProps
54
+
55
+ | Member | Type | Required | Description |
56
+ | --- | --- | --- | --- |
57
+ | `children` | `ReactNode` | no | |
58
+
59
+ ### BreadcrumbEllipsisProps
60
+
61
+ | Member | Type | Required | Description |
62
+ | --- | --- | --- | --- |
63
+ | `hiddenItems` | `readonly BreadcrumbItemData[]` | yes | |
64
+ | `separator` | `ReactNode` | no | |
65
+
66
+ ## Other types
67
+
68
+ - `BreadcrumbRootProps<TAs>`: `RenderableProps<TAs, BreadcrumbRootOwnProps, Record<string, never>, HTMLElement>`
69
+ - `BreadcrumbListProps<TAs>`: `RenderableProps<TAs, BreadcrumbListOwnProps, Record<string, never>, HTMLOListElement>`
70
+ - `BreadcrumbItemProps<TAs>`: `RenderableProps<TAs, { readonly children?: ReactNode }, Record<string, never>, HTMLLIElement>`
71
+ - `BreadcrumbLinkProps<TAs>`: `RenderableProps<TAs, BreadcrumbLinkOwnProps, { current: boolean }, HTMLAnchorElement>`
72
+ - `BreadcrumbSeparatorProps<TAs>`: `RenderableProps<TAs, BreadcrumbSeparatorOwnProps, Record<string, never>, HTMLElement>`
@@ -0,0 +1,40 @@
1
+ <!-- Generated from the package source. Do not edit by hand. -->
2
+ # button
3
+
4
+ - Import: `@gunkin/uiify/components/button`
5
+ - Tier 0 (RSC — zero client JavaScript); state source none; native element `button`
6
+ - Without JavaScript: full
7
+ - Types file: `dist/components/button.d.ts`
8
+
9
+ ## Exports
10
+
11
+ - Runtime: `Button`
12
+ - Types: `ButtonOwnProps`, `ButtonProps`, `ButtonSize`, `ButtonState`, `ButtonVariant`
13
+
14
+ ## Values
15
+
16
+ - `ButtonVariant`: `"secondary" | "outline" | "ghost" | "destructive" | "link"`
17
+ - `ButtonSize`: `"sm" | "md" | "lg" | "icon-sm" | "icon" | "icon-lg"`
18
+
19
+ ## Props and shapes
20
+
21
+ ### ButtonOwnProps
22
+
23
+ | Member | Type | Required | Description |
24
+ | --- | --- | --- | --- |
25
+ | `disabled` | `boolean` | no | |
26
+ | `selected` | `boolean` | no | Marks the button as the chosen one of a set, or a toggle that is on. |
27
+ | `type` | `"button" \| "submit" \| "reset"` | no | |
28
+ | `size` | `ButtonSize` | no | |
29
+ | `variant` | `ButtonVariant` | no | |
30
+
31
+ ### ButtonState
32
+
33
+ | Member | Type | Required | Description |
34
+ | --- | --- | --- | --- |
35
+ | `disabled` | `boolean` | yes | |
36
+ | `selected` | `boolean` | yes | |
37
+
38
+ ## Other types
39
+
40
+ - `ButtonProps<TAs>`: `RenderableProps<TAs, ButtonOwnProps, ButtonState, HTMLElement>`
@@ -0,0 +1,107 @@
1
+ <!-- Generated from the package source. Do not edit by hand. -->
2
+ # candle-chart
3
+
4
+ - Import: `@gunkin/uiify/components/candle-chart`
5
+ - Tier 0 (RSC — zero client JavaScript); state source none; native element `figure>ol>li`
6
+ - Without JavaScript: full
7
+ - Types file: `dist/components/candle-chart.d.ts`
8
+ - Note: Static OHLC geometry is computed during render and expressed as percentage CSS custom properties; the decorative candle glyphs have an accessible table fallback.
9
+
10
+ ## Exports
11
+
12
+ - Runtime: `CandleChart`
13
+ - Types: `CandleChartAxisLabel`, `CandleChartData`, `CandleChartOwnProps`, `CandleChartPointerPosition`, `CandleChartProps`
14
+
15
+ ## Props and shapes
16
+
17
+ ### CandleChartData
18
+
19
+ | Member | Type | Required | Description |
20
+ | --- | --- | --- | --- |
21
+ | `time` | `string \| number` | yes | |
22
+ | `open` | `number` | yes | |
23
+ | `high` | `number` | yes | |
24
+ | `low` | `number` | yes | |
25
+ | `close` | `number` | yes | |
26
+
27
+ ### CandleChartAxisLabel
28
+
29
+ | Member | Type | Required | Description |
30
+ | --- | --- | --- | --- |
31
+ | `label` | `ReactNode` | yes | |
32
+ | `position` | `number` | yes | Position on the axis as a percentage from 0 to 100. |
33
+
34
+ ### CandleChartPointerPosition
35
+
36
+ | Member | Type | Required | Description |
37
+ | --- | --- | --- | --- |
38
+ | `index` | `number` | yes | |
39
+ | `offsetY` | `number` | yes | Pointer offset inside the candle hit area, in CSS pixels. |
40
+
41
+ ### CandleChartOwnProps
42
+
43
+ | Member | Type | Required | Description |
44
+ | --- | --- | --- | --- |
45
+ | `"aria-label"` | `string` | no | |
46
+ | `activeCandleIndex` | `number` | no | |
47
+ | `cursorY` | `number` | no | |
48
+ | `data` | `readonly CandleChartData[]` | yes | |
49
+ | `interactive` | `boolean` | no | |
50
+ | `onCandleClick` | `(index: number) => void` | no | |
51
+ | `onCandlePointerLeave` | `() => void` | no | |
52
+ | `onCandlePointerMove` | `(position: CandleChartPointerPosition) => void` | no | |
53
+ | `selectedCandleIndex` | `number` | no | |
54
+ | `xAxis` | `readonly CandleChartAxisLabel[]` | no | |
55
+ | `yAxis` | `readonly CandleChartAxisLabel[]` | no | |
56
+
57
+ ### CandleChartClientOwnProps
58
+
59
+ Extends: `CandleChartOwnProps`
60
+
61
+ | Member | Type | Required | Description |
62
+ | --- | --- | --- | --- |
63
+ | `visibleCount` | `number` | no | Live mode: sizes candles so `visibleCount` fill the viewport and virtualizes the full history with a horizontal VirtualScroll. The chart follows new candles while the reader is at the newest one; the price scale, axes, readout, and data table follow the visible candles. Zoom is disabled. |
64
+
65
+ ### CandleChartViewProps
66
+
67
+ Internal props the client entry passes to `CandleChart`; not part of the public API.
68
+
69
+ Extends: `CandleChartOwnProps`
70
+
71
+ | Member | Type | Required | Description |
72
+ | --- | --- | --- | --- |
73
+ | `candleLayer` | `ReactNode` | no | Replaces the static candle list (e.g. with a virtualized layer). |
74
+ | `announceReadout` | `boolean` | no | Announce readout changes; off for streaming data. Defaults to `true`. |
75
+ | `slotCount` | `number` | no | Slots the crosshair is positioned across. Defaults to `data.length`. |
76
+ | `slotOffset` | `number` | no | Slot of `data[0]` within those slots, when `data` is a slice. Defaults to `0`. |
77
+
78
+ ### CandleChartCandleProps
79
+
80
+ | Member | Type | Required | Description |
81
+ | --- | --- | --- | --- |
82
+ | `as` | `"div" \| "li"` | yes | |
83
+ | `candle` | `CandleChartData` | yes | |
84
+ | `index` | `number` | yes | Index reported to the pointer and click callbacks. |
85
+ | `x` | `number` | yes | Candle position and width, as percentages of the candle layer. |
86
+ | `slot` | `number` | yes | |
87
+ | `min` | `number` | yes | |
88
+ | `max` | `number` | yes | |
89
+ | `interactive` | `boolean` | yes | |
90
+ | `isActive` | `boolean` | yes | |
91
+ | `isSelected` | `boolean` | yes | |
92
+ | `cursorY` | `number \| undefined` | no | |
93
+ | `onCandleClick` | `((index: number) => void) \| undefined` | no | |
94
+ | `onCandlePointerLeave` | `(() => void) \| undefined` | no | |
95
+ | `onCandlePointerMove` | `((position: CandleChartPointerPosition) => void) \| undefined` | no | |
96
+
97
+ ## Other types
98
+
99
+ - `CandleChartProps<TAs>`: `RenderableProps<TAs, CandleChartOwnProps, Record<string, never>, HTMLElement>`
100
+ - `CandleChartClientProps<TAs>`: `RenderableProps<TAs, CandleChartClientOwnProps, Record<string, never>, HTMLElement>`
101
+
102
+ ## Sub-entries
103
+
104
+ ### `@gunkin/uiify/components/candle-chart/client`
105
+
106
+ - Runtime: `CandleChartClient`
107
+ - Types: `CandleChartClientOwnProps`, `CandleChartClientProps`