@astryxdesign/core 0.5.1 → 0.5.2-canary.00477a5

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 (270) hide show
  1. package/CHANGELOG.md +19 -0
  2. package/dist/BottomSheet/BottomSheet.d.ts +3 -1
  3. package/dist/BottomSheet/BottomSheet.d.ts.map +1 -1
  4. package/dist/BottomSheet/BottomSheet.js +4 -3
  5. package/dist/BottomSheet/BottomSheetEdgeTint.d.ts +2 -2
  6. package/dist/BottomSheet/BottomSheetEdgeTint.d.ts.map +1 -1
  7. package/dist/BottomSheet/BottomSheetEdgeTint.js +7 -10
  8. package/dist/BottomSheet/BottomSheetSwitcher.d.ts.map +1 -1
  9. package/dist/BottomSheet/BottomSheetSwitcher.js +1 -1
  10. package/dist/Button/Button.d.ts +2 -1
  11. package/dist/Button/Button.d.ts.map +1 -1
  12. package/dist/Button/Button.js +11 -4
  13. package/dist/Carousel/Carousel.d.ts.map +1 -1
  14. package/dist/Carousel/Carousel.js +2 -2
  15. package/dist/Chat/ChatToolCalls.d.ts.map +1 -1
  16. package/dist/Chat/ChatToolCalls.js +34 -17
  17. package/dist/ContextMenu/ContextMenu.d.ts +14 -3
  18. package/dist/ContextMenu/ContextMenu.d.ts.map +1 -1
  19. package/dist/ContextMenu/ContextMenu.js +149 -26
  20. package/dist/ContextMenu/index.d.ts +1 -0
  21. package/dist/ContextMenu/index.d.ts.map +1 -1
  22. package/dist/DropdownMenu/DropdownMenu.d.ts +24 -5
  23. package/dist/DropdownMenu/DropdownMenu.d.ts.map +1 -1
  24. package/dist/DropdownMenu/DropdownMenu.js +340 -26
  25. package/dist/DropdownMenu/DropdownMenuContext.d.ts +1 -1
  26. package/dist/DropdownMenu/DropdownMenuContext.d.ts.map +1 -1
  27. package/dist/DropdownMenu/DropdownMenuItem.d.ts.map +1 -1
  28. package/dist/DropdownMenu/DropdownMenuItem.js +1 -1
  29. package/dist/DropdownMenu/DropdownMenuSubMenu.d.ts +6 -2
  30. package/dist/DropdownMenu/DropdownMenuSubMenu.d.ts.map +1 -1
  31. package/dist/DropdownMenu/DropdownMenuSubMenu.js +43 -14
  32. package/dist/DropdownMenu/MenuBottomSheet.d.ts +20 -0
  33. package/dist/DropdownMenu/MenuBottomSheet.d.ts.map +1 -0
  34. package/dist/DropdownMenu/MenuBottomSheet.js +36 -0
  35. package/dist/DropdownMenu/MenuBottomSheetActionList.d.ts +10 -0
  36. package/dist/DropdownMenu/MenuBottomSheetActionList.d.ts.map +1 -0
  37. package/dist/DropdownMenu/MenuBottomSheetActionList.js +111 -0
  38. package/dist/DropdownMenu/index.d.ts +2 -1
  39. package/dist/DropdownMenu/index.d.ts.map +1 -1
  40. package/dist/DropdownMenu/menuWidth.d.ts +14 -0
  41. package/dist/DropdownMenu/menuWidth.d.ts.map +1 -0
  42. package/dist/DropdownMenu/menuWidth.js +35 -0
  43. package/dist/DropdownMenu/useMenuOverflow.d.ts +10 -0
  44. package/dist/DropdownMenu/useMenuOverflow.d.ts.map +1 -0
  45. package/dist/DropdownMenu/useMenuOverflow.js +60 -0
  46. package/dist/MoreMenu/MoreMenu.d.ts +8 -2
  47. package/dist/MoreMenu/MoreMenu.d.ts.map +1 -1
  48. package/dist/MoreMenu/MoreMenu.js +2 -0
  49. package/dist/MultiSelector/MultiSelector.d.ts +11 -1
  50. package/dist/MultiSelector/MultiSelector.d.ts.map +1 -1
  51. package/dist/MultiSelector/MultiSelector.js +97 -68
  52. package/dist/MultiSelector/index.d.ts +1 -1
  53. package/dist/MultiSelector/index.d.ts.map +1 -1
  54. package/dist/Popover/Popover.d.ts +10 -6
  55. package/dist/Popover/Popover.d.ts.map +1 -1
  56. package/dist/Popover/Popover.js +141 -16
  57. package/dist/Popover/usePopover.d.ts +4 -0
  58. package/dist/Popover/usePopover.d.ts.map +1 -1
  59. package/dist/Popover/usePopover.js +52 -5
  60. package/dist/Selector/Selector.d.ts +10 -0
  61. package/dist/Selector/Selector.d.ts.map +1 -1
  62. package/dist/Selector/Selector.js +106 -80
  63. package/dist/Selector/SelectorBottomSheet.d.ts +21 -0
  64. package/dist/Selector/SelectorBottomSheet.d.ts.map +1 -0
  65. package/dist/Selector/SelectorBottomSheet.js +83 -0
  66. package/dist/Selector/index.d.ts +1 -1
  67. package/dist/Selector/index.d.ts.map +1 -1
  68. package/dist/Selector/selectorPresentation.stylex.d.ts +16 -0
  69. package/dist/Selector/selectorPresentation.stylex.d.ts.map +1 -0
  70. package/dist/Selector/selectorPresentation.stylex.js +21 -0
  71. package/dist/Selector/useSelectorPresentation.d.ts +32 -0
  72. package/dist/Selector/useSelectorPresentation.d.ts.map +1 -0
  73. package/dist/Selector/useSelectorPresentation.js +90 -0
  74. package/dist/Toast/useToastGesture.d.ts.map +1 -1
  75. package/dist/Toast/useToastGesture.js +46 -9
  76. package/dist/astryx.css +19 -1
  77. package/dist/hooks/useAdaptivePresentation.d.ts +5 -0
  78. package/dist/hooks/useAdaptivePresentation.d.ts.map +1 -0
  79. package/dist/hooks/useAdaptivePresentation.js +19 -0
  80. package/dist/hooks/useFocusReturnVisibility.d.ts +7 -0
  81. package/dist/hooks/useFocusReturnVisibility.d.ts.map +1 -0
  82. package/dist/hooks/useFocusReturnVisibility.js +35 -0
  83. package/dist/hooks/useFocusTrap.d.ts.map +1 -1
  84. package/dist/hooks/useFocusTrap.js +12 -0
  85. package/dist/i18n/InternationalizationContext.d.ts +2 -0
  86. package/dist/i18n/InternationalizationContext.d.ts.map +1 -1
  87. package/dist/i18n/InternationalizationContext.js +3 -1
  88. package/dist/i18n/InternationalizationProvider.d.ts.map +1 -1
  89. package/dist/i18n/InternationalizationProvider.js +3 -1
  90. package/dist/i18n/resolve.d.ts +1 -1
  91. package/dist/i18n/resolve.d.ts.map +1 -1
  92. package/dist/i18n/resolve.js +37 -38
  93. package/dist/i18n/useTranslator.d.ts.map +1 -1
  94. package/dist/i18n/useTranslator.js +2 -3
  95. package/locales/af-ZA.json +0 -4
  96. package/locales/ar-SA.json +0 -4
  97. package/locales/ca-ES.json +0 -4
  98. package/locales/cs-CZ.json +0 -4
  99. package/locales/da-DK.json +0 -4
  100. package/locales/de-DE.json +0 -4
  101. package/locales/el-GR.json +0 -4
  102. package/locales/en.json +20 -0
  103. package/locales/es-ES.json +0 -4
  104. package/locales/fi-FI.json +0 -4
  105. package/locales/fr-FR.json +0 -4
  106. package/locales/he-IL.json +0 -4
  107. package/locales/hu-HU.json +0 -4
  108. package/locales/it-IT.json +0 -4
  109. package/locales/ja-JP.json +0 -4
  110. package/locales/ko-KR.json +0 -4
  111. package/locales/nl-NL.json +0 -4
  112. package/locales/no-NO.json +0 -4
  113. package/locales/pl-PL.json +0 -4
  114. package/locales/pseudo.json +15 -0
  115. package/locales/pt-BR.json +0 -4
  116. package/locales/pt-PT.json +0 -4
  117. package/locales/ro-RO.json +0 -4
  118. package/locales/ru-RU.json +0 -4
  119. package/locales/sr-SP.json +0 -4
  120. package/locales/sv-SE.json +0 -4
  121. package/locales/tr-TR.json +0 -4
  122. package/locales/uk-UA.json +0 -4
  123. package/locales/vi-VN.json +0 -4
  124. package/locales/zh-CN.json +0 -4
  125. package/locales/zh-TW.json +0 -4
  126. package/package.json +3 -3
  127. package/src/BottomSheet/BottomSheet.doc.mjs +37 -0
  128. package/src/BottomSheet/BottomSheet.spec.md +177 -0
  129. package/src/BottomSheet/BottomSheet.test.tsx +29 -0
  130. package/src/BottomSheet/BottomSheet.tsx +7 -4
  131. package/src/BottomSheet/BottomSheetEdgeTint.test.tsx +4 -6
  132. package/src/BottomSheet/BottomSheetEdgeTint.tsx +7 -10
  133. package/src/BottomSheet/BottomSheetSwitcher.tsx +1 -2
  134. package/src/Button/Button.doc.mjs +56 -0
  135. package/src/Button/Button.test.tsx +10 -0
  136. package/src/Button/Button.tsx +13 -5
  137. package/src/ButtonGroup/ButtonGroup.doc.mjs +47 -0
  138. package/src/Calendar/Calendar.doc.mjs +1 -1
  139. package/src/Carousel/Carousel.test.tsx +83 -0
  140. package/src/Carousel/Carousel.tsx +8 -2
  141. package/src/Chat/ChatToolCalls.test.tsx +44 -0
  142. package/src/Chat/ChatToolCalls.tsx +36 -15
  143. package/src/CheckboxInput/CheckboxInput.doc.mjs +1 -1
  144. package/src/CheckboxList/CheckboxList.doc.mjs +173 -32
  145. package/src/CheckboxList/CheckboxList.spec.md +214 -0
  146. package/src/CommandPalette/CommandPalette.doc.mjs +72 -0
  147. package/src/CommandPalette/CommandPalette.spec.md +223 -0
  148. package/src/ComplexSelector/ComplexSelector.doc.mjs +44 -2
  149. package/src/ComplexSelector/ComplexSelector.spec.md +189 -0
  150. package/src/ContextMenu/ContextMenu.doc.mjs +13 -1
  151. package/src/ContextMenu/ContextMenu.test.tsx +131 -1
  152. package/src/ContextMenu/ContextMenu.tsx +199 -32
  153. package/src/ContextMenu/index.ts +1 -0
  154. package/src/DateInput/DateInput.doc.mjs +1 -1
  155. package/src/DateRangeInput/DateRangeInput.doc.mjs +1 -1
  156. package/src/DateTimeInput/DateTimeInput.doc.mjs +1 -1
  157. package/src/Divider/Divider.doc.mjs +24 -0
  158. package/src/Divider/Divider.spec.md +150 -0
  159. package/src/DropdownMenu/DropdownMenu.doc.mjs +201 -40
  160. package/src/DropdownMenu/DropdownMenu.test.tsx +518 -7
  161. package/src/DropdownMenu/DropdownMenu.tsx +459 -28
  162. package/src/DropdownMenu/DropdownMenuContext.tsx +1 -1
  163. package/src/DropdownMenu/DropdownMenuItem.tsx +2 -0
  164. package/src/DropdownMenu/DropdownMenuSubMenu.doc.mjs +4 -2
  165. package/src/DropdownMenu/DropdownMenuSubMenu.test.tsx +124 -0
  166. package/src/DropdownMenu/DropdownMenuSubMenu.tsx +72 -17
  167. package/src/DropdownMenu/MenuBottomSheet.tsx +46 -0
  168. package/src/DropdownMenu/MenuBottomSheetActionList.tsx +141 -0
  169. package/src/DropdownMenu/index.ts +2 -0
  170. package/src/DropdownMenu/menuWidth.ts +51 -0
  171. package/src/DropdownMenu/useMenuOverflow.ts +77 -0
  172. package/src/Field/Field.doc.mjs +1 -1
  173. package/src/FieldStatus/FieldStatus.doc.mjs +22 -1
  174. package/src/FieldStatus/FieldStatus.spec.md +212 -0
  175. package/src/FileInput/FileInput.doc.mjs +1 -1
  176. package/src/Grid/Grid.doc.mjs +19 -0
  177. package/src/Grid/Grid.spec.md +161 -0
  178. package/src/Icon/Icon.doc.mjs +196 -48
  179. package/src/Icon/Icon.spec.md +191 -0
  180. package/src/IconButton/IconButton.doc.mjs +38 -0
  181. package/src/Indicator/Indicator.doc.mjs +1 -1
  182. package/src/InputGroup/InputGroup.doc.mjs +1 -1
  183. package/src/Kbd/Kbd.doc.mjs +18 -0
  184. package/src/Kbd/Kbd.spec.md +141 -0
  185. package/src/Layout/Layout.doc.mjs +32 -0
  186. package/src/Layout/Layout.spec.md +199 -0
  187. package/src/Lightbox/Lightbox.doc.mjs +149 -33
  188. package/src/Lightbox/Lightbox.spec.md +197 -0
  189. package/src/Markdown/Markdown.doc.mjs +60 -0
  190. package/src/Markdown/Markdown.spec.md +200 -0
  191. package/src/MobileNav/MobileNav.doc.mjs +140 -32
  192. package/src/MobileNav/MobileNav.spec.md +208 -0
  193. package/src/MoreMenu/MoreMenu.doc.mjs +17 -0
  194. package/src/MoreMenu/MoreMenu.test.tsx +47 -0
  195. package/src/MoreMenu/MoreMenu.tsx +13 -1
  196. package/src/MultiSelector/MultiSelector.doc.mjs +129 -1
  197. package/src/MultiSelector/MultiSelector.spec.md +266 -0
  198. package/src/MultiSelector/MultiSelector.test.tsx +127 -0
  199. package/src/MultiSelector/MultiSelector.tsx +121 -73
  200. package/src/MultiSelector/index.ts +1 -0
  201. package/src/NavIcon/NavIcon.doc.mjs +17 -0
  202. package/src/NavIcon/NavIcon.spec.md +133 -0
  203. package/src/NavMenu/NavHeadingMenu.spec.md +205 -0
  204. package/src/NavMenu/NavMenu.doc.mjs +37 -0
  205. package/src/NumberInput/NumberInput.doc.mjs +1 -1
  206. package/src/Outline/Outline.doc.mjs +35 -0
  207. package/src/Outline/Outline.spec.md +161 -0
  208. package/src/OverflowList/OverflowList.doc.mjs +24 -0
  209. package/src/OverflowList/OverflowList.spec.md +156 -0
  210. package/src/Pagination/Pagination.doc.mjs +74 -0
  211. package/src/Pagination/Pagination.spec.md +225 -0
  212. package/src/Popover/Popover.doc.mjs +11 -11
  213. package/src/Popover/Popover.test.tsx +397 -2
  214. package/src/Popover/Popover.tsx +228 -21
  215. package/src/Popover/usePopover.tsx +92 -15
  216. package/src/PowerSearch/PowerSearch.doc.mjs +1 -1
  217. package/src/ProgressBar/ProgressBar.doc.mjs +198 -38
  218. package/src/ProgressBar/ProgressBar.spec.md +260 -0
  219. package/src/RadioList/RadioList.doc.mjs +1 -1
  220. package/src/Resizable/Resizable.doc.mjs +59 -16
  221. package/src/Resizable/Resizable.spec.md +194 -0
  222. package/src/Section/Section.doc.mjs +17 -0
  223. package/src/Section/Section.spec.md +138 -0
  224. package/src/SegmentedControl/SegmentedControl.doc.mjs +83 -0
  225. package/src/SegmentedControl/SegmentedControl.spec.md +151 -0
  226. package/src/Selector/Selector.doc.mjs +13 -1
  227. package/src/Selector/Selector.test.tsx +135 -0
  228. package/src/Selector/Selector.tsx +141 -82
  229. package/src/Selector/SelectorBottomSheet.tsx +97 -0
  230. package/src/Selector/index.ts +1 -0
  231. package/src/Selector/selectorPresentation.stylex.ts +20 -0
  232. package/src/Selector/useSelectorPresentation.ts +147 -0
  233. package/src/Skeleton/Skeleton.doc.mjs +12 -0
  234. package/src/Skeleton/Skeleton.spec.md +126 -0
  235. package/src/Slider/Slider.doc.mjs +186 -32
  236. package/src/Slider/Slider.spec.md +223 -0
  237. package/src/Stack/Stack.doc.mjs +22 -0
  238. package/src/Stack/Stack.spec.md +154 -0
  239. package/src/StatusDot/StatusDot.doc.mjs +17 -0
  240. package/src/StatusDot/StatusDot.spec.md +137 -0
  241. package/src/Switch/Switch.doc.mjs +41 -1
  242. package/src/Switch/Switch.spec.md +174 -0
  243. package/src/Text/Text.doc.mjs +190 -43
  244. package/src/Text/Text.spec.md +205 -0
  245. package/src/TextArea/TextArea.doc.mjs +256 -46
  246. package/src/TextArea/TextArea.spec.md +204 -0
  247. package/src/TextInput/TextInput.doc.mjs +1 -1
  248. package/src/TimeInput/TimeInput.doc.mjs +1 -1
  249. package/src/Toast/ToastViewport.test.tsx +118 -4
  250. package/src/Toast/useToastGesture.ts +61 -8
  251. package/src/ToggleButton/ToggleButton.doc.mjs +56 -0
  252. package/src/Tokenizer/Tokenizer.doc.mjs +1 -1
  253. package/src/Toolbar/Toolbar.doc.mjs +19 -0
  254. package/src/Toolbar/Toolbar.spec.md +173 -0
  255. package/src/Tooltip/Tooltip.doc.mjs +17 -0
  256. package/src/Tooltip/Tooltip.spec.md +141 -0
  257. package/src/TreeList/TreeList.doc.mjs +58 -0
  258. package/src/TreeList/TreeList.spec.md +220 -0
  259. package/src/Typeahead/Typeahead.doc.mjs +84 -2
  260. package/src/Typeahead/Typeahead.spec.md +250 -0
  261. package/src/hooks/useAdaptivePresentation.ts +35 -0
  262. package/src/hooks/useFocusReturnVisibility.ts +45 -0
  263. package/src/hooks/useFocusTrap.test.tsx +40 -0
  264. package/src/hooks/useFocusTrap.ts +13 -0
  265. package/src/i18n/InternationalizationContext.ts +3 -0
  266. package/src/i18n/InternationalizationProvider.tsx +8 -1
  267. package/src/i18n/__tests__/resolve.test.ts +23 -1
  268. package/src/i18n/resolve.ts +46 -49
  269. package/src/i18n/useTranslator.ts +2 -7
  270. package/src/theme/themingTargets.test.ts +91 -25
@@ -0,0 +1,205 @@
1
+ ---
2
+ schema_version: 1
3
+ template_version: 3
4
+ kind: component
5
+ id: component:Text
6
+ authority: draft
7
+ archive_reason: null
8
+ superseded_by: null
9
+ approved_by: null
10
+ approved_at: null
11
+ owners: [cixzhang]
12
+ review_triggers: [theming]
13
+ verified_by:
14
+ [
15
+ packages/core/src/Text/Text.test.tsx,
16
+ packages/core/src/Heading/Heading.test.tsx,
17
+ packages/core/src/theme/themingTargets.test.ts,
18
+ scripts/check-knowledge.mjs,
19
+ ]
20
+ families: []
21
+ design_specs: []
22
+ architecture: [architecture:component-theming-surface]
23
+ contributing: []
24
+ system_specs: []
25
+ ---
26
+
27
+ # Text component contract
28
+
29
+ ## Intent
30
+
31
+ Text renders themed body text through the Text component and semantic headings
32
+ through its referenced Heading member. This draft records their current consumer
33
+ anatomy, the two live root targets owned by the canonical Text documentation, and
34
+ the conditional Tooltip delegation used for truncated content. It does not
35
+ change runtime behavior, styling, targets, or public API.
36
+
37
+ ## Compatibility and migration
38
+
39
+ - Released default preserved: `yes`
40
+ - Compatibility class: additive documentation only; runtime, DOM, styling,
41
+ targets, and public API remain unchanged
42
+ - Controlled/uncontrolled behavior: not applicable
43
+ - Migration decision: none
44
+
45
+ Consumer migration instructions belong in consumer docs and release notes.
46
+
47
+ ## Ownership boundary
48
+
49
+ **Owns**
50
+
51
+ - The polymorphic Text element and its current `text` theming target.
52
+ - The referenced Heading member's semantic heading element and its current
53
+ `heading` theming target.
54
+ - Deciding from the current truncation state whether to compose Tooltip against
55
+ the Text or Heading element.
56
+
57
+ **Does not own / non-goals**
58
+
59
+ - The truncation tooltip surface, layer behavior, or `tooltip` target — owned by
60
+ Tooltip when that composed surface renders.
61
+ - Content supplied as Text or Heading children — owned by the caller.
62
+ - A separate Heading component contract; Heading remains a referenced member of
63
+ the canonical Text documentation and target inventory.
64
+ - New typography behavior, truncation behavior, semantics, styling, targets,
65
+ public API, or target aliases.
66
+
67
+ ## Public concepts
68
+
69
+ No new public concept is introduced. Text and Heading props, defaults, and usage
70
+ remain documented in `Text.doc.mjs` and `Heading.doc.mjs`.
71
+
72
+ ## Behavioral and layout contract
73
+
74
+ | ID | Candidate invariant | Basis | Draft review state |
75
+ | --- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------- | ----------------------------------------------------- |
76
+ | FR1 | Text renders one polymorphic text element carrying the current `text` target. | Current source, docs, and tests | Verified current behavior; no new behavior decided |
77
+ | FR2 | Heading renders one semantic `h1`–`h6` element carrying the current `heading` target. Heading is a referenced member of Text rather than a nested Text element. | Current source, docs, tests, and target history | Verified current behavior and canonical ownership |
78
+ | FR3 | Text or Heading composes Tooltip only when `maxLines` is positive, truncation tooltips are enabled, and measurement reports that the rendered content is truncated. Otherwise the truncation Tooltip path does not render. | Current source, tests, and truncation history | Verified current conditional behavior |
79
+ | FR4 | When the conditional truncation path renders, Tooltip owns the layer surface and applies the `tooltip` target. Text and Heading retain their own root targets and do not apply or claim Tooltip's target. | Current source and owner target metadata | Verified current ownership; no target change |
80
+ | FR5 | Text reflects `type`, `size`, and resolved `color` on `text`; Heading reflects `level`, `color`, and an explicitly supplied `type` on `heading`. Display mode, truncation state, semantic element choice, and Tooltip open state do not become separate anatomy parts or Text-owned targets. | Current source, docs, tests, and target inventory | Verified current capabilities; no new anatomy decided |
81
+
82
+ ### Observed current behavior
83
+
84
+ These observations describe the implementation; they do not establish new
85
+ intent:
86
+
87
+ - Text defaults to a `span` and may render another supported text element through
88
+ `as`. Heading maps `level` directly to `h1` through `h6`.
89
+ - Both members render caller content directly inside their targeted root element;
90
+ neither creates a separately targeted content wrapper.
91
+ - Both members measure truncation only when `maxLines` is positive. When the
92
+ measurement reports overflow and `hasTruncateTooltip` is not `false`, they
93
+ lazy-load Tooltip in sibling-anchor mode.
94
+ - Tooltip owns its layer lifecycle and applies `tooltip` only to its own rendered
95
+ layer. The truncated Text or Heading element remains the anchor and keeps only
96
+ its own target.
97
+ - Text and Heading no longer add a native `title` for this path; the composed
98
+ Tooltip is the single tooltip presentation.
99
+
100
+ ### Allowed variation
101
+
102
+ - **AV1 — Text element and content.** Text may use any currently supported `as`
103
+ element and either member may contain caller-supplied content without changing
104
+ target ownership.
105
+ - **AV2 — Typography.** Level, type, size, color, weight, wrapping, decoration,
106
+ and theme or consumer styling may vary through the existing APIs and targets.
107
+ - **AV3 — Conditional tooltip.** Fitting content, disabled truncation tooltips,
108
+ and non-truncating configurations omit the delegated Tooltip path.
109
+
110
+ ### Representative states
111
+
112
+ | State | Required invariant | Allowed variation |
113
+ | ----------------------------------------- | ------------------------------------------------------------------------------------------ | ------------------------------------------------- |
114
+ | Text without truncation | One Text element carries `text`; no truncation Tooltip path renders. | Supported element, content, and typography props. |
115
+ | Heading without truncation | One semantic heading carries `heading`; no Text target or truncation Tooltip path renders. | Heading level, accessibility level, and type. |
116
+ | Truncation configured but content fits | The owning Text or Heading root remains; no truncation Tooltip path renders. | Line limit and available width. |
117
+ | Truncated with tooltip disabled | The owning root remains clipped; no truncation Tooltip path renders. | Text or Heading owner. |
118
+ | Truncated with tooltip enabled and opened | The owning root anchors one Tooltip-owned surface carrying `tooltip`. | Placement and full text content. |
119
+
120
+ ### Transformation and precedence order
121
+
122
+ - No new typography, truncation, element-selection, or styling precedence rule is
123
+ introduced.
124
+
125
+ ### Performance and resources
126
+
127
+ - This draft records the current shared ResizeObserver-based truncation path and
128
+ lazy Tooltip composition but introduces no new measurement, observer, render,
129
+ or loading requirement.
130
+
131
+ ## Accessibility contract
132
+
133
+ This draft does not change or extend Text's polymorphic semantics, Heading's
134
+ native heading level and optional `aria-level`, or Tooltip's existing
135
+ `aria-describedby` ownership for truncated content.
136
+
137
+ ## Design relationships
138
+
139
+ | Anatomy or state | Design requirement | Representation authority | Hierarchy role | Component contract |
140
+ | ------------------ | --------------------------------------------------------------------------------- | ------------------------------ | -------------- | ------------------ |
141
+ | Text | Presents caller content in the current polymorphic text element. | Current source and public docs | Prominent | FR1, FR5 |
142
+ | Heading | Presents caller content in the referenced semantic Heading member. | Current source and public docs | Prominent | FR2, FR5 |
143
+ | Truncation tooltip | Presents the full content only on the current measured-overflow and enabled path. | `component:Tooltip` | Supporting | FR3, FR4 |
144
+
145
+ Text and Heading are sibling public components represented by the canonical Text
146
+ documentation; Heading is not nested inside Text. The Tooltip row is conditional
147
+ composition rather than a Text- or Heading-owned surface.
148
+
149
+ ### Theming anatomy
150
+
151
+ <!-- anatomy-theming:v1 -->
152
+
153
+ ```json
154
+ {
155
+ "Text": {"target": "text"},
156
+ "Heading": {"target": "heading"},
157
+ "Truncation tooltip": {
158
+ "delegatesTo": {"owner": "component:Tooltip", "target": "tooltip"}
159
+ }
160
+ }
161
+ ```
162
+
163
+ The two local targets are the exact current targets declared by the canonical
164
+ Text doc. The delegated `tooltip` target applies only when the conditional
165
+ truncation path reaches Tooltip and Tooltip renders its layer; it is not a
166
+ Text- or Heading-owned target. No anatomy part requires a `none` disposition.
167
+
168
+ ## Family and system relationships
169
+
170
+ - `architecture:component-theming-surface` owns anatomy qualification, aggregate
171
+ parent/member target ownership, exact target mapping, and delegation.
172
+ - Text is the canonical documentation and contract owner for both `text` and
173
+ `heading`; Heading remains a referenced member and does not receive a separate
174
+ component spec.
175
+ - Tooltip retains ownership of its delegated surface, interaction behavior, and
176
+ `tooltip` target.
177
+
178
+ ## Verification map
179
+
180
+ | Contract | Verification | Representative states | Mutation or failure expectation | Audit section |
181
+ | ------------------- | ---------------------------------------------------------------------------------------------- | ------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------- | ----------------------- |
182
+ | FR1, FR5 | `Text.test.tsx` and `themingTargets.test.ts` | Default, polymorphic, custom type/color, explicit size | Removing, renaming, or changing the current Text target capabilities fails focused or global target assertions. | `audit:Text/theming` |
183
+ | FR2, FR5 | `Heading.test.tsx`, `themingTargets.test.ts`, and target-introduction history | Levels 1–6, display type, custom color | Removing, renaming, or changing the current Heading target capabilities fails focused or global assertions. | `audit:Heading/theming` |
184
+ | FR3, FR4 | Text and Heading source inspection, truncation tests, Tooltip target metadata, and fix history | Fitting, overflowing, disabled, enabled | Moving the surface or target into Text/Heading, or restoring a native duplicate tooltip, violates current evidence. | `audit:Text/anatomy` |
185
+ | Theming anatomy map | `scripts/check-knowledge.mjs` | Canonical anatomy, both local targets, Tooltip delegate | Missing, extra, prefixed, stale, multiply assigned, or invalid delegated mappings fail repository validation. | `audit:Text/theming` |
186
+
187
+ Current focused tests pin both local target names and Text's lack of a duplicate
188
+ native `title`. The conditional Tooltip path and Heading's matching no-`title`
189
+ behavior are established by shared source shape and history rather than a
190
+ separate focused assertion in each suite.
191
+
192
+ ## Decision log
193
+
194
+ None. This draft records current facts and introduces no component-local design,
195
+ API, behavior, accessibility, or theming decision.
196
+
197
+ ## Open questions
198
+
199
+ None.
200
+
201
+ ## Content boundary
202
+
203
+ This file does not duplicate consumer prop tables/examples, typography token
204
+ values, truncation measurement mechanics, Tooltip internals, implementation
205
+ steps, current audit results, or system theming rules. It links to their owners.
@@ -1,18 +1,95 @@
1
1
  // Copyright (c) Meta Platforms, Inc. and affiliates.
2
2
 
3
+ /** @type {import('@astryxdesign/cli/authoring').ComponentAnatomyElement[]} */
4
+ const anatomy = [
5
+ {
6
+ name: 'Label',
7
+ required: true,
8
+ description: 'Text identifying the multi-line field.',
9
+ },
10
+ {
11
+ name: 'Description',
12
+ required: false,
13
+ description: 'Helper text between the label and the input.',
14
+ },
15
+ {
16
+ name: 'Input container',
17
+ required: true,
18
+ description: 'Painted boundary containing the text area and its overlays.',
19
+ },
20
+ {
21
+ name: 'Text area',
22
+ required: true,
23
+ description: 'Multi-line control that displays and edits the value.',
24
+ },
25
+ {
26
+ name: 'Placeholder',
27
+ required: false,
28
+ description: 'Hint text shown inside the empty text area.',
29
+ },
30
+ {
31
+ name: 'Start icon',
32
+ required: false,
33
+ description:
34
+ 'Astryx Icon rendered at the start when startIcon is a semantic name or icon component.',
35
+ },
36
+ {
37
+ name: 'Custom start content',
38
+ required: false,
39
+ description:
40
+ 'Caller-provided ReactNode rendered at the start instead of an Astryx Icon.',
41
+ },
42
+ {
43
+ name: 'Spinner',
44
+ required: false,
45
+ description: 'Loading indicator shown at the end of the input container.',
46
+ },
47
+ {
48
+ name: 'Status icon',
49
+ required: false,
50
+ description: 'Error, warning, or success icon shown inside the input.',
51
+ },
52
+ {
53
+ name: 'Character counter',
54
+ required: false,
55
+ description:
56
+ 'Current and maximum character counts shown inside the input container.',
57
+ },
58
+ {
59
+ name: 'Field status message',
60
+ required: false,
61
+ description:
62
+ 'Attached or detached error, warning, or success message associated with the field.',
63
+ },
64
+ {
65
+ name: 'Tooltip status message',
66
+ required: false,
67
+ description:
68
+ 'Tooltip surface presenting the status message for the tooltip variant.',
69
+ },
70
+ ];
71
+
3
72
  /** @type {import('@astryxdesign/cli/authoring').ComponentDoc} */
4
73
 
5
74
  export const docs = {
6
75
  name: 'TextArea',
7
76
  displayName: 'Text Area',
8
- category: 'Data Input',
9
- keywords: ["textarea","textfield","multiline","comment","message","autoresize","autosize","charlimit"],
77
+ category: 'Form Controls',
78
+ keywords: [
79
+ 'textarea',
80
+ 'textfield',
81
+ 'multiline',
82
+ 'comment',
83
+ 'message',
84
+ 'autoresize',
85
+ 'autosize',
86
+ 'charlimit',
87
+ ],
10
88
  props: [
11
89
  {
12
90
  name: 'ref',
13
91
  type: 'React.Ref<HTMLTextAreaElement>',
14
- description:
15
- 'Ref forwarded to the underlying <textarea> element.',
92
+ description: 'Ref forwarded to the underlying <textarea> element.',
16
93
  },
17
94
  {
18
95
  name: 'label',
@@ -147,7 +224,8 @@ export const docs = {
147
224
  {
148
225
  name: 'size',
149
226
  type: "'sm' | 'md' | 'lg'",
150
- description: 'Size of the textarea, affecting internal padding. Height is controlled by rows, not size.',
227
+ description:
228
+ 'Size of the textarea, affecting internal padding. Height is controlled by rows, not size.',
151
229
  default: "'md'",
152
230
  },
153
231
  {
@@ -186,12 +264,21 @@ export const docs = {
186
264
  ],
187
265
  theming: {
188
266
  targets: [
189
- {className: 'astryx-text-area', visualProps: ['size', 'status'], states: ['disabled', 'readonly']},
267
+ {
268
+ className: 'astryx-text-area',
269
+ visualProps: ['size', 'status'],
270
+ states: ['disabled', 'readonly'],
271
+ },
190
272
  {className: 'astryx-text-area-control'},
191
273
  {className: 'astryx-text-area-counter'},
192
274
  // Still emitted beside the names above, so themes written against
193
275
  // them keep working. Drop in the next major.
194
- {className: 'astryx-textarea', visualProps: ['size', 'status'], states: ['disabled', 'readonly'], deprecatedFor: 'text-area'},
276
+ {
277
+ className: 'astryx-textarea',
278
+ visualProps: ['size', 'status'],
279
+ states: ['disabled', 'readonly'],
280
+ deprecatedFor: 'text-area',
281
+ },
195
282
  ],
196
283
  vars: [
197
284
  {
@@ -203,21 +290,58 @@ export const docs = {
203
290
  },
204
291
  ],
205
292
  derived: [
206
- {property: 'paddingInline', vars: ['--_textarea-inline-padding'], replaces: true},
293
+ {
294
+ property: 'paddingInline',
295
+ vars: ['--_textarea-inline-padding'],
296
+ replaces: true,
297
+ },
207
298
  ],
208
299
  },
209
300
  usage: {
301
+ anatomy,
210
302
  description:
211
303
  'TextArea is a multi-line text input for collecting longer-form content like comments, descriptions, or messages. Use it when the expected input spans multiple lines. For shorter, single-line values, use TextInput.',
212
304
  bestPractices: [
213
- { guidance: true, description: 'Provide a visible label so users know what to enter. If the label must be hidden, set isLabelHidden with a descriptive label for screen readers.' },
214
- { guidance: true, description: 'Set maxLength with a character counter when there is a defined limit; it helps users stay within bounds before they submit.' },
215
- { guidance: true, description: 'Use the status prop to surface validation feedback inline: show success when input is valid, warning for soft limits, and error for hard failures.' },
216
- { guidance: true, description: 'Add a description or placeholder to clarify expected content, like "Describe the issue in detail," but never rely on placeholder alone as the only label.' },
217
- { guidance: false, description: 'Avoid using TextArea for short, single-line values like names or emails; use TextInput instead.' },
218
- { guidance: false, description: 'Don\'t rely solely on placeholder text to communicate the purpose of the field; placeholders disappear on focus and are not accessible labels.' },
219
- { guidance: false, description: 'Don\'t show a status message without also setting the status type; the colored border and icon are what draw the user\'s attention to the message.' },
220
- { guidance: false, description: 'Don\'t wrap a disabled TextArea in Tooltip to explain why it\'s disabled; disabled controls swallow the hover events the wrapper needs. Use the disabledMessage prop instead.' },
305
+ {
306
+ guidance: true,
307
+ description:
308
+ 'Provide a visible label so users know what to enter. If the label must be hidden, set isLabelHidden with a descriptive label for screen readers.',
309
+ },
310
+ {
311
+ guidance: true,
312
+ description:
313
+ 'Set maxLength with a character counter when there is a defined limit; it helps users stay within bounds before they submit.',
314
+ },
315
+ {
316
+ guidance: true,
317
+ description:
318
+ 'Use the status prop to surface validation feedback inline: show success when input is valid, warning for soft limits, and error for hard failures.',
319
+ },
320
+ {
321
+ guidance: true,
322
+ description:
323
+ 'Add a description or placeholder to clarify expected content, like "Describe the issue in detail," but never rely on placeholder alone as the only label.',
324
+ },
325
+ {
326
+ guidance: false,
327
+ description:
328
+ 'Avoid using TextArea for short, single-line values like names or emails; use TextInput instead.',
329
+ },
330
+ {
331
+ guidance: false,
332
+ description:
333
+ "Don't rely solely on placeholder text to communicate the purpose of the field; placeholders disappear on focus and are not accessible labels.",
334
+ },
335
+ {
336
+ guidance: false,
337
+ description:
338
+ "Don't show a status message without also setting the status type; the colored border and icon are what draw the user's attention to the message.",
339
+ },
340
+ {
341
+ guidance: false,
342
+ description:
343
+ "Don't wrap a disabled TextArea in Tooltip to explain why it's disabled; disabled controls swallow the hover events the wrapper needs. Use the disabledMessage prop instead.",
344
+ },
221
345
  ],
222
346
  },
223
347
  };
@@ -252,7 +376,8 @@ export const docsZh = {
252
376
  {
253
377
  name: 'changeAction',
254
378
  type: '(value: string, e: ChangeEvent<HTMLTextAreaElement>) => void | Promise<void>',
255
- description: '在 React transition 内于 onChange 之后触发的异步操作。通过 useOptimistic 启用乐观更新。',
379
+ description:
380
+ '在 React transition 内于 onChange 之后触发的异步操作。通过 useOptimistic 启用乐观更新。',
256
381
  },
257
382
  {
258
383
  name: 'isLabelHidden',
@@ -274,7 +399,8 @@ export const docsZh = {
274
399
  {
275
400
  name: 'isRequired',
276
401
  type: 'boolean',
277
- description: '在标签旁显示"必填"指示器并设置 aria-required。与 isOptional 互斥。',
402
+ description:
403
+ '在标签旁显示"必填"指示器并设置 aria-required。与 isOptional 互斥。',
278
404
  default: 'false',
279
405
  },
280
406
  {
@@ -316,12 +442,14 @@ export const docsZh = {
316
442
  {
317
443
  name: 'maxLength',
318
444
  type: 'number',
319
- description: '允许的最大字符数。设置后,在文本域下方显示字符计数器(当前/最大)。不原生强制限制:超出时计数器显示错误样式。',
445
+ description:
446
+ '允许的最大字符数。设置后,在文本域下方显示字符计数器(当前/最大)。不原生强制限制:超出时计数器显示错误样式。',
320
447
  },
321
448
  {
322
449
  name: 'status',
323
450
  type: "{ type: 'warning' | 'error' | 'success'; message?: string }",
324
- description: '应用彩色边框和图标的状态指示器。可选消息显示在文本域下方的浮动框中。',
451
+ description:
452
+ '应用彩色边框和图标的状态指示器。可选消息显示在文本域下方的浮动框中。',
325
453
  },
326
454
  {
327
455
  name: 'statusVariant',
@@ -381,17 +509,27 @@ export const docsZh = {
381
509
  {
382
510
  name: 'xstyle',
383
511
  type: 'StyleXStyles',
384
- description: 'StyleX 样式,用于布局自定义(边距、定位、尺寸)。必须是 stylex.create() 的值,而非内联样式对象。',
512
+ description:
513
+ 'StyleX 样式,用于布局自定义(边距、定位、尺寸)。必须是 stylex.create() 的值,而非内联样式对象。',
385
514
  },
386
515
  ],
387
516
  theming: {
388
517
  targets: [
389
- {className: 'astryx-text-area', visualProps: ['size', 'status'], states: ['disabled', 'readonly']},
518
+ {
519
+ className: 'astryx-text-area',
520
+ visualProps: ['size', 'status'],
521
+ states: ['disabled', 'readonly'],
522
+ },
390
523
  {className: 'astryx-text-area-control'},
391
524
  {className: 'astryx-text-area-counter'},
392
525
  // Still emitted beside the names above, so themes written against
393
526
  // them keep working. Drop in the next major.
394
- {className: 'astryx-textarea', visualProps: ['size', 'status'], states: ['disabled', 'readonly'], deprecatedFor: 'text-area'},
527
+ {
528
+ className: 'astryx-textarea',
529
+ visualProps: ['size', 'status'],
530
+ states: ['disabled', 'readonly'],
531
+ deprecatedFor: 'text-area',
532
+ },
395
533
  ],
396
534
  vars: [
397
535
  {
@@ -403,21 +541,57 @@ export const docsZh = {
403
541
  },
404
542
  ],
405
543
  derived: [
406
- {property: 'paddingInline', vars: ['--_textarea-inline-padding'], replaces: true},
544
+ {
545
+ property: 'paddingInline',
546
+ vars: ['--_textarea-inline-padding'],
547
+ replaces: true,
548
+ },
407
549
  ],
408
550
  },
409
551
  usage: {
410
552
  description:
411
553
  'TextArea is a multi-line text input for collecting longer-form content like comments, descriptions, or messages. Use it when the expected input spans multiple lines. For shorter, single-line values, use TextInput.',
412
554
  bestPractices: [
413
- { guidance: true, description: 'Provide a visible label so users know what to enter. If the label must be hidden, set isLabelHidden with a descriptive label for screen readers.' },
414
- { guidance: true, description: 'Set maxLength with a character counter when there is a defined limit; it helps users stay within bounds before they submit.' },
415
- { guidance: true, description: 'Use the status prop to surface validation feedback inline: show success when input is valid, warning for soft limits, and error for hard failures.' },
416
- { guidance: true, description: 'Add a description or placeholder to clarify expected content, like "Describe the issue in detail," but never rely on placeholder alone as the only label.' },
417
- { guidance: false, description: 'Avoid using TextArea for short, single-line values like names or emails; use TextInput instead.' },
418
- { guidance: false, description: 'Don\'t rely solely on placeholder text to communicate the purpose of the field; placeholders disappear on focus and are not accessible labels.' },
419
- { guidance: false, description: 'Don\'t show a status message without also setting the status type; the colored border and icon are what draw the user\'s attention to the message.' },
420
- { guidance: false, description: 'Don\'t wrap a disabled TextArea in Tooltip to explain why it\'s disabled; disabled controls swallow the hover events the wrapper needs. Use the disabledMessage prop instead.' },
555
+ {
556
+ guidance: true,
557
+ description:
558
+ 'Provide a visible label so users know what to enter. If the label must be hidden, set isLabelHidden with a descriptive label for screen readers.',
559
+ },
560
+ {
561
+ guidance: true,
562
+ description:
563
+ 'Set maxLength with a character counter when there is a defined limit; it helps users stay within bounds before they submit.',
564
+ },
565
+ {
566
+ guidance: true,
567
+ description:
568
+ 'Use the status prop to surface validation feedback inline: show success when input is valid, warning for soft limits, and error for hard failures.',
569
+ },
570
+ {
571
+ guidance: true,
572
+ description:
573
+ 'Add a description or placeholder to clarify expected content, like "Describe the issue in detail," but never rely on placeholder alone as the only label.',
574
+ },
575
+ {
576
+ guidance: false,
577
+ description:
578
+ 'Avoid using TextArea for short, single-line values like names or emails; use TextInput instead.',
579
+ },
580
+ {
581
+ guidance: false,
582
+ description:
583
+ "Don't rely solely on placeholder text to communicate the purpose of the field; placeholders disappear on focus and are not accessible labels.",
584
+ },
585
+ {
586
+ guidance: false,
587
+ description:
588
+ "Don't show a status message without also setting the status type; the colored border and icon are what draw the user's attention to the message.",
589
+ },
590
+ {
591
+ guidance: false,
592
+ description:
593
+ "Don't wrap a disabled TextArea in Tooltip to explain why it's disabled; disabled controls swallow the hover events the wrapper needs. Use the disabledMessage prop instead.",
594
+ },
421
595
  ],
422
596
  },
423
597
  };
@@ -429,14 +603,44 @@ export const docsDense = {
429
603
  description:
430
604
  'Multi-line input for comments, descriptions, messages. Use when input spans multiple lines; use TextInput for single-line.',
431
605
  bestPractices: [
432
- { guidance: true, description: 'Visible label or isLabelHidden with descriptive label for screen readers.' },
433
- { guidance: true, description: 'Set maxLength for character counter when a limit exists.' },
434
- { guidance: true, description: 'Use status prop for inline validation: success, warning, error.' },
435
- { guidance: true, description: 'Add description or placeholder for context; never placeholder alone as label.' },
436
- { guidance: false, description: 'Avoid TextArea for single-line values; use TextInput.' },
437
- { guidance: false, description: 'Don\'t use placeholder as only label; disappears on focus, not accessible.' },
438
- { guidance: false, description: 'Don\'t show status message without status type; border and icon draw attention.' },
439
- { guidance: false, description: 'Don\'t wrap a disabled TextArea in Tooltip to explain the disabled state; use the disabledMessage prop instead.' },
606
+ {
607
+ guidance: true,
608
+ description:
609
+ 'Visible label or isLabelHidden with descriptive label for screen readers.',
610
+ },
611
+ {
612
+ guidance: true,
613
+ description: 'Set maxLength for character counter when a limit exists.',
614
+ },
615
+ {
616
+ guidance: true,
617
+ description:
618
+ 'Use status prop for inline validation: success, warning, error.',
619
+ },
620
+ {
621
+ guidance: true,
622
+ description:
623
+ 'Add description or placeholder for context; never placeholder alone as label.',
624
+ },
625
+ {
626
+ guidance: false,
627
+ description: 'Avoid TextArea for single-line values; use TextInput.',
628
+ },
629
+ {
630
+ guidance: false,
631
+ description:
632
+ "Don't use placeholder as only label; disappears on focus, not accessible.",
633
+ },
634
+ {
635
+ guidance: false,
636
+ description:
637
+ "Don't show status message without status type; border and icon draw attention.",
638
+ },
639
+ {
640
+ guidance: false,
641
+ description:
642
+ "Don't wrap a disabled TextArea in Tooltip to explain the disabled state; use the disabledMessage prop instead.",
643
+ },
440
644
  ],
441
645
  },
442
646
  propDescriptions: {
@@ -444,11 +648,13 @@ export const docsDense = {
444
648
  label: 'Label text for textarea; always rendered for a11y.',
445
649
  value: 'Current textarea value.',
446
650
  onChange: 'Fired on textarea value change.',
447
- changeAction: 'Async action after onChange in React transition. Enables useOptimistic.',
651
+ changeAction:
652
+ 'Async action after onChange in React transition. Enables useOptimistic.',
448
653
  isLabelHidden: 'Visually hides label; keeps screen reader access.',
449
654
  description: 'Helper text between label+textarea.',
450
655
  isOptional: 'Shows "Optional" indicator. Mutually exclusive w/ isRequired.',
451
- isRequired: 'Shows "Required" indicator+sets aria-required. Mutually exclusive w/ isOptional.',
656
+ isRequired:
657
+ 'Shows "Required" indicator+sets aria-required. Mutually exclusive w/ isOptional.',
452
658
  isDisabled: 'Disables textarea, prevents interaction.',
453
659
  isReadOnly:
454
660
  'Read-only: value visible + still submits, but not editable. Unlike isDisabled: not dimmed, stays in tab order.',
@@ -457,9 +663,12 @@ export const docsDense = {
457
663
  isLoading: 'Loading state w/ spinner inside input.',
458
664
  placeholder: 'Placeholder when textarea empty.',
459
665
  rows: 'Visible text rows.',
460
- maxLength: 'Max chars allowed. Shows counter (current/max) inside the container, bottom-right beneath the text. No native enforcement; over-limit shows red + a warning icon and is announced to screen readers.',
461
- status: 'Colored border+icon status. Optional floating message below textarea.',
462
- statusVariant: 'How status message is placed: attached overlaps below input; detached floats below w/ spacing; tooltip hides the box and shows it on the status icon.',
666
+ maxLength:
667
+ 'Max chars allowed. Shows counter (current/max) inside the container, bottom-right beneath the text. No native enforcement; over-limit shows red + a warning icon and is announced to screen readers.',
668
+ status:
669
+ 'Colored border+icon status. Optional floating message below textarea.',
670
+ statusVariant:
671
+ 'How status message is placed: attached overlaps below input; detached floats below w/ spacing; tooltip hides the box and shows it on the status icon.',
463
672
  labelTooltip: 'Tooltip in info icon at label end.',
464
673
  startIcon: 'Icon inside leading edge of textarea wrapper.',
465
674
  hasSpellCheck: 'Enables/disables browser spell checking.',
@@ -469,6 +678,7 @@ export const docsDense = {
469
678
  htmlName: 'HTML name attr for form submissions.',
470
679
  onFocus: 'Callback on focus.',
471
680
  onBlur: 'Callback on blur.',
472
- xstyle: 'StyleX styles for layout customization. Must be stylex.create() value, not inline style.',
681
+ xstyle:
682
+ 'StyleX styles for layout customization. Must be stylex.create() value, not inline style.',
473
683
  },
474
684
  };