@commercetools/nimbus-mcp 0.1.0 → 2.11.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (453) hide show
  1. package/README.md +63 -14
  2. package/data/docs/route-manifest.json +10998 -0
  3. package/data/docs/routes/components-accessibility-visually-hidden.json +388 -0
  4. package/data/docs/routes/components-accessibility.json +34 -0
  5. package/data/docs/routes/components-buttons-button.json +715 -0
  6. package/data/docs/routes/components-buttons-icon-button.json +852 -0
  7. package/data/docs/routes/components-buttons-icon-toggle-button.json +594 -0
  8. package/data/docs/routes/components-buttons-split-button.json +670 -0
  9. package/data/docs/routes/components-buttons-toggle-button-group.json +722 -0
  10. package/data/docs/routes/components-buttons-toggle-button.json +689 -0
  11. package/data/docs/routes/components-buttons.json +36 -0
  12. package/data/docs/routes/components-data-display-badge.json +555 -0
  13. package/data/docs/routes/components-data-display-card.json +338 -0
  14. package/data/docs/routes/components-data-display-data-table.json +855 -0
  15. package/data/docs/routes/components-data-display-draggable-list.json +596 -0
  16. package/data/docs/routes/components-data-display-table.json +472 -0
  17. package/data/docs/routes/components-data-display-tag-group.json +535 -0
  18. package/data/docs/routes/components-data-display.json +34 -0
  19. package/data/docs/routes/components-feedback-alert.json +696 -0
  20. package/data/docs/routes/components-feedback-dialog.json +682 -0
  21. package/data/docs/routes/components-feedback-drawer.json +600 -0
  22. package/data/docs/routes/components-feedback-loading-spinner.json +415 -0
  23. package/data/docs/routes/components-feedback-progress-bar.json +661 -0
  24. package/data/docs/routes/components-feedback-toast.json +1040 -0
  25. package/data/docs/routes/components-feedback-tooltip.json +510 -0
  26. package/data/docs/routes/components-feedback.json +34 -0
  27. package/data/docs/routes/components-forms-field-errors.json +557 -0
  28. package/data/docs/routes/components-forms-form-field.json +848 -0
  29. package/data/docs/routes/components-forms-group.json +427 -0
  30. package/data/docs/routes/components-forms-localized-field.json +770 -0
  31. package/data/docs/routes/components-forms.json +37 -0
  32. package/data/docs/routes/components-inputs-calendar.json +611 -0
  33. package/data/docs/routes/components-inputs-checkbox.json +774 -0
  34. package/data/docs/routes/components-inputs-combo-box.json +761 -0
  35. package/data/docs/routes/components-inputs-date-input.json +628 -0
  36. package/data/docs/routes/components-inputs-date-picker.json +709 -0
  37. package/data/docs/routes/components-inputs-date-range-picker.json +599 -0
  38. package/data/docs/routes/components-inputs-money-input.json +721 -0
  39. package/data/docs/routes/components-inputs-multiline-text-input.json +611 -0
  40. package/data/docs/routes/components-inputs-number-input.json +647 -0
  41. package/data/docs/routes/components-inputs-password-input.json +576 -0
  42. package/data/docs/routes/components-inputs-radio-input.json +583 -0
  43. package/data/docs/routes/components-inputs-range-calendar.json +607 -0
  44. package/data/docs/routes/components-inputs-rich-text-input.json +599 -0
  45. package/data/docs/routes/components-inputs-scoped-search-input.json +570 -0
  46. package/data/docs/routes/components-inputs-search-input.json +588 -0
  47. package/data/docs/routes/components-inputs-select-input.json +960 -0
  48. package/data/docs/routes/components-inputs-switch.json +720 -0
  49. package/data/docs/routes/components-inputs-text-input.json +566 -0
  50. package/data/docs/routes/components-inputs-time-input.json +775 -0
  51. package/data/docs/routes/components-inputs.json +34 -0
  52. package/data/docs/routes/components-layout-box.json +501 -0
  53. package/data/docs/routes/components-layout-defaultpage.json +748 -0
  54. package/data/docs/routes/components-layout-flex.json +587 -0
  55. package/data/docs/routes/components-layout-grid.json +393 -0
  56. package/data/docs/routes/components-layout-modalpage.json +716 -0
  57. package/data/docs/routes/components-layout-pagecontent.json +673 -0
  58. package/data/docs/routes/components-layout-scrollarea.json +428 -0
  59. package/data/docs/routes/components-layout-separator.json +461 -0
  60. package/data/docs/routes/components-layout-simple-grid.json +519 -0
  61. package/data/docs/routes/components-layout-spacer.json +573 -0
  62. package/data/docs/routes/components-layout-stack.json +481 -0
  63. package/data/docs/routes/components-layout.json +34 -0
  64. package/data/docs/routes/components-media-avatar.json +427 -0
  65. package/data/docs/routes/components-media-icon.json +663 -0
  66. package/data/docs/routes/components-media-image.json +511 -0
  67. package/data/docs/routes/components-media-inline-svg.json +586 -0
  68. package/data/docs/routes/components-media.json +34 -0
  69. package/data/docs/routes/components-navigation-accordion.json +643 -0
  70. package/data/docs/routes/components-navigation-collapsible-motion.json +628 -0
  71. package/data/docs/routes/components-navigation-link.json +554 -0
  72. package/data/docs/routes/components-navigation-menu.json +546 -0
  73. package/data/docs/routes/components-navigation-pagination.json +502 -0
  74. package/data/docs/routes/components-navigation-steps.json +629 -0
  75. package/data/docs/routes/components-navigation-tabnav.json +546 -0
  76. package/data/docs/routes/components-navigation-tabs.json +635 -0
  77. package/data/docs/routes/components-navigation-toolbar.json +549 -0
  78. package/data/docs/routes/components-navigation.json +34 -0
  79. package/data/docs/routes/components-typography-code.json +39 -0
  80. package/data/docs/routes/components-typography-heading.json +402 -0
  81. package/data/docs/routes/components-typography-kbd.json +399 -0
  82. package/data/docs/routes/components-typography-list.json +593 -0
  83. package/data/docs/routes/components-typography-text.json +444 -0
  84. package/data/docs/routes/components-typography.json +34 -0
  85. package/data/docs/routes/components-utilities-nimbus-i18n-provider.json +295 -0
  86. package/data/docs/routes/components-utilities-nimbus-provider.json +663 -0
  87. package/data/docs/routes/components-utilities.json +34 -0
  88. package/data/docs/routes/components.json +33 -0
  89. package/data/docs/routes/home-contribute-adrs-adr0001-consumer-component-apis.json +314 -0
  90. package/data/docs/routes/home-contribute-adrs-adr0002-compound-component-extraction.json +160 -0
  91. package/data/docs/routes/home-contribute-adrs-adr0003-component-lifecycle-states.json +460 -0
  92. package/data/docs/routes/home-contribute-adrs.json +205 -0
  93. package/data/docs/routes/home-contribute-development-setup.json +213 -0
  94. package/data/docs/routes/home-contribute-stats.json +36 -0
  95. package/data/docs/routes/home-contribute.json +36 -0
  96. package/data/docs/routes/home-design-tokens-aspect-ratios.json +36 -0
  97. package/data/docs/routes/home-design-tokens-borders.json +35 -0
  98. package/data/docs/routes/home-design-tokens-colors.json +157 -0
  99. package/data/docs/routes/home-design-tokens-other-animations.json +119 -0
  100. package/data/docs/routes/home-design-tokens-other-blurs.json +36 -0
  101. package/data/docs/routes/home-design-tokens-other-breakpoints.json +61 -0
  102. package/data/docs/routes/home-design-tokens-other-cursors.json +36 -0
  103. package/data/docs/routes/home-design-tokens-other-z-indices.json +39 -0
  104. package/data/docs/routes/home-design-tokens-other.json +35 -0
  105. package/data/docs/routes/home-design-tokens-radii.json +59 -0
  106. package/data/docs/routes/home-design-tokens-shadows.json +57 -0
  107. package/data/docs/routes/home-design-tokens-sizes.json +137 -0
  108. package/data/docs/routes/home-design-tokens-spacing.json +36 -0
  109. package/data/docs/routes/home-design-tokens-typography.json +184 -0
  110. package/data/docs/routes/home-design-tokens.json +34 -0
  111. package/data/docs/routes/home-getting-started-core-concepts.json +301 -0
  112. package/data/docs/routes/home-getting-started-installation.json +621 -0
  113. package/data/docs/routes/home-getting-started-mcp-server-overview.json +139 -0
  114. package/data/docs/routes/home-getting-started-mcp-server-setup.json +316 -0
  115. package/data/docs/routes/home-getting-started-release-process.json +294 -0
  116. package/data/docs/routes/home-getting-started-testing-setup.json +296 -0
  117. package/data/docs/routes/home-playground-markdown.json +638 -0
  118. package/data/docs/routes/home-playground-toc.json +169 -0
  119. package/data/docs/routes/home-playground.json +34 -0
  120. package/data/docs/routes/home-style-props-background.json +236 -0
  121. package/data/docs/routes/home-style-props-border.json +310 -0
  122. package/data/docs/routes/home-style-props-display.json +120 -0
  123. package/data/docs/routes/home-style-props-effects.json +116 -0
  124. package/data/docs/routes/home-style-props-filters.json +396 -0
  125. package/data/docs/routes/home-style-props-flex-and-grid.json +496 -0
  126. package/data/docs/routes/home-style-props-interactivity.json +356 -0
  127. package/data/docs/routes/home-style-props-layout.json +422 -0
  128. package/data/docs/routes/home-style-props-list.json +116 -0
  129. package/data/docs/routes/home-style-props-sizing.json +244 -0
  130. package/data/docs/routes/home-style-props-spacing.json +228 -0
  131. package/data/docs/routes/home-style-props-svg.json +96 -0
  132. package/data/docs/routes/home-style-props-tables.json +116 -0
  133. package/data/docs/routes/home-style-props-transforms.json +216 -0
  134. package/data/docs/routes/home-style-props-transitions.json +216 -0
  135. package/data/docs/routes/home-style-props-typography.json +536 -0
  136. package/data/docs/routes/home-style-props.json +33 -0
  137. package/data/docs/routes/home.json +32 -0
  138. package/data/docs/routes/hooks-usecopytoclipboard.json +76 -0
  139. package/data/docs/routes/hooks-usehotkeys.json +117 -0
  140. package/data/docs/routes/hooks.json +33 -0
  141. package/data/docs/routes/icons.json +32 -0
  142. package/data/docs/routes/patterns-fields-date-range-picker-field.json +393 -0
  143. package/data/docs/routes/patterns-fields-money-input-field.json +415 -0
  144. package/data/docs/routes/patterns-fields-multiline-text-input-field.json +404 -0
  145. package/data/docs/routes/patterns-fields-number-input-field.json +470 -0
  146. package/data/docs/routes/patterns-fields-password-input-field.json +319 -0
  147. package/data/docs/routes/patterns-fields-search-input-field.json +382 -0
  148. package/data/docs/routes/patterns-fields-text-input-field.json +404 -0
  149. package/data/docs/routes/patterns-fields.json +78 -0
  150. package/data/docs/routes/patterns.json +34 -0
  151. package/data/docs/search-index.json +1 -0
  152. package/data/docs/types/Accordion.json +12 -0
  153. package/data/docs/types/AccordionContent.json +286 -0
  154. package/data/docs/types/AccordionHeader.json +891 -0
  155. package/data/docs/types/AccordionHeaderRightContent.json +27 -0
  156. package/data/docs/types/AccordionItem.json +242 -0
  157. package/data/docs/types/AccordionRoot.json +162 -0
  158. package/data/docs/types/Alert.json +12 -0
  159. package/data/docs/types/AlertActions.json +11 -0
  160. package/data/docs/types/AlertDescription.json +118 -0
  161. package/data/docs/types/AlertDismissButton.json +937 -0
  162. package/data/docs/types/AlertRoot.json +42 -0
  163. package/data/docs/types/AlertTitle.json +118 -0
  164. package/data/docs/types/Avatar.json +125 -0
  165. package/data/docs/types/Badge.json +64 -0
  166. package/data/docs/types/Body.json +67 -0
  167. package/data/docs/types/Box.json +85 -0
  168. package/data/docs/types/Button.json +1015 -0
  169. package/data/docs/types/Calendar.json +565 -0
  170. package/data/docs/types/Caption.json +67 -0
  171. package/data/docs/types/Card.json +12 -0
  172. package/data/docs/types/CardContent.json +27 -0
  173. package/data/docs/types/CardHeader.json +27 -0
  174. package/data/docs/types/CardRoot.json +106 -0
  175. package/data/docs/types/Cell.json +227 -0
  176. package/data/docs/types/Checkbox.json +897 -0
  177. package/data/docs/types/Code.json +112 -0
  178. package/data/docs/types/CollapsibleMotionContent.json +35 -0
  179. package/data/docs/types/CollapsibleMotionRoot.json +99 -0
  180. package/data/docs/types/CollapsibleMotionTrigger.json +71 -0
  181. package/data/docs/types/Column.json +101 -0
  182. package/data/docs/types/ColumnGroup.json +101 -0
  183. package/data/docs/types/ColumnHeader.json +193 -0
  184. package/data/docs/types/ComboBoxListBox.json +751 -0
  185. package/data/docs/types/ComboBoxOption.json +672 -0
  186. package/data/docs/types/ComboBoxPopover.json +786 -0
  187. package/data/docs/types/ComboBoxRoot.json +747 -0
  188. package/data/docs/types/ComboBoxSection.json +277 -0
  189. package/data/docs/types/ComboBoxTrigger.json +70 -0
  190. package/data/docs/types/Content.json +33 -0
  191. package/data/docs/types/DataTable.json +596 -0
  192. package/data/docs/types/DataTableBody.json +223 -0
  193. package/data/docs/types/DataTableFooter.json +27 -0
  194. package/data/docs/types/DataTableHeader.json +269 -0
  195. package/data/docs/types/DataTableManager.json +11 -0
  196. package/data/docs/types/DataTableRoot.json +590 -0
  197. package/data/docs/types/DataTableTable.json +271 -0
  198. package/data/docs/types/DateInput.json +792 -0
  199. package/data/docs/types/DatePicker.json +700 -0
  200. package/data/docs/types/DateRangePicker.json +936 -0
  201. package/data/docs/types/DateRangePickerField.json +1047 -0
  202. package/data/docs/types/DefaultPage.json +12 -0
  203. package/data/docs/types/DefaultPageActions.json +27 -0
  204. package/data/docs/types/DefaultPageBackLink.json +213 -0
  205. package/data/docs/types/DefaultPageContent.json +27 -0
  206. package/data/docs/types/DefaultPageFooter.json +27 -0
  207. package/data/docs/types/DefaultPageHeader.json +27 -0
  208. package/data/docs/types/DefaultPageRoot.json +106 -0
  209. package/data/docs/types/DefaultPageSubtitle.json +27 -0
  210. package/data/docs/types/DefaultPageTabNav.json +28 -0
  211. package/data/docs/types/DefaultPageTitle.json +27 -0
  212. package/data/docs/types/DialogBody.json +27 -0
  213. package/data/docs/types/DialogCloseTrigger.json +939 -0
  214. package/data/docs/types/DialogContent.json +27 -0
  215. package/data/docs/types/DialogFooter.json +27 -0
  216. package/data/docs/types/DialogHeader.json +27 -0
  217. package/data/docs/types/DialogRoot.json +138 -0
  218. package/data/docs/types/DialogTitle.json +27 -0
  219. package/data/docs/types/DialogTrigger.json +80 -0
  220. package/data/docs/types/DraggableList.json +12 -0
  221. package/data/docs/types/DraggableListField.json +894 -0
  222. package/data/docs/types/DraggableListItem.json +574 -0
  223. package/data/docs/types/DraggableListRoot.json +745 -0
  224. package/data/docs/types/Drawer.json +12 -0
  225. package/data/docs/types/DrawerBody.json +27 -0
  226. package/data/docs/types/DrawerCloseTrigger.json +939 -0
  227. package/data/docs/types/DrawerContent.json +27 -0
  228. package/data/docs/types/DrawerFooter.json +27 -0
  229. package/data/docs/types/DrawerHeader.json +27 -0
  230. package/data/docs/types/DrawerRoot.json +142 -0
  231. package/data/docs/types/DrawerTitle.json +27 -0
  232. package/data/docs/types/DrawerTrigger.json +80 -0
  233. package/data/docs/types/FieldErrors.getBuiltInMessage.json +11 -0
  234. package/data/docs/types/FieldErrors.getCustomMessage.json +9 -0
  235. package/data/docs/types/FieldErrors.json +109 -0
  236. package/data/docs/types/Flex.json +238 -0
  237. package/data/docs/types/Footer.json +67 -0
  238. package/data/docs/types/FormFieldDescription.json +11 -0
  239. package/data/docs/types/FormFieldError.json +11 -0
  240. package/data/docs/types/FormFieldInfoBox.json +27 -0
  241. package/data/docs/types/FormFieldInput.json +11 -0
  242. package/data/docs/types/FormFieldLabel.json +11 -0
  243. package/data/docs/types/FormFieldRoot.json +148 -0
  244. package/data/docs/types/Grid.json +253 -0
  245. package/data/docs/types/GridProps.json +11 -0
  246. package/data/docs/types/Group.json +143 -0
  247. package/data/docs/types/Header.json +67 -0
  248. package/data/docs/types/Heading.json +109 -0
  249. package/data/docs/types/Icon.json +112 -0
  250. package/data/docs/types/IconButton.json +1019 -0
  251. package/data/docs/types/IconToggleButton.json +787 -0
  252. package/data/docs/types/Image.json +373 -0
  253. package/data/docs/types/Indicator.json +67 -0
  254. package/data/docs/types/InlineSvg.json +98 -0
  255. package/data/docs/types/Item.json +67 -0
  256. package/data/docs/types/Kbd.json +118 -0
  257. package/data/docs/types/Link.json +380 -0
  258. package/data/docs/types/List.json +12 -0
  259. package/data/docs/types/ListIndicator.json +70 -0
  260. package/data/docs/types/ListItem.json +70 -0
  261. package/data/docs/types/ListRoot.json +124 -0
  262. package/data/docs/types/LoadingSpinner.json +87 -0
  263. package/data/docs/types/LocalizedField.json +460 -0
  264. package/data/docs/types/LocalizedStringFormatter.json +9 -0
  265. package/data/docs/types/MakeElementFocusable.json +196 -0
  266. package/data/docs/types/MenuContent.json +111 -0
  267. package/data/docs/types/MenuItem.json +671 -0
  268. package/data/docs/types/MenuRoot.json +670 -0
  269. package/data/docs/types/MenuSection.json +364 -0
  270. package/data/docs/types/MenuSubmenu.json +111 -0
  271. package/data/docs/types/MenuSubmenuTrigger.json +67 -0
  272. package/data/docs/types/MenuTrigger.json +906 -0
  273. package/data/docs/types/ModalPage.json +12 -0
  274. package/data/docs/types/ModalPageActions.json +27 -0
  275. package/data/docs/types/ModalPageContent.json +27 -0
  276. package/data/docs/types/ModalPageFooter.json +27 -0
  277. package/data/docs/types/ModalPageHeader.json +27 -0
  278. package/data/docs/types/ModalPageRoot.json +87 -0
  279. package/data/docs/types/ModalPageSubtitle.json +27 -0
  280. package/data/docs/types/ModalPageTabNav.json +28 -0
  281. package/data/docs/types/ModalPageTitle.json +27 -0
  282. package/data/docs/types/ModalPageTopBar.json +57 -0
  283. package/data/docs/types/MoneyInput.isEmpty.json +40 -0
  284. package/data/docs/types/MoneyInput.json +282 -0
  285. package/data/docs/types/MoneyInputField.json +379 -0
  286. package/data/docs/types/MoneyInputFieldProps.json +9 -0
  287. package/data/docs/types/MultilineTextInput.json +1194 -0
  288. package/data/docs/types/MultilineTextInputField.json +1269 -0
  289. package/data/docs/types/MultilineTextInputFieldProps.json +9 -0
  290. package/data/docs/types/NimbusI18nProvider.json +42 -0
  291. package/data/docs/types/NimbusI18nProviderProps.json +9 -0
  292. package/data/docs/types/NimbusProvider.json +270 -0
  293. package/data/docs/types/NumberInput.json +952 -0
  294. package/data/docs/types/NumberInputField.json +1004 -0
  295. package/data/docs/types/NumberInputFieldProps.json +9 -0
  296. package/data/docs/types/PageContent.json +11 -0
  297. package/data/docs/types/PageContentColumn.json +99 -0
  298. package/data/docs/types/PageContentRoot.json +114 -0
  299. package/data/docs/types/Pagination.json +159 -0
  300. package/data/docs/types/PasswordInput.json +1120 -0
  301. package/data/docs/types/PasswordInputField.json +1216 -0
  302. package/data/docs/types/PasswordInputFieldProps.json +9 -0
  303. package/data/docs/types/ProgressBar.json +280 -0
  304. package/data/docs/types/RadioInputOption.json +550 -0
  305. package/data/docs/types/RadioInputRoot.json +514 -0
  306. package/data/docs/types/RangeCalendar.json +618 -0
  307. package/data/docs/types/RichTextInput.json +134 -0
  308. package/data/docs/types/Root.json +122 -0
  309. package/data/docs/types/Row.json +67 -0
  310. package/data/docs/types/ScopedSearchInput.isEmpty.json +40 -0
  311. package/data/docs/types/ScopedSearchInput.json +253 -0
  312. package/data/docs/types/ScrollArea.json +179 -0
  313. package/data/docs/types/ScrollAreaElementIds.json +9 -0
  314. package/data/docs/types/ScrollAreaProps.json +9 -0
  315. package/data/docs/types/SearchInput.json +1165 -0
  316. package/data/docs/types/SearchInputField.json +1240 -0
  317. package/data/docs/types/Select.json +12 -0
  318. package/data/docs/types/SelectOption.json +572 -0
  319. package/data/docs/types/SelectOptionGroup.json +215 -0
  320. package/data/docs/types/SelectOptions.json +693 -0
  321. package/data/docs/types/SelectRoot.json +926 -0
  322. package/data/docs/types/Separator.json +65 -0
  323. package/data/docs/types/SimpleGrid.json +291 -0
  324. package/data/docs/types/Spacer.json +27 -0
  325. package/data/docs/types/SpacerProps.json +9 -0
  326. package/data/docs/types/SplitButton.json +203 -0
  327. package/data/docs/types/Stack.json +144 -0
  328. package/data/docs/types/Steps.json +12 -0
  329. package/data/docs/types/StepsChangeDetails.json +9 -0
  330. package/data/docs/types/StepsCompletedContent.json +28 -0
  331. package/data/docs/types/StepsCompletedContentProps.json +9 -0
  332. package/data/docs/types/StepsContent.json +43 -0
  333. package/data/docs/types/StepsContentProps.json +9 -0
  334. package/data/docs/types/StepsDescription.json +28 -0
  335. package/data/docs/types/StepsDescriptionProps.json +9 -0
  336. package/data/docs/types/StepsIndicator.json +28 -0
  337. package/data/docs/types/StepsIndicatorProps.json +9 -0
  338. package/data/docs/types/StepsItem.json +43 -0
  339. package/data/docs/types/StepsItemProps.json +9 -0
  340. package/data/docs/types/StepsList.json +28 -0
  341. package/data/docs/types/StepsListProps.json +9 -0
  342. package/data/docs/types/StepsNextTrigger.json +62 -0
  343. package/data/docs/types/StepsNextTriggerProps.json +9 -0
  344. package/data/docs/types/StepsNumber.json +28 -0
  345. package/data/docs/types/StepsNumberProps.json +9 -0
  346. package/data/docs/types/StepsPrevTrigger.json +62 -0
  347. package/data/docs/types/StepsPrevTriggerProps.json +9 -0
  348. package/data/docs/types/StepsRoot.json +183 -0
  349. package/data/docs/types/StepsRootProps.json +11 -0
  350. package/data/docs/types/StepsSeparator.json +28 -0
  351. package/data/docs/types/StepsSeparatorProps.json +9 -0
  352. package/data/docs/types/StepsStatus.json +57 -0
  353. package/data/docs/types/StepsStatusProps.json +9 -0
  354. package/data/docs/types/StepsTitle.json +28 -0
  355. package/data/docs/types/StepsTitleProps.json +9 -0
  356. package/data/docs/types/StepsTrigger.json +47 -0
  357. package/data/docs/types/StepsTriggerProps.json +9 -0
  358. package/data/docs/types/Switch.json +371 -0
  359. package/data/docs/types/TabListProps.json +9 -0
  360. package/data/docs/types/TabNav.json +12 -0
  361. package/data/docs/types/TabNavItem.json +300 -0
  362. package/data/docs/types/TabNavItemProps.json +9 -0
  363. package/data/docs/types/TabNavProps.json +9 -0
  364. package/data/docs/types/TabNavRoot.json +80 -0
  365. package/data/docs/types/TabPanelProps.json +9 -0
  366. package/data/docs/types/TabPanelsProps.json +9 -0
  367. package/data/docs/types/TabProps.json +9 -0
  368. package/data/docs/types/Table.json +9 -0
  369. package/data/docs/types/TableBody.json +67 -0
  370. package/data/docs/types/TableBodyProps.json +9 -0
  371. package/data/docs/types/TableCaption.json +67 -0
  372. package/data/docs/types/TableCaptionProps.json +9 -0
  373. package/data/docs/types/TableCell.json +227 -0
  374. package/data/docs/types/TableCellProps.json +9 -0
  375. package/data/docs/types/TableColumn.json +101 -0
  376. package/data/docs/types/TableColumnGroup.json +101 -0
  377. package/data/docs/types/TableColumnGroupProps.json +9 -0
  378. package/data/docs/types/TableColumnHeader.json +193 -0
  379. package/data/docs/types/TableColumnHeaderProps.json +9 -0
  380. package/data/docs/types/TableColumnProps.json +9 -0
  381. package/data/docs/types/TableFooter.json +67 -0
  382. package/data/docs/types/TableFooterProps.json +9 -0
  383. package/data/docs/types/TableHeader.json +67 -0
  384. package/data/docs/types/TableHeaderProps.json +9 -0
  385. package/data/docs/types/TableRoot.json +365 -0
  386. package/data/docs/types/TableRootProps.json +12 -0
  387. package/data/docs/types/TableRow.json +67 -0
  388. package/data/docs/types/TableRowProps.json +9 -0
  389. package/data/docs/types/TableScrollArea.json +82 -0
  390. package/data/docs/types/TableScrollAreaProps.json +9 -0
  391. package/data/docs/types/Tabs.json +12 -0
  392. package/data/docs/types/TabsList.json +110 -0
  393. package/data/docs/types/TabsPanel.json +112 -0
  394. package/data/docs/types/TabsPanels.json +108 -0
  395. package/data/docs/types/TabsRoot.json +211 -0
  396. package/data/docs/types/TabsTab.json +174 -0
  397. package/data/docs/types/TagGroup.json +12 -0
  398. package/data/docs/types/TagGroupRoot.json +306 -0
  399. package/data/docs/types/TagGroupTag.json +595 -0
  400. package/data/docs/types/TagGroupTagList.json +166 -0
  401. package/data/docs/types/Text.json +119 -0
  402. package/data/docs/types/TextInput.json +1156 -0
  403. package/data/docs/types/TextInputField.json +1263 -0
  404. package/data/docs/types/TimeInput.json +752 -0
  405. package/data/docs/types/ToastAction.json +9 -0
  406. package/data/docs/types/ToastManagerApi.json +9 -0
  407. package/data/docs/types/ToastOptions.json +9 -0
  408. package/data/docs/types/ToastOutlet.json +12 -0
  409. package/data/docs/types/ToastPlacement.json +9 -0
  410. package/data/docs/types/ToastPromiseOptions.json +9 -0
  411. package/data/docs/types/ToastType.json +9 -0
  412. package/data/docs/types/ToastVariant.json +9 -0
  413. package/data/docs/types/ToggleButton.json +789 -0
  414. package/data/docs/types/ToggleButtonGroup.json +9 -0
  415. package/data/docs/types/ToggleButtonGroupButton.json +331 -0
  416. package/data/docs/types/ToggleButtonGroupRoot.json +269 -0
  417. package/data/docs/types/Toolbar.json +176 -0
  418. package/data/docs/types/Tooltip.json +12 -0
  419. package/data/docs/types/TooltipContent.json +372 -0
  420. package/data/docs/types/TooltipRoot.json +179 -0
  421. package/data/docs/types/Trigger.json +69 -0
  422. package/data/docs/types/VisuallyHidden.json +93 -0
  423. package/data/docs/types/__object.json +12 -0
  424. package/data/docs/types/filters.json +11 -0
  425. package/data/docs/types/manifest.json +280 -0
  426. package/data/docs/types/toast.json +234 -0
  427. package/data/docs/types/useColorMode.json +13 -0
  428. package/data/docs/types/useColorModeValue.json +13 -0
  429. package/data/docs/types/useColorScheme.json +12 -0
  430. package/data/docs/types/useLocalizedStringFormatter.json +14 -0
  431. package/data/icons.json +21940 -0
  432. package/data/tokens.json +40061 -0
  433. package/dist/index.js +2516 -17
  434. package/package.json +25 -6
  435. package/dist/data-loader.d.ts +0 -102
  436. package/dist/data-loader.js +0 -104
  437. package/dist/index.d.ts +0 -13
  438. package/dist/server.d.ts +0 -9
  439. package/dist/server.js +0 -22
  440. package/dist/server.spec.d.ts +0 -1
  441. package/dist/server.spec.js +0 -69
  442. package/dist/tools/list-components.d.ts +0 -9
  443. package/dist/tools/list-components.js +0 -42
  444. package/dist/types.d.ts +0 -28
  445. package/dist/types.js +0 -4
  446. package/src/data-loader.ts +0 -226
  447. package/src/index.ts +0 -29
  448. package/src/server.spec.ts +0 -86
  449. package/src/server.ts +0 -28
  450. package/src/tools/list-components.ts +0 -49
  451. package/src/types.ts +0 -31
  452. package/tsconfig.json +0 -14
  453. package/vitest.config.ts +0 -9
@@ -0,0 +1,848 @@
1
+ {
2
+ "meta": {
3
+ "id": "Components-FormField",
4
+ "title": "Form field",
5
+ "exportName": "FormField",
6
+ "description": "Form fields are the building blocks of user interaction, collecting essential data, facilitating actions, and enabling customization within digital interfaces.",
7
+ "lifecycleState": "Stable",
8
+ "order": 999,
9
+ "repoPath": "packages/nimbus/src/components/form-field/form-field.mdx",
10
+ "menu": [
11
+ "Components",
12
+ "Forms",
13
+ "Form field"
14
+ ],
15
+ "route": "components/forms/form-field",
16
+ "tags": [
17
+ "component",
18
+ "form",
19
+ "field",
20
+ "label",
21
+ "input wrapper"
22
+ ],
23
+ "toc": [
24
+ {
25
+ "value": "Overview",
26
+ "href": "#overview",
27
+ "depth": 2,
28
+ "numbering": [
29
+ 1,
30
+ 1
31
+ ],
32
+ "parent": "root"
33
+ },
34
+ {
35
+ "value": "Resources",
36
+ "href": "#resources",
37
+ "depth": 3,
38
+ "numbering": [
39
+ 1,
40
+ 1,
41
+ 1
42
+ ],
43
+ "parent": "root"
44
+ },
45
+ {
46
+ "value": "Variables",
47
+ "href": "#variables",
48
+ "depth": 2,
49
+ "numbering": [
50
+ 1,
51
+ 2
52
+ ],
53
+ "parent": "root"
54
+ },
55
+ {
56
+ "value": "Label options",
57
+ "href": "#label-options",
58
+ "depth": 3,
59
+ "numbering": [
60
+ 1,
61
+ 2,
62
+ 1
63
+ ],
64
+ "parent": "root"
65
+ },
66
+ {
67
+ "value": "Simple",
68
+ "href": "#simple",
69
+ "depth": 4,
70
+ "numbering": [
71
+ 1,
72
+ 2,
73
+ 1,
74
+ 1
75
+ ],
76
+ "parent": "root"
77
+ },
78
+ {
79
+ "value": "With help text",
80
+ "href": "#with-help-text",
81
+ "depth": 4,
82
+ "numbering": [
83
+ 1,
84
+ 2,
85
+ 1,
86
+ 2
87
+ ],
88
+ "parent": "root"
89
+ },
90
+ {
91
+ "value": "With error message",
92
+ "href": "#with-error-message",
93
+ "depth": 4,
94
+ "numbering": [
95
+ 1,
96
+ 2,
97
+ 1,
98
+ 3
99
+ ],
100
+ "parent": "root"
101
+ },
102
+ {
103
+ "value": "Required with info icon and help text",
104
+ "href": "#required-with-info-icon-and-help-text",
105
+ "depth": 4,
106
+ "numbering": [
107
+ 1,
108
+ 2,
109
+ 1,
110
+ 4
111
+ ],
112
+ "parent": "root"
113
+ },
114
+ {
115
+ "value": "Label on the left with info icon and help text",
116
+ "href": "#label-on-the-left-with-info-icon-and-help-text",
117
+ "depth": 4,
118
+ "numbering": [
119
+ 1,
120
+ 2,
121
+ 1,
122
+ 5
123
+ ],
124
+ "parent": "root"
125
+ },
126
+ {
127
+ "value": "Size",
128
+ "href": "#size",
129
+ "depth": 3,
130
+ "numbering": [
131
+ 1,
132
+ 2,
133
+ 2
134
+ ],
135
+ "parent": "root"
136
+ },
137
+ {
138
+ "value": "Medium",
139
+ "href": "#medium",
140
+ "depth": 4,
141
+ "numbering": [
142
+ 1,
143
+ 2,
144
+ 2,
145
+ 1
146
+ ],
147
+ "parent": "root"
148
+ },
149
+ {
150
+ "value": "Small",
151
+ "href": "#small",
152
+ "depth": 4,
153
+ "numbering": [
154
+ 1,
155
+ 2,
156
+ 2,
157
+ 2
158
+ ],
159
+ "parent": "root"
160
+ }
161
+ ],
162
+ "figmaLink": "https://www.figma.com/design/AvtPX6g7OGGCRvNlatGOIY/NIMBUS-design-system?node-id=349-2635&m=dev",
163
+ "layout": "app-frame",
164
+ "tabs": [
165
+ {
166
+ "key": "overview",
167
+ "title": "Overview",
168
+ "order": 0
169
+ },
170
+ {
171
+ "key": "guidelines",
172
+ "title": "Guidelines",
173
+ "order": 2
174
+ },
175
+ {
176
+ "key": "dev",
177
+ "title": "Implementation",
178
+ "order": 3
179
+ },
180
+ {
181
+ "key": "a11y",
182
+ "title": "Accessibility",
183
+ "order": 4
184
+ }
185
+ ]
186
+ },
187
+ "mdx": "\n## Overview\n\nComposed of several elements, a label, optional helper icon, a text input. There\nis also an optional helper text feature that presents at the bottom of the\nfield.\n\n### Resources\n\nDeep dive into implementation details and access the Nimbus design library.\n\n[Figma library](https://www.figma.com/design/AvtPX6g7OGGCRvNlatGOIY/NIMBUS-design-system?node-id=349-2635&m=dev)\n\n## Variables\n\nGet familiar with the features.\n\n### Label options\n\n#### Simple\n\nLabel is used to describe the form.\n\n```jsx live\nconst App = () => {\n const [val, setVal] = useState('Input value');\n\n return (\n <FormField.Root>\n <FormField.Label>Label</FormField.Label>\n <FormField.Input>\n <TextInput width=\"full\" value={val} onChange={(v)=>setVal(v)} placeholder=\"Enter something...\" />\n </FormField.Input>\n </FormField.Root>\n )\n}\n```\n\n#### With help text\n\nLabel paired with form and description to give users extra clarification.\n\n```jsx live\nconst App = () => {\n const [val, setVal] = useState('Input value');\n\n return (\n <FormField.Root>\n <FormField.Label>Label</FormField.Label>\n <FormField.Input>\n <TextInput width=\"full\" value={val} onChange={(v)=>setVal(v)} placeholder=\"Enter something...\" />\n </FormField.Input>\n <FormField.Description>Help Text</FormField.Description>\n </FormField.Root>\n )\n}\n```\n\n#### With error message\n\nExplain errors to the user in an eye catching way.\n\n```jsx live\nconst App = () => {\n const [val, setVal] = useState('Input value');\n\n return (\n <FormField.Root isInvalid>\n <FormField.Label>Label</FormField.Label>\n <FormField.Input>\n <TextInput width=\"full\" value={val} onChange={(v)=>setVal(v)} placeholder=\"Enter something...\" />\n </FormField.Input>\n <FormField.Error>\n Error message\n </FormField.Error>\n </FormField.Root>\n )\n}\n```\n\n#### Required with info icon and help text\n\nThis is the default placement of labels. Info button should always open an info\ndialog, not just a tooltip on hover.\n\n```jsx live\nconst App = () => {\n const [val, setVal] = useState('Input value');\n\n return (\n <FormField.Root isRequired>\n <FormField.Label>Label</FormField.Label>\n <FormField.Input>\n <TextInput width=\"full\" value={val} onChange={(v)=>setVal(v)} placeholder=\"Enter something...\" />\n </FormField.Input>\n <FormField.Description>\n Help Text\n </FormField.Description>\n <FormField.InfoBox>\n Info box content.\n </FormField.InfoBox>\n </FormField.Root>\n )\n}\n```\n\n#### Label on the left with info icon and help text\n\nThese can be used to make the page a little more condensed for the user.\n\n```jsx live\nconst App = () => {\n const [val, setVal] = useState('Input value');\n\n return (\n <FormField.Root direction=\"row\" isRequired>\n <FormField.Label>Label</FormField.Label>\n <FormField.Input>\n <TextInput value={val} onChange={(v)=>setVal(v)} placeholder=\"Enter something...\" />\n </FormField.Input>\n <FormField.Description>\n Help Text\n </FormField.Description>\n <FormField.InfoBox>\n Info box content.\n </FormField.InfoBox>\n </FormField.Root>\n )\n}\n```\n\n### Size\n\n#### Medium\n\nThis is the default size for form fields.\n\n```jsx live\nconst App = () => {\n const [val, setVal] = useState('Input value');\n\n return (\n <FormField.Root isRequired size=\"md\">\n <FormField.Label>Label</FormField.Label>\n <FormField.Input>\n <TextInput width=\"full\" value={val} onChange={(v)=>setVal(v)} placeholder=\"Enter something...\" />\n </FormField.Input>\n <FormField.Description>\n Help Text\n </FormField.Description>\n <FormField.InfoBox>\n Info box content.\n </FormField.InfoBox>\n </FormField.Root>\n )\n}\n```\n\n#### Small\n\nUse to condense forms.\n\n```jsx live\nconst App = () => {\n const [val, setVal] = useState('Input value');\n\n return (\n <FormField.Root isRequired size=\"sm\">\n <FormField.Label>Label</FormField.Label>\n <FormField.Input>\n <TextInput width=\"full\" size=\"sm\" value={val} onChange={(v)=>setVal(v)} placeholder=\"Enter something...\" />\n </FormField.Input>\n <FormField.Description>\n Help Text\n </FormField.Description>\n <FormField.InfoBox>\n Info box content.\n </FormField.InfoBox>\n </FormField.Root>\n )\n}\n```\n",
188
+ "views": {
189
+ "overview": {
190
+ "mdx": "\n## Overview\n\nComposed of several elements, a label, optional helper icon, a text input. There\nis also an optional helper text feature that presents at the bottom of the\nfield.\n\n### Resources\n\nDeep dive into implementation details and access the Nimbus design library.\n\n[Figma library](https://www.figma.com/design/AvtPX6g7OGGCRvNlatGOIY/NIMBUS-design-system?node-id=349-2635&m=dev)\n\n## Variables\n\nGet familiar with the features.\n\n### Label options\n\n#### Simple\n\nLabel is used to describe the form.\n\n```jsx live\nconst App = () => {\n const [val, setVal] = useState('Input value');\n\n return (\n <FormField.Root>\n <FormField.Label>Label</FormField.Label>\n <FormField.Input>\n <TextInput width=\"full\" value={val} onChange={(v)=>setVal(v)} placeholder=\"Enter something...\" />\n </FormField.Input>\n </FormField.Root>\n )\n}\n```\n\n#### With help text\n\nLabel paired with form and description to give users extra clarification.\n\n```jsx live\nconst App = () => {\n const [val, setVal] = useState('Input value');\n\n return (\n <FormField.Root>\n <FormField.Label>Label</FormField.Label>\n <FormField.Input>\n <TextInput width=\"full\" value={val} onChange={(v)=>setVal(v)} placeholder=\"Enter something...\" />\n </FormField.Input>\n <FormField.Description>Help Text</FormField.Description>\n </FormField.Root>\n )\n}\n```\n\n#### With error message\n\nExplain errors to the user in an eye catching way.\n\n```jsx live\nconst App = () => {\n const [val, setVal] = useState('Input value');\n\n return (\n <FormField.Root isInvalid>\n <FormField.Label>Label</FormField.Label>\n <FormField.Input>\n <TextInput width=\"full\" value={val} onChange={(v)=>setVal(v)} placeholder=\"Enter something...\" />\n </FormField.Input>\n <FormField.Error>\n Error message\n </FormField.Error>\n </FormField.Root>\n )\n}\n```\n\n#### Required with info icon and help text\n\nThis is the default placement of labels. Info button should always open an info\ndialog, not just a tooltip on hover.\n\n```jsx live\nconst App = () => {\n const [val, setVal] = useState('Input value');\n\n return (\n <FormField.Root isRequired>\n <FormField.Label>Label</FormField.Label>\n <FormField.Input>\n <TextInput width=\"full\" value={val} onChange={(v)=>setVal(v)} placeholder=\"Enter something...\" />\n </FormField.Input>\n <FormField.Description>\n Help Text\n </FormField.Description>\n <FormField.InfoBox>\n Info box content.\n </FormField.InfoBox>\n </FormField.Root>\n )\n}\n```\n\n#### Label on the left with info icon and help text\n\nThese can be used to make the page a little more condensed for the user.\n\n```jsx live\nconst App = () => {\n const [val, setVal] = useState('Input value');\n\n return (\n <FormField.Root direction=\"row\" isRequired>\n <FormField.Label>Label</FormField.Label>\n <FormField.Input>\n <TextInput value={val} onChange={(v)=>setVal(v)} placeholder=\"Enter something...\" />\n </FormField.Input>\n <FormField.Description>\n Help Text\n </FormField.Description>\n <FormField.InfoBox>\n Info box content.\n </FormField.InfoBox>\n </FormField.Root>\n )\n}\n```\n\n### Size\n\n#### Medium\n\nThis is the default size for form fields.\n\n```jsx live\nconst App = () => {\n const [val, setVal] = useState('Input value');\n\n return (\n <FormField.Root isRequired size=\"md\">\n <FormField.Label>Label</FormField.Label>\n <FormField.Input>\n <TextInput width=\"full\" value={val} onChange={(v)=>setVal(v)} placeholder=\"Enter something...\" />\n </FormField.Input>\n <FormField.Description>\n Help Text\n </FormField.Description>\n <FormField.InfoBox>\n Info box content.\n </FormField.InfoBox>\n </FormField.Root>\n )\n}\n```\n\n#### Small\n\nUse to condense forms.\n\n```jsx live\nconst App = () => {\n const [val, setVal] = useState('Input value');\n\n return (\n <FormField.Root isRequired size=\"sm\">\n <FormField.Label>Label</FormField.Label>\n <FormField.Input>\n <TextInput width=\"full\" size=\"sm\" value={val} onChange={(v)=>setVal(v)} placeholder=\"Enter something...\" />\n </FormField.Input>\n <FormField.Description>\n Help Text\n </FormField.Description>\n <FormField.InfoBox>\n Info box content.\n </FormField.InfoBox>\n </FormField.Root>\n )\n}\n```\n",
191
+ "toc": [
192
+ {
193
+ "value": "Overview",
194
+ "href": "#overview",
195
+ "depth": 2,
196
+ "numbering": [
197
+ 1,
198
+ 1
199
+ ],
200
+ "parent": "root"
201
+ },
202
+ {
203
+ "value": "Resources",
204
+ "href": "#resources",
205
+ "depth": 3,
206
+ "numbering": [
207
+ 1,
208
+ 1,
209
+ 1
210
+ ],
211
+ "parent": "root"
212
+ },
213
+ {
214
+ "value": "Variables",
215
+ "href": "#variables",
216
+ "depth": 2,
217
+ "numbering": [
218
+ 1,
219
+ 2
220
+ ],
221
+ "parent": "root"
222
+ },
223
+ {
224
+ "value": "Label options",
225
+ "href": "#label-options",
226
+ "depth": 3,
227
+ "numbering": [
228
+ 1,
229
+ 2,
230
+ 1
231
+ ],
232
+ "parent": "root"
233
+ },
234
+ {
235
+ "value": "Simple",
236
+ "href": "#simple",
237
+ "depth": 4,
238
+ "numbering": [
239
+ 1,
240
+ 2,
241
+ 1,
242
+ 1
243
+ ],
244
+ "parent": "root"
245
+ },
246
+ {
247
+ "value": "With help text",
248
+ "href": "#with-help-text",
249
+ "depth": 4,
250
+ "numbering": [
251
+ 1,
252
+ 2,
253
+ 1,
254
+ 2
255
+ ],
256
+ "parent": "root"
257
+ },
258
+ {
259
+ "value": "With error message",
260
+ "href": "#with-error-message",
261
+ "depth": 4,
262
+ "numbering": [
263
+ 1,
264
+ 2,
265
+ 1,
266
+ 3
267
+ ],
268
+ "parent": "root"
269
+ },
270
+ {
271
+ "value": "Required with info icon and help text",
272
+ "href": "#required-with-info-icon-and-help-text",
273
+ "depth": 4,
274
+ "numbering": [
275
+ 1,
276
+ 2,
277
+ 1,
278
+ 4
279
+ ],
280
+ "parent": "root"
281
+ },
282
+ {
283
+ "value": "Label on the left with info icon and help text",
284
+ "href": "#label-on-the-left-with-info-icon-and-help-text",
285
+ "depth": 4,
286
+ "numbering": [
287
+ 1,
288
+ 2,
289
+ 1,
290
+ 5
291
+ ],
292
+ "parent": "root"
293
+ },
294
+ {
295
+ "value": "Size",
296
+ "href": "#size",
297
+ "depth": 3,
298
+ "numbering": [
299
+ 1,
300
+ 2,
301
+ 2
302
+ ],
303
+ "parent": "root"
304
+ },
305
+ {
306
+ "value": "Medium",
307
+ "href": "#medium",
308
+ "depth": 4,
309
+ "numbering": [
310
+ 1,
311
+ 2,
312
+ 2,
313
+ 1
314
+ ],
315
+ "parent": "root"
316
+ },
317
+ {
318
+ "value": "Small",
319
+ "href": "#small",
320
+ "depth": 4,
321
+ "numbering": [
322
+ 1,
323
+ 2,
324
+ 2,
325
+ 2
326
+ ],
327
+ "parent": "root"
328
+ }
329
+ ]
330
+ },
331
+ "a11y": {
332
+ "mdx": "\n## Accessibility\n\nAccessibility ensures that digital content and functionality are usable by\neveryone, including people with disabilities, by addressing visual, auditory,\ncognitive, and physical limitations.\n\n```jsx live\nconst App = () => {\n const [val, setVal] = useState('Input value');\n\n return (\n <FormField.Root isRequired>\n <FormField.Label>Label</FormField.Label>\n <FormField.Input>\n <TextInput width=\"full\" value={val} onChange={(v)=>setVal(v)} placeholder=\"Enter something...\" />\n </FormField.Input>\n <FormField.Description>Help Text</FormField.Description>\n <FormField.InfoBox>\n Info box content.\n </FormField.InfoBox>\n </FormField.Root>\n )\n}\n```\n\n### Accessibility standards\n\n- **Non-text content:** Provide text alternatives for any non-text content\n within or associated with form fields (e.g., icons, images). Use alt text for\n images and provide text equivalents for other non-text content.\n- **Info and relationships:** Use the `<label>` element to programmatically\n associate labels with form fields. Ensure that assistive technologies can\n determine the relationship between labels and their corresponding inputs.\n- **Group related fields:** Group related form fields using `<fieldset>` and\n provide a `<legend>` to create logical sections.\n- **ARIA attributes:** Use ARIA attributes (e.g., `aria-describedby`,\n `aria-labelledby`) to establish relationships between form fields and related\n elements.\n- **Use of color:** Avoid relying solely on color to convey information or\n indicate the state of form fields (e.g., required fields, error states).\n Provide redundant visual cues, such as icons, text, or patterns, to supplement\n color-based indicators.\n- **Color contrast:** Ensure sufficient color contrast between form field\n labels, input fields, borders, and background colors. Use a contrast checking\n tool to verify that the contrast ratio meets the minimum requirements.\n- **Keyboard accessibility:** Make all form field functionality operable using\n the keyboard. Enable users to navigate between form fields using the Tab key.\n Allow users to activate form field controls (e.g., buttons, checkboxes, radio\n buttons) using the Spacebar or Enter key. Ensure that keyboard focus is not\n trapped within form fields.\n- **Focus visible:** Provide a clear and visible focus indicator for form fields\n when they receive keyboard focus. Visually distinguish the focus state from\n the default state using outlines, highlights, or other visual cues. Avoid\n relying solely on color changes to indicate focus.\n- **On focus:** Prevent form fields from unexpectedly changing the context of\n the page when they receive focus. Ensure that any context changes are\n initiated by user actions, such as submitting the form.\n- **Error identification:** Identify and describe input errors in text when they\n are automatically detected. Display clear and concise error messages near the\n corresponding form fields.\n- **Labels or instructions:** Provide clear, concise, and descriptive labels or\n instructions for all form fields. Write labels that accurately reflect the\n purpose of the form fields. Provide instructions about the expected input\n format or requirements. Avoid using placeholder text as a replacement for\n visible labels.\n- **Error suggestion:** If an input error is automatically detected and\n suggestions for correction are known, provide the suggestions to the user,\n unless it would jeopardize the security or purpose of the content.\n- **Name, role, value:** Use semantic HTML elements (e.g., `<input>`,\n `<textarea>`, `<select>`) to define the role, name, and value of form fields.\n Ensure that assistive technologies can correctly interpret form fields and\n their attributes. Use ARIA attributes when necessary to provide additional\n information to assistive technologies, especially for complex or custom form\n fields.\n",
333
+ "toc": [
334
+ {
335
+ "value": "Accessibility",
336
+ "href": "#accessibility",
337
+ "depth": 2,
338
+ "numbering": [
339
+ 1,
340
+ 1
341
+ ],
342
+ "parent": "root"
343
+ },
344
+ {
345
+ "value": "Accessibility standards",
346
+ "href": "#accessibility-standards",
347
+ "depth": 3,
348
+ "numbering": [
349
+ 1,
350
+ 1,
351
+ 1
352
+ ],
353
+ "parent": "root"
354
+ }
355
+ ]
356
+ },
357
+ "dev": {
358
+ "mdx": "\n## Getting started\n\n### Import\n\n```tsx\nimport { FormField, type FormFieldProps } from '@commercetools/nimbus';\n```\n\n### Basic usage\n\nFormField is a compound component that provides a structured container for form inputs with automatic accessibility via React Aria. It coordinates label, input, description, and error elements:\n\n```jsx live-dev\nconst App = () => (\n <FormField.Root>\n <FormField.Label>Username</FormField.Label>\n <FormField.Input>\n <TextInput placeholder=\"Enter your username\" />\n </FormField.Input>\n <FormField.Description>\n Must be 3-20 characters, letters and numbers only\n </FormField.Description>\n </FormField.Root>\n);\n```\n\n## Usage examples\n\n### Size options\n\nFormField supports two size variants that affect the typography scale:\n\n```jsx live-dev\nconst App = () => (\n <Stack direction=\"column\" gap=\"600\">\n <FormField.Root size=\"sm\">\n <FormField.Label>Small Size</FormField.Label>\n <FormField.Input>\n <TextInput placeholder=\"Small field\" />\n </FormField.Input>\n <FormField.Description>Smaller typography for compact layouts</FormField.Description>\n </FormField.Root>\n\n <FormField.Root size=\"md\">\n <FormField.Label>Medium Size (default)</FormField.Label>\n <FormField.Input>\n <TextInput placeholder=\"Medium field\" />\n </FormField.Input>\n <FormField.Description>Standard typography for most forms</FormField.Description>\n </FormField.Root>\n </Stack>\n);\n```\n\n### Layout direction\n\nControl the label and input positioning with the `direction` prop:\n\n```jsx live-dev\nconst App = () => (\n <Stack direction=\"column\" gap=\"600\">\n <FormField.Root direction=\"column\">\n <FormField.Label>Column Layout (default)</FormField.Label>\n <FormField.Input>\n <TextInput placeholder=\"Label above input\" />\n </FormField.Input>\n <FormField.Description>Label and input stacked vertically</FormField.Description>\n </FormField.Root>\n\n <FormField.Root direction=\"row\">\n <FormField.Label>Row Layout</FormField.Label>\n <FormField.Input>\n <TextInput placeholder=\"Label beside input\" />\n </FormField.Input>\n <FormField.Description>Label and input side by side</FormField.Description>\n </FormField.Root>\n </Stack>\n);\n```\n\n### Required fields\n\nMark fields as required to display a visual indicator and set ARIA attributes:\n\n```jsx live-dev\nconst App = () => (\n <FormField.Root isRequired>\n <FormField.Label>Email Address</FormField.Label>\n <FormField.Input>\n <TextInput type=\"email\" placeholder=\"your@email.com\" />\n </FormField.Input>\n <FormField.Description>\n We'll never share your email with anyone else\n </FormField.Description>\n </FormField.Root>\n);\n```\n\n### Validation errors\n\nDisplay error messages when validation fails using the `isInvalid` prop:\n\n```jsx live-dev\nconst App = () => {\n const [email, setEmail] = React.useState('invalid-email');\n const [touched, setTouched] = React.useState(false);\n\n const isValid = email.includes('@') && email.includes('.');\n const showError = touched && !isValid;\n\n return (\n <Stack direction=\"column\" gap=\"400\">\n <FormField.Root isInvalid={showError} isRequired>\n <FormField.Label>Email Address</FormField.Label>\n <FormField.Input>\n <TextInput\n type=\"email\"\n value={email}\n onChange={(e) => setEmail(e.target.value)}\n onBlur={() => setTouched(true)}\n placeholder=\"your@email.com\"\n />\n </FormField.Input>\n <FormField.Description>Enter a valid email address</FormField.Description>\n <FormField.Error>Please enter a valid email address</FormField.Error>\n </FormField.Root>\n\n <Text fontSize=\"300\" color=\"neutral.11\">\n Current value: {email}\n </Text>\n </Stack>\n );\n};\n```\n\n### Disabled state\n\nDisable user interaction with the field using `isDisabled`:\n\n```jsx live-dev\nconst App = () => (\n <FormField.Root isDisabled>\n <FormField.Label>Account Type</FormField.Label>\n <FormField.Input>\n <TextInput value=\"Premium (locked)\" readOnly />\n </FormField.Input>\n <FormField.Description>\n Contact support to change your account type\n </FormField.Description>\n </FormField.Root>\n);\n```\n\n### Read-only state\n\nDisplay values without allowing edits using `isReadOnly`:\n\n```jsx live-dev\nconst App = () => (\n <FormField.Root isReadOnly>\n <FormField.Label>User ID</FormField.Label>\n <FormField.Input>\n <TextInput value=\"user-12345-abcde\" readOnly />\n </FormField.Input>\n <FormField.Description>\n Your unique user identifier (cannot be changed)\n </FormField.Description>\n </FormField.Root>\n);\n```\n\n### Field descriptions\n\nProvide helpful context with description text that's automatically linked for screen readers:\n\n```jsx live-dev\nconst App = () => (\n <Stack direction=\"column\" gap=\"600\">\n <FormField.Root>\n <FormField.Label>Password</FormField.Label>\n <FormField.Input>\n <PasswordInput placeholder=\"Enter password\" />\n </FormField.Input>\n <FormField.Description>\n Must be at least 8 characters with uppercase, lowercase, and numbers\n </FormField.Description>\n </FormField.Root>\n\n <FormField.Root>\n <FormField.Label>Confirm Password</FormField.Label>\n <FormField.Input>\n <PasswordInput placeholder=\"Re-enter password\" />\n </FormField.Input>\n <FormField.Description>\n Enter the same password for verification\n </FormField.Description>\n </FormField.Root>\n </Stack>\n);\n```\n\n### InfoBox for contextual help\n\nAdd an info icon with a popover for additional field context:\n\n```jsx live-dev\nconst App = () => (\n <FormField.Root>\n <FormField.Label>API Key</FormField.Label>\n <FormField.InfoBox>\n <Stack direction=\"column\" gap=\"300\" padding=\"400\">\n <Text fontWeight=\"500\">About API Keys</Text>\n <Text>\n Your API key can be found in your account settings under \"Developer Tools\".\n Keep it secure and never share it publicly or commit it to version control.\n </Text>\n <Text>\n If you believe your key has been compromised, regenerate it immediately\n from your account settings.\n </Text>\n </Stack>\n </FormField.InfoBox>\n <FormField.Input>\n <TextInput placeholder=\"sk_live_...\" type=\"password\" />\n </FormField.Input>\n <FormField.Description>\n Used for API authentication\n </FormField.Description>\n </FormField.Root>\n);\n```\n\n### With different input types\n\nFormField works with any input component:\n\n```jsx live-dev\nconst App = () => (\n <Stack direction=\"column\" gap=\"600\">\n <FormField.Root>\n <FormField.Label>Full Name</FormField.Label>\n <FormField.Input>\n <TextInput placeholder=\"John Doe\" />\n </FormField.Input>\n </FormField.Root>\n\n <FormField.Root>\n <FormField.Label>Age</FormField.Label>\n <FormField.Input>\n <NumberInput placeholder=\"25\" min={0} max={120} />\n </FormField.Input>\n </FormField.Root>\n\n <FormField.Root>\n <FormField.Label>Country</FormField.Label>\n <FormField.Input>\n <Select.Root>\n <Select.Options placeholder=\"Select your country\">\n <Select.Option id=\"us\">United States</Select.Option>\n <Select.Option id=\"uk\">United Kingdom</Select.Option>\n <Select.Option id=\"ca\">Canada</Select.Option>\n <Select.Option id=\"au\">Australia</Select.Option>\n </Select.Options>\n </Select.Root>\n </FormField.Input>\n </FormField.Root>\n\n <FormField.Root>\n <FormField.Label>Bio</FormField.Label>\n <FormField.Input>\n <MultilineTextInput placeholder=\"Tell us about yourself...\" />\n </FormField.Input>\n </FormField.Root>\n </Stack>\n);\n```\n\n## Component requirements\n\n## Accessibility\n\nFormField implements comprehensive accessibility features through React Aria's `useField` hook, automatically managing ARIA attributes for all child components.\n\n#### Role\n\n- The root container uses appropriate semantic HTML structure\n- Input elements receive proper roles from their respective components\n- Label associations are automatic via React Aria\n\n#### Labeling\n\n- **Automatic label association**: `FormField.Label` automatically links to the input via `aria-labelledby`\n- **Required indicator**: Visual asterisk and `aria-required=\"true\"` when `isRequired={true}`\n- **Description linking**: `FormField.Description` automatically links via `aria-describedby`\n- **Error linking**: `FormField.Error` automatically links via `aria-errormessage` when `isInvalid={true}`\n- **InfoBox accessibility**: InfoBox trigger has appropriate `aria-label` and popover role\n\n#### Keyboard navigation\n\nFormField itself doesn't handle keyboard interaction - navigation is managed by the input components it contains. The InfoBox trigger supports standard button keyboard interaction:\n\n| Key | Action |\n|-----|--------|\n| `Tab` | Move focus to/from InfoBox trigger |\n| `Enter` / `Space` | Open InfoBox popover |\n| `Escape` | Close InfoBox popover (when open) |\n\nStandard keyboard navigation for input elements applies based on the input type used within `FormField.Input`.\n\n#### Persistent ID\n\nIf your use case requires tracking and analytics for this component, it is good practice to add a **persistent**, **unique** `id` to the component:\n\n```tsx\n<FormField.Root id=\"user-email-field\">\n <FormField.Label>Email Address</FormField.Label>\n <FormField.Input>\n <TextInput />\n </FormField.Input>\n</FormField.Root>\n```\n\nThe `id` is used by React Aria to generate consistent IDs for all child elements, ensuring proper accessibility attribute relationships.\n\n## API reference\n\n<PropsTable id=\"FormField\" />\n\n## Common patterns\n\n### Complete form with validation\n\nA realistic login form with validation and state management:\n\n```jsx live-dev\nconst App = () => {\n const [formData, setFormData] = React.useState({\n email: '',\n password: ''\n });\n const [errors, setErrors] = React.useState({});\n const [touched, setTouched] = React.useState({});\n\n const validate = () => {\n const newErrors = {};\n\n if (!formData.email) {\n newErrors.email = 'Email is required';\n } else if (!/^[A-Z0-9._%+-]+@[A-Z0-9.-]+\\.[A-Z]{2,}$/i.test(formData.email)) {\n newErrors.email = 'Invalid email address';\n }\n\n if (!formData.password) {\n newErrors.password = 'Password is required';\n } else if (formData.password.length < 8) {\n newErrors.password = 'Password must be at least 8 characters';\n }\n\n setErrors(newErrors);\n return Object.keys(newErrors).length === 0;\n };\n\n const handleSubmit = () => {\n setTouched({ email: true, password: true });\n if (validate()) {\n console.log('Form submitted:', formData);\n }\n };\n\n return (\n <Stack direction=\"column\" gap=\"500\">\n <FormField.Root\n isRequired\n isInvalid={!!(errors.email && touched.email)}\n >\n <FormField.Label>Email Address</FormField.Label>\n <FormField.Input>\n <TextInput\n type=\"email\"\n value={formData.email}\n onChange={(value) => setFormData({ ...formData, email: value })}\n onBlur={() => setTouched({ ...touched, email: true })}\n placeholder=\"your@email.com\"\n />\n </FormField.Input>\n <FormField.Error>{errors.email}</FormField.Error>\n </FormField.Root>\n\n <FormField.Root\n isRequired\n isInvalid={!!(errors.password && touched.password)}\n >\n <FormField.Label>Password</FormField.Label>\n <FormField.Input>\n <PasswordInput\n value={formData.password}\n onChange={(value) => setFormData({ ...formData, password: value })}\n onBlur={() => setTouched({ ...touched, password: true })}\n placeholder=\"Enter password\"\n />\n </FormField.Input>\n <FormField.Description>Minimum 8 characters</FormField.Description>\n <FormField.Error>{errors.password}</FormField.Error>\n </FormField.Root>\n\n <Button onClick={handleSubmit}>Log In</Button>\n\n <Text fontSize=\"300\" color=\"neutral.11\">\n Email: {formData.email || '(empty)'} | Password length: {formData.password.length}\n </Text>\n </Stack>\n );\n};\n```\n\n### Multi-step form with validation\n\nBuild multi-step forms with per-step validation:\n\n```jsx live-dev\nconst App = () => {\n const [step, setStep] = React.useState('personal');\n const [formData, setFormData] = React.useState({\n firstName: '',\n lastName: '',\n email: '',\n password: '',\n notifications: true\n });\n const [errors, setErrors] = React.useState({});\n const [touched, setTouched] = React.useState({});\n\n const validateStep = (currentStep) => {\n const newErrors = {};\n\n if (currentStep === 'personal') {\n if (!formData.firstName) newErrors.firstName = 'First name is required';\n if (!formData.lastName) newErrors.lastName = 'Last name is required';\n } else if (currentStep === 'account') {\n if (!formData.email) newErrors.email = 'Email is required';\n if (!formData.password) newErrors.password = 'Password is required';\n else if (formData.password.length < 8) {\n newErrors.password = 'Password must be at least 8 characters';\n }\n }\n\n setErrors(newErrors);\n return Object.keys(newErrors).length === 0;\n };\n\n const handleNext = () => {\n if (validateStep(step)) {\n if (step === 'personal') setStep('account');\n else if (step === 'account') setStep('preferences');\n }\n };\n\n const handleBack = () => {\n if (step === 'account') setStep('personal');\n else if (step === 'preferences') setStep('account');\n };\n\n const handleSubmit = () => {\n if (validateStep(step)) {\n console.log('Form submitted:', formData);\n }\n };\n\n return (\n <Stack direction=\"column\" gap=\"500\">\n <Text fontWeight=\"500\" fontSize=\"400\">\n Step {step === 'personal' ? '1' : step === 'account' ? '2' : '3'} of 3: {\n step === 'personal' ? 'Personal Info' :\n step === 'account' ? 'Account Details' :\n 'Preferences'\n }\n </Text>\n\n {step === 'personal' && (\n <>\n <FormField.Root\n isRequired\n isInvalid={!!(errors.firstName && touched.firstName)}\n >\n <FormField.Label>First Name</FormField.Label>\n <FormField.Input>\n <TextInput\n value={formData.firstName}\n onChange={(value) => setFormData({ ...formData, firstName: value })}\n onBlur={() => setTouched({ ...touched, firstName: true })}\n />\n </FormField.Input>\n <FormField.Error>{errors.firstName}</FormField.Error>\n </FormField.Root>\n\n <FormField.Root\n isRequired\n isInvalid={!!(errors.lastName && touched.lastName)}\n >\n <FormField.Label>Last Name</FormField.Label>\n <FormField.Input>\n <TextInput\n value={formData.lastName}\n onChange={(value) => setFormData({ ...formData, lastName: value })}\n onBlur={() => setTouched({ ...touched, lastName: true })}\n />\n </FormField.Input>\n <FormField.Error>{errors.lastName}</FormField.Error>\n </FormField.Root>\n </>\n )}\n\n {step === 'account' && (\n <>\n <FormField.Root\n isRequired\n isInvalid={!!(errors.email && touched.email)}\n >\n <FormField.Label>Email</FormField.Label>\n <FormField.Input>\n <TextInput\n type=\"email\"\n value={formData.email}\n onChange={(value) => setFormData({ ...formData, email: value })}\n onBlur={() => setTouched({ ...touched, email: true })}\n />\n </FormField.Input>\n <FormField.Error>{errors.email}</FormField.Error>\n </FormField.Root>\n\n <FormField.Root\n isRequired\n isInvalid={!!(errors.password && touched.password)}\n >\n <FormField.Label>Password</FormField.Label>\n <FormField.Input>\n <PasswordInput\n value={formData.password}\n onChange={(value) => setFormData({ ...formData, password: value })}\n onBlur={() => setTouched({ ...touched, password: true })}\n />\n </FormField.Input>\n <FormField.Description>Minimum 8 characters</FormField.Description>\n <FormField.Error>{errors.password}</FormField.Error>\n </FormField.Root>\n </>\n )}\n\n {step === 'preferences' && (\n <>\n <FormField.Root>\n <FormField.Label>Email Notifications</FormField.Label>\n <FormField.Input>\n <Checkbox\n isSelected={formData.notifications}\n onChange={(value) => setFormData({ ...formData, notifications: value })}\n >\n Send me product updates and newsletters\n </Checkbox>\n </FormField.Input>\n <FormField.Description>\n You can change this preference anytime in settings\n </FormField.Description>\n </FormField.Root>\n\n <Text fontSize=\"300\" color=\"neutral.11\">\n Review: {formData.firstName} {formData.lastName} ({formData.email})\n </Text>\n </>\n )}\n\n <Stack direction=\"row\" gap=\"300\">\n {step !== 'personal' && (\n <Button variant=\"outline\" onClick={handleBack}>\n Back\n </Button>\n )}\n {step !== 'preferences' ? (\n <Button onClick={handleNext}>Next</Button>\n ) : (\n <Button onClick={handleSubmit}>Submit</Button>\n )}\n </Stack>\n </Stack>\n );\n};\n```\n\n### Conditional field visibility\n\nShow or hide fields based on form state:\n\n```jsx live-dev\nconst App = () => {\n const [accountType, setAccountType] = React.useState('personal');\n const [needsShipping, setNeedsShipping] = React.useState(false);\n\n return (\n <Stack direction=\"column\" gap=\"500\">\n <FormField.Root>\n <FormField.Label>Account Type</FormField.Label>\n <FormField.Input>\n <Select.Root\n selectedKey={accountType}\n onSelectionChange={setAccountType}\n >\n <Select.Options placeholder=\"Select account type\">\n <Select.Option id=\"personal\">Personal</Select.Option>\n <Select.Option id=\"business\">Business</Select.Option>\n </Select.Options>\n </Select.Root>\n </FormField.Input>\n </FormField.Root>\n\n {accountType === 'business' && (\n <FormField.Root isRequired>\n <FormField.Label>Company Name</FormField.Label>\n <FormField.Input>\n <TextInput placeholder=\"Acme Corporation\" />\n </FormField.Input>\n <FormField.Description>\n Your registered business name\n </FormField.Description>\n </FormField.Root>\n )}\n\n <Checkbox\n isSelected={needsShipping}\n onChange={setNeedsShipping}\n >\n Ship to different address\n </Checkbox>\n\n {needsShipping && (\n <FormField.Root isRequired>\n <FormField.Label>Shipping Address</FormField.Label>\n <FormField.Input>\n <MultilineTextInput\n placeholder=\"123 Main St, City, State ZIP\"\n />\n </FormField.Input>\n </FormField.Root>\n )}\n </Stack>\n );\n};\n```\n\n### React 19 form state integration\n\nFormField integrates seamlessly with React 19's built-in form state features, including `useActionState` for progressive enhancement and server-side validation. This example demonstrates the standard React 19 pattern where validation occurs on form submission:\n\n```jsx live-dev\nconst App = () => {\n const [state, submitAction, isPending] = React.useActionState(\n async (previousState, formData) => {\n // Simulate async server-side validation\n await new Promise(resolve => setTimeout(resolve, 1000));\n\n const errors = {};\n const email = formData.get('email');\n const password = formData.get('password');\n\n if (!email) {\n errors.email = 'Email is required';\n } else if (!/^[A-Z0-9._%+-]+@[A-Z0-9.-]+\\.[A-Z]{2,}$/i.test(email)) {\n errors.email = 'Invalid email address';\n }\n\n if (!password) {\n errors.password = 'Password is required';\n } else if (password.length < 8) {\n errors.password = 'Password must be at least 8 characters';\n }\n\n if (Object.keys(errors).length > 0) {\n return { success: false, errors, data: null };\n }\n\n return {\n success: true,\n message: 'Login successful!',\n data: { email, password: '••••••••' },\n errors: {}\n };\n },\n { success: false, errors: {}, data: null }\n );\n\n return (\n <form action={submitAction} noValidate>\n <Stack direction=\"column\" gap=\"500\">\n <FormField.Root\n isRequired\n isInvalid={!!(state.errors && state.errors.email)}\n >\n <FormField.Label>Email Address</FormField.Label>\n <FormField.Input>\n <TextInput\n type=\"email\"\n name=\"email\"\n placeholder=\"your@email.com\"\n autoComplete=\"email\"\n />\n </FormField.Input>\n <FormField.Error>{state.errors?.email}</FormField.Error>\n </FormField.Root>\n\n <FormField.Root\n isRequired\n isInvalid={!!(state.errors && state.errors.password)}\n >\n <FormField.Label>Password</FormField.Label>\n <FormField.Input>\n <PasswordInput\n name=\"password\"\n placeholder=\"Enter password\"\n autoComplete=\"current-password\"\n />\n </FormField.Input>\n <FormField.Description>Minimum 8 characters</FormField.Description>\n <FormField.Error>{state.errors?.password}</FormField.Error>\n </FormField.Root>\n\n <Button type=\"submit\" isDisabled={isPending}>\n {isPending ? 'Logging in...' : 'Log In'}\n </Button>\n\n {state.success && state.data && (\n <Alert.Root colorPalette=\"positive\">\n <Alert.Title>{state.message}</Alert.Title>\n <Alert.Description>\n Email: {state.data.email}\n </Alert.Description>\n </Alert.Root>\n )}\n </Stack>\n </form>\n );\n};\n```\n\n## Testing your implementation\n\nThese examples demonstrate how to test your implementation when using FormField within your application. As the component's internal functionality is already tested by Nimbus, these patterns help you verify your integration and application-specific logic.\n\n### Basic Rendering Tests\n\nVerify FormField renders with all parts correctly structured\n\n```tsx\nimport { describe, it, expect } from \"vitest\";\nimport { render, screen } from \"@testing-library/react\";\nimport userEvent from \"@testing-library/user-event\";\nimport React from \"react\";\nimport { FormField, TextInput, NimbusProvider } from \"@commercetools/nimbus\";\n\ndescribe(\"FormField - Basic rendering\", () => {\n it(\"renders with label and input\", () => {\n render(\n <NimbusProvider>\n <FormField.Root>\n <FormField.Label>Username</FormField.Label>\n <FormField.Input>\n <TextInput placeholder=\"Enter username\" />\n </FormField.Input>\n </FormField.Root>\n </NimbusProvider>\n );\n\n expect(screen.getByText(\"Username\")).toBeInTheDocument();\n expect(screen.getByPlaceholderText(\"Enter username\")).toBeInTheDocument();\n });\n\n it(\"renders with description\", () => {\n render(\n <NimbusProvider>\n <FormField.Root>\n <FormField.Label>Password</FormField.Label>\n <FormField.Input>\n <TextInput type=\"password\" />\n </FormField.Input>\n <FormField.Description>\n Must be at least 8 characters\n </FormField.Description>\n </FormField.Root>\n </NimbusProvider>\n );\n\n expect(\n screen.getByText(\"Must be at least 8 characters\")\n ).toBeInTheDocument();\n });\n\n it(\"renders with all parts\", () => {\n render(\n <NimbusProvider>\n <FormField.Root isInvalid>\n <FormField.Label>Email</FormField.Label>\n <FormField.Input>\n <TextInput type=\"email\" />\n </FormField.Input>\n <FormField.Description>Your contact email</FormField.Description>\n <FormField.Error>Invalid email format</FormField.Error>\n </FormField.Root>\n </NimbusProvider>\n );\n\n expect(screen.getByText(\"Email\")).toBeInTheDocument();\n expect(screen.getByText(\"Your contact email\")).toBeInTheDocument();\n expect(screen.getByText(\"Invalid email format\")).toBeInTheDocument();\n });\n});\n```\n\n### Accessibility Tests\n\nVerify ARIA attributes and label associations\n\n```tsx\nimport { describe, it, expect } from \"vitest\";\nimport { render, screen } from \"@testing-library/react\";\nimport userEvent from \"@testing-library/user-event\";\nimport React from \"react\";\nimport { FormField, TextInput, NimbusProvider } from \"@commercetools/nimbus\";\n\ndescribe(\"FormField - Accessibility\", () => {\n it(\"associates label with input via aria-labelledby\", () => {\n render(\n <NimbusProvider>\n <FormField.Root>\n <FormField.Label>Username</FormField.Label>\n <FormField.Input>\n <TextInput />\n </FormField.Input>\n </FormField.Root>\n </NimbusProvider>\n );\n\n const input = screen.getByRole(\"textbox\");\n const label = screen.getByText(\"Username\");\n\n expect(input).toHaveAttribute(\"aria-labelledby\", label.id);\n });\n\n it(\"associates description with input via aria-describedby\", () => {\n render(\n <NimbusProvider>\n <FormField.Root>\n <FormField.Label>Username</FormField.Label>\n <FormField.Input>\n <TextInput />\n </FormField.Input>\n <FormField.Description>\n Must be at least 8 characters\n </FormField.Description>\n </FormField.Root>\n </NimbusProvider>\n );\n\n const input = screen.getByRole(\"textbox\");\n const description = screen.getByText(\"Must be at least 8 characters\");\n\n expect(input.getAttribute(\"aria-describedby\")).toContain(description.id);\n });\n\n it(\"marks input as required when isRequired is true\", () => {\n render(\n <NimbusProvider>\n <FormField.Root isRequired>\n <FormField.Label>Email</FormField.Label>\n <FormField.Input>\n <TextInput type=\"email\" />\n </FormField.Input>\n </FormField.Root>\n </NimbusProvider>\n );\n\n const input = screen.getByRole(\"textbox\");\n expect(input).toHaveAttribute(\"aria-required\", \"true\");\n });\n\n it(\"marks input as invalid when isInvalid is true\", () => {\n render(\n <NimbusProvider>\n <FormField.Root isInvalid>\n <FormField.Label>Email</FormField.Label>\n <FormField.Input>\n <TextInput type=\"email\" />\n </FormField.Input>\n <FormField.Error>Invalid email</FormField.Error>\n </FormField.Root>\n </NimbusProvider>\n );\n\n const input = screen.getByRole(\"textbox\");\n expect(input).toHaveAttribute(\"aria-invalid\", \"true\");\n });\n});\n```\n\n### Size Variants\n\nTest different size variants\n\n```tsx\nimport { describe, it, expect } from \"vitest\";\nimport { render, screen } from \"@testing-library/react\";\nimport userEvent from \"@testing-library/user-event\";\nimport React from \"react\";\nimport { FormField, TextInput, NimbusProvider } from \"@commercetools/nimbus\";\n\ndescribe(\"FormField - Size variants\", () => {\n it(\"renders small size\", () => {\n render(\n <NimbusProvider>\n <FormField.Root size=\"sm\">\n <FormField.Label>Small Field</FormField.Label>\n <FormField.Input>\n <TextInput />\n </FormField.Input>\n </FormField.Root>\n </NimbusProvider>\n );\n\n expect(screen.getByText(\"Small Field\")).toBeInTheDocument();\n });\n\n it(\"renders medium size (default)\", () => {\n render(\n <NimbusProvider>\n <FormField.Root size=\"md\">\n <FormField.Label>Medium Field</FormField.Label>\n <FormField.Input>\n <TextInput />\n </FormField.Input>\n </FormField.Root>\n </NimbusProvider>\n );\n\n expect(screen.getByText(\"Medium Field\")).toBeInTheDocument();\n });\n});\n```\n\n### Layout Direction\n\nTest column and row layout directions\n\n```tsx\nimport { describe, it, expect } from \"vitest\";\nimport { render, screen } from \"@testing-library/react\";\nimport userEvent from \"@testing-library/user-event\";\nimport React from \"react\";\nimport { FormField, TextInput, NimbusProvider } from \"@commercetools/nimbus\";\n\ndescribe(\"FormField - Layout direction\", () => {\n it(\"renders with column direction (default)\", () => {\n render(\n <NimbusProvider>\n <FormField.Root direction=\"column\">\n <FormField.Label>Column Layout</FormField.Label>\n <FormField.Input>\n <TextInput />\n </FormField.Input>\n </FormField.Root>\n </NimbusProvider>\n );\n\n expect(screen.getByText(\"Column Layout\")).toBeInTheDocument();\n });\n\n it(\"renders with row direction\", () => {\n render(\n <NimbusProvider>\n <FormField.Root direction=\"row\">\n <FormField.Label>Row Layout</FormField.Label>\n <FormField.Input>\n <TextInput />\n </FormField.Input>\n </FormField.Root>\n </NimbusProvider>\n );\n\n expect(screen.getByText(\"Row Layout\")).toBeInTheDocument();\n });\n});\n```\n\n### Component States\n\nTest required, invalid, disabled, and read-only states\n\n```tsx\nimport { describe, it, expect } from \"vitest\";\nimport { render, screen } from \"@testing-library/react\";\nimport userEvent from \"@testing-library/user-event\";\nimport React from \"react\";\nimport { FormField, TextInput, NimbusProvider } from \"@commercetools/nimbus\";\n\ndescribe(\"FormField - States\", () => {\n it(\"displays required indicator\", () => {\n render(\n <NimbusProvider>\n <FormField.Root isRequired>\n <FormField.Label>Required Field</FormField.Label>\n <FormField.Input>\n <TextInput />\n </FormField.Input>\n </FormField.Root>\n </NimbusProvider>\n );\n\n const input = screen.getByRole(\"textbox\");\n expect(input).toHaveAttribute(\"aria-required\", \"true\");\n });\n\n it(\"displays error when invalid\", () => {\n render(\n <NimbusProvider>\n <FormField.Root isInvalid>\n <FormField.Label>Email</FormField.Label>\n <FormField.Input>\n <TextInput type=\"email\" />\n </FormField.Input>\n <FormField.Error>Please enter a valid email</FormField.Error>\n </FormField.Root>\n </NimbusProvider>\n );\n\n expect(screen.getByText(\"Please enter a valid email\")).toBeInTheDocument();\n const input = screen.getByRole(\"textbox\");\n expect(input).toHaveAttribute(\"aria-invalid\", \"true\");\n });\n\n it(\"disables input when isDisabled is true\", () => {\n render(\n <NimbusProvider>\n <FormField.Root isDisabled>\n <FormField.Label>Disabled Field</FormField.Label>\n <FormField.Input>\n <TextInput />\n </FormField.Input>\n </FormField.Root>\n </NimbusProvider>\n );\n\n const input = screen.getByRole(\"textbox\");\n expect(input).toBeDisabled();\n });\n\n it(\"makes input read-only when isReadOnly is true\", () => {\n render(\n <NimbusProvider>\n <FormField.Root isReadOnly>\n <FormField.Label>Read-only Field</FormField.Label>\n <FormField.Input>\n <TextInput value=\"Cannot edit\" />\n </FormField.Input>\n </FormField.Root>\n </NimbusProvider>\n );\n\n const input = screen.getByRole(\"textbox\");\n expect(input).toHaveAttribute(\"readonly\");\n });\n});\n```\n\n### Error Visibility\n\nTest that errors only show when isInvalid is true\n\n```tsx\nimport { describe, it, expect } from \"vitest\";\nimport { render, screen } from \"@testing-library/react\";\nimport userEvent from \"@testing-library/user-event\";\nimport React from \"react\";\nimport { FormField, TextInput, NimbusProvider } from \"@commercetools/nimbus\";\n\ndescribe(\"FormField - Error visibility\", () => {\n it(\"hides error when isInvalid is false\", () => {\n render(\n <NimbusProvider>\n <FormField.Root isInvalid={false}>\n <FormField.Label>Email</FormField.Label>\n <FormField.Input>\n <TextInput type=\"email\" />\n </FormField.Input>\n <FormField.Error>This should be hidden</FormField.Error>\n </FormField.Root>\n </NimbusProvider>\n );\n\n expect(screen.queryByText(\"This should be hidden\")).not.toBeInTheDocument();\n });\n\n it(\"shows error when isInvalid is true\", () => {\n render(\n <NimbusProvider>\n <FormField.Root isInvalid={true}>\n <FormField.Label>Email</FormField.Label>\n <FormField.Input>\n <TextInput type=\"email\" />\n </FormField.Input>\n <FormField.Error>This should be visible</FormField.Error>\n </FormField.Root>\n </NimbusProvider>\n );\n\n expect(screen.getByText(\"This should be visible\")).toBeInTheDocument();\n });\n});\n```\n\n### User Interactions\n\nTest user input and validation flows\n\n```tsx\nimport { describe, it, expect } from \"vitest\";\nimport { render, screen } from \"@testing-library/react\";\nimport userEvent from \"@testing-library/user-event\";\nimport React from \"react\";\nimport { FormField, TextInput, NimbusProvider } from \"@commercetools/nimbus\";\n\ndescribe(\"FormField - User interactions\", () => {\n it(\"handles user input\", async () => {\n const user = userEvent.setup();\n\n render(\n <NimbusProvider>\n <FormField.Root>\n <FormField.Label>Username</FormField.Label>\n <FormField.Input>\n <TextInput placeholder=\"Enter username\" />\n </FormField.Input>\n </FormField.Root>\n </NimbusProvider>\n );\n\n const input = screen.getByRole(\"textbox\");\n await user.type(input, \"testuser\");\n\n expect(input).toHaveValue(\"testuser\");\n });\n\n it(\"supports validation on blur\", async () => {\n const user = userEvent.setup();\n\n const TestComponent = () => {\n const [invalid, setInvalid] = React.useState(false);\n const [value, setValue] = React.useState(\"\");\n\n const handleChange = (newValue: string) => {\n setValue(newValue);\n };\n\n const handleBlur = () => {\n setInvalid(value.length < 3);\n };\n\n return (\n <NimbusProvider>\n <FormField.Root isInvalid={invalid}>\n <FormField.Label>Username</FormField.Label>\n <FormField.Input>\n <TextInput\n value={value}\n onChange={handleChange}\n onBlur={handleBlur}\n />\n </FormField.Input>\n <FormField.Error>Must be at least 3 characters</FormField.Error>\n </FormField.Root>\n </NimbusProvider>\n );\n };\n\n render(<TestComponent />);\n\n const input = screen.getByRole(\"textbox\");\n await user.type(input, \"ab\");\n await user.tab(); // Blur the input\n\n expect(\n screen.getByText(\"Must be at least 3 characters\")\n ).toBeInTheDocument();\n });\n});\n```\n\n### InfoBox Functionality\n\nTest InfoBox popover interactions\n\n```tsx\nimport { describe, it, expect } from \"vitest\";\nimport { render, screen } from \"@testing-library/react\";\nimport userEvent from \"@testing-library/user-event\";\nimport React from \"react\";\nimport { FormField, TextInput, NimbusProvider } from \"@commercetools/nimbus\";\n\ndescribe(\"FormField - InfoBox\", () => {\n it(\"renders InfoBox trigger when InfoBox is provided\", () => {\n render(\n <NimbusProvider>\n <FormField.Root>\n <FormField.Label>API Key</FormField.Label>\n <FormField.InfoBox>\n Additional information about this field\n </FormField.InfoBox>\n <FormField.Input>\n <TextInput />\n </FormField.Input>\n </FormField.Root>\n </NimbusProvider>\n );\n\n // InfoBox trigger button should be present (help icon)\n const buttons = screen.getAllByRole(\"button\");\n expect(buttons.length).toBeGreaterThan(0);\n });\n\n it(\"shows InfoBox content when trigger is clicked\", async () => {\n const user = userEvent.setup();\n\n render(\n <NimbusProvider>\n <FormField.Root>\n <FormField.Label>API Key</FormField.Label>\n <FormField.InfoBox>\n Your API key is sensitive information\n </FormField.InfoBox>\n <FormField.Input>\n <TextInput />\n </FormField.Input>\n </FormField.Root>\n </NimbusProvider>\n );\n\n // Click the help icon button\n const helpButton = screen.getAllByRole(\"button\")[0];\n await user.click(helpButton);\n\n // Wait for popover content\n await screen.findByText(\"Your API key is sensitive information\");\n expect(\n screen.getByText(\"Your API key is sensitive information\")\n ).toBeInTheDocument();\n });\n});\n```\n\n\n## Resources\n\n- [Storybook - FormField](https://nimbus-storybook.vercel.app/?path=/docs/components-formfield--docs)\n- [React Aria - useField](https://react-spectrum.adobe.com/react-aria/useField.html) - Underlying accessibility implementation\n",
359
+ "toc": [
360
+ {
361
+ "value": "Getting started",
362
+ "href": "#getting-started",
363
+ "depth": 2,
364
+ "numbering": [
365
+ 1,
366
+ 1
367
+ ],
368
+ "parent": "root"
369
+ },
370
+ {
371
+ "value": "Import",
372
+ "href": "#import",
373
+ "depth": 3,
374
+ "numbering": [
375
+ 1,
376
+ 1,
377
+ 1
378
+ ],
379
+ "parent": "root"
380
+ },
381
+ {
382
+ "value": "Basic usage",
383
+ "href": "#basic-usage",
384
+ "depth": 3,
385
+ "numbering": [
386
+ 1,
387
+ 1,
388
+ 2
389
+ ],
390
+ "parent": "root"
391
+ },
392
+ {
393
+ "value": "Usage examples",
394
+ "href": "#usage-examples",
395
+ "depth": 2,
396
+ "numbering": [
397
+ 1,
398
+ 2
399
+ ],
400
+ "parent": "root"
401
+ },
402
+ {
403
+ "value": "Size options",
404
+ "href": "#size-options",
405
+ "depth": 3,
406
+ "numbering": [
407
+ 1,
408
+ 2,
409
+ 1
410
+ ],
411
+ "parent": "root"
412
+ },
413
+ {
414
+ "value": "Layout direction",
415
+ "href": "#layout-direction",
416
+ "depth": 3,
417
+ "numbering": [
418
+ 1,
419
+ 2,
420
+ 2
421
+ ],
422
+ "parent": "root"
423
+ },
424
+ {
425
+ "value": "Required fields",
426
+ "href": "#required-fields",
427
+ "depth": 3,
428
+ "numbering": [
429
+ 1,
430
+ 2,
431
+ 3
432
+ ],
433
+ "parent": "root"
434
+ },
435
+ {
436
+ "value": "Validation errors",
437
+ "href": "#validation-errors",
438
+ "depth": 3,
439
+ "numbering": [
440
+ 1,
441
+ 2,
442
+ 4
443
+ ],
444
+ "parent": "root"
445
+ },
446
+ {
447
+ "value": "Disabled state",
448
+ "href": "#disabled-state",
449
+ "depth": 3,
450
+ "numbering": [
451
+ 1,
452
+ 2,
453
+ 5
454
+ ],
455
+ "parent": "root"
456
+ },
457
+ {
458
+ "value": "Read-only state",
459
+ "href": "#read-only-state",
460
+ "depth": 3,
461
+ "numbering": [
462
+ 1,
463
+ 2,
464
+ 6
465
+ ],
466
+ "parent": "root"
467
+ },
468
+ {
469
+ "value": "Field descriptions",
470
+ "href": "#field-descriptions",
471
+ "depth": 3,
472
+ "numbering": [
473
+ 1,
474
+ 2,
475
+ 7
476
+ ],
477
+ "parent": "root"
478
+ },
479
+ {
480
+ "value": "InfoBox for contextual help",
481
+ "href": "#infobox-for-contextual-help",
482
+ "depth": 3,
483
+ "numbering": [
484
+ 1,
485
+ 2,
486
+ 8
487
+ ],
488
+ "parent": "root"
489
+ },
490
+ {
491
+ "value": "With different input types",
492
+ "href": "#with-different-input-types",
493
+ "depth": 3,
494
+ "numbering": [
495
+ 1,
496
+ 2,
497
+ 9
498
+ ],
499
+ "parent": "root"
500
+ },
501
+ {
502
+ "value": "Component requirements",
503
+ "href": "#component-requirements",
504
+ "depth": 2,
505
+ "numbering": [
506
+ 1,
507
+ 3
508
+ ],
509
+ "parent": "root"
510
+ },
511
+ {
512
+ "value": "Accessibility",
513
+ "href": "#accessibility",
514
+ "depth": 2,
515
+ "numbering": [
516
+ 1,
517
+ 4
518
+ ],
519
+ "parent": "root"
520
+ },
521
+ {
522
+ "value": "Role",
523
+ "href": "#role",
524
+ "depth": 4,
525
+ "numbering": [
526
+ 1,
527
+ 4,
528
+ 1,
529
+ 1
530
+ ],
531
+ "parent": "root"
532
+ },
533
+ {
534
+ "value": "Labeling",
535
+ "href": "#labeling",
536
+ "depth": 4,
537
+ "numbering": [
538
+ 1,
539
+ 4,
540
+ 1,
541
+ 2
542
+ ],
543
+ "parent": "root"
544
+ },
545
+ {
546
+ "value": "Keyboard navigation",
547
+ "href": "#keyboard-navigation",
548
+ "depth": 4,
549
+ "numbering": [
550
+ 1,
551
+ 4,
552
+ 1,
553
+ 3
554
+ ],
555
+ "parent": "root"
556
+ },
557
+ {
558
+ "value": "Persistent ID",
559
+ "href": "#persistent-id",
560
+ "depth": 4,
561
+ "numbering": [
562
+ 1,
563
+ 4,
564
+ 1,
565
+ 4
566
+ ],
567
+ "parent": "root"
568
+ },
569
+ {
570
+ "value": "API reference",
571
+ "href": "#api-reference",
572
+ "depth": 2,
573
+ "numbering": [
574
+ 1,
575
+ 5
576
+ ],
577
+ "parent": "root"
578
+ },
579
+ {
580
+ "value": "Common patterns",
581
+ "href": "#common-patterns",
582
+ "depth": 2,
583
+ "numbering": [
584
+ 1,
585
+ 6
586
+ ],
587
+ "parent": "root"
588
+ },
589
+ {
590
+ "value": "Complete form with validation",
591
+ "href": "#complete-form-with-validation",
592
+ "depth": 3,
593
+ "numbering": [
594
+ 1,
595
+ 6,
596
+ 1
597
+ ],
598
+ "parent": "root"
599
+ },
600
+ {
601
+ "value": "Multi-step form with validation",
602
+ "href": "#multi-step-form-with-validation",
603
+ "depth": 3,
604
+ "numbering": [
605
+ 1,
606
+ 6,
607
+ 2
608
+ ],
609
+ "parent": "root"
610
+ },
611
+ {
612
+ "value": "Conditional field visibility",
613
+ "href": "#conditional-field-visibility",
614
+ "depth": 3,
615
+ "numbering": [
616
+ 1,
617
+ 6,
618
+ 3
619
+ ],
620
+ "parent": "root"
621
+ },
622
+ {
623
+ "value": "React 19 form state integration",
624
+ "href": "#react-19-form-state-integration",
625
+ "depth": 3,
626
+ "numbering": [
627
+ 1,
628
+ 6,
629
+ 4
630
+ ],
631
+ "parent": "root"
632
+ },
633
+ {
634
+ "value": "Testing your implementation",
635
+ "href": "#testing-your-implementation",
636
+ "depth": 2,
637
+ "numbering": [
638
+ 1,
639
+ 7
640
+ ],
641
+ "parent": "root"
642
+ },
643
+ {
644
+ "value": "Basic Rendering Tests",
645
+ "href": "#basic-rendering-tests",
646
+ "depth": 3,
647
+ "numbering": [
648
+ 1,
649
+ 7,
650
+ 1
651
+ ],
652
+ "parent": "root"
653
+ },
654
+ {
655
+ "value": "Accessibility Tests",
656
+ "href": "#accessibility-tests",
657
+ "depth": 3,
658
+ "numbering": [
659
+ 1,
660
+ 7,
661
+ 2
662
+ ],
663
+ "parent": "root"
664
+ },
665
+ {
666
+ "value": "Size Variants",
667
+ "href": "#size-variants",
668
+ "depth": 3,
669
+ "numbering": [
670
+ 1,
671
+ 7,
672
+ 3
673
+ ],
674
+ "parent": "root"
675
+ },
676
+ {
677
+ "value": "Layout Direction",
678
+ "href": "#layout-direction-1",
679
+ "depth": 3,
680
+ "numbering": [
681
+ 1,
682
+ 7,
683
+ 4
684
+ ],
685
+ "parent": "root"
686
+ },
687
+ {
688
+ "value": "Component States",
689
+ "href": "#component-states",
690
+ "depth": 3,
691
+ "numbering": [
692
+ 1,
693
+ 7,
694
+ 5
695
+ ],
696
+ "parent": "root"
697
+ },
698
+ {
699
+ "value": "Error Visibility",
700
+ "href": "#error-visibility",
701
+ "depth": 3,
702
+ "numbering": [
703
+ 1,
704
+ 7,
705
+ 6
706
+ ],
707
+ "parent": "root"
708
+ },
709
+ {
710
+ "value": "User Interactions",
711
+ "href": "#user-interactions",
712
+ "depth": 3,
713
+ "numbering": [
714
+ 1,
715
+ 7,
716
+ 7
717
+ ],
718
+ "parent": "root"
719
+ },
720
+ {
721
+ "value": "InfoBox Functionality",
722
+ "href": "#infobox-functionality",
723
+ "depth": 3,
724
+ "numbering": [
725
+ 1,
726
+ 7,
727
+ 8
728
+ ],
729
+ "parent": "root"
730
+ },
731
+ {
732
+ "value": "Resources",
733
+ "href": "#resources",
734
+ "depth": 2,
735
+ "numbering": [
736
+ 1,
737
+ 8
738
+ ],
739
+ "parent": "root"
740
+ }
741
+ ]
742
+ },
743
+ "guidelines": {
744
+ "mdx": "\n## Guidelines\n\nDesign guidelines offer a set of standardized rules and recommendations that\nensure consistency, usability, and accessibility across all design elements and\ninteractions.\n\nRelated guidelines [text-fields](#).\n\n### Best practices\n\n- **Clarity and simplicity:**\n - Minimize the number of fields. Only ask for essential information.\n - Use clear, concise labels that accurately describe the required input.\n - Choose what position (top or left) the labels will be and make it consistent\n in the area to help with scanning.\n- **Labels:**\n - Place labels above or to the left of input fields.\n - Keep labels short and descriptive.\n - Avoid using placeholders as labels.\n- **Error handling:**\n - Display error messages clearly and prominently.\n - Use specific and helpful error messages and provide suggestions for\n correcting errors.\n\n#### Labels\n\nFor label text, use a short, catch-all description (1-3 words) of the\ninformation that a user needs to provide. Label text that gets too long can be\noverwhelming and distracting, especially in complex interactions and long forms.\nSupplementary information or requirements about what to input can be shown in\nhelp text below the field, or in a tooltip.\n\n- **Use sentence case:** This follows our consistent style, unless statement\n contains words that are branded proper nouns.\n- **Don’t add a colon (:) at the end of a field label:** The design of the\n component already communicates the relationship between the label and the\n input field.\n- **Use clear and concise language:** Try to keep labels to 1-3 words. Avoid\n jargon or technical terms that the user might not understand.\n- **Be specific, brief, and descriptive:** Ensure labels are easily scannable\n and reflect the function of the element. If you need instructional text, use a\n helper label beneath.\n- **Avoid ambiguity:** Labels should leave no room for misinterpretation.\n- **Internalization friendly:** Be aware that translation lengthens by 20% on\n average, but also avoid creating a sentence using the label combined with the\n response from a user. (e.g., Label: My favorite color is... Response...Green.\n Sentence structures between languages vary greatly.)\n\n### Helper text vs info icon\n\nUse the right informative tool to aid your user to understand what is needed.\nSee [info button](#) for more guidelines.\n\n- **Info Button:**\n - **Complex or lengthy information:** When you need to provide more than a\n short sentence or two of explanation. By default the info button will open a\n dialog overlay. It can be used to show a tooltip on hover, but the amount of\n information a popover and a help text can contain is similar. If there is a\n want to simplify the UI, this can be used, but test to make sure that this\n information needs to be shown without interaction from a user.\n - **Progressive disclosure:** To avoid cluttering the form with too much text\n upfront, revealing details only when the user actively seeks them.\n - **Contextual help:** When the help information is very specific to a\n particular field or a user's current state within the form.  \n- **Help Text:**\n - **Short, concise explanations:** For simple clarifications or hints about\n the expected input. Try to keep helper text below 150 characters.\n - **Formatting guidance:** To provide examples of the required format (e.g.,\n date formats, phone number patterns).\n - **Input requirements:** To specify character limits, password rules, or\n other constraints.\n - **Immediate visibility:** When it's crucial for the user to see the guidance\n without any extra action like a click or a hover to display.\n\n### Usage\n\nBe sure to give enough information to the user to understand the form without\nbeing overwhelmed. Prioritize clarity and function over personality and over\nexplanation. To increase understanding, test your forms with users to understand\nwhere confusion might occur.\n\n### Formatting\n\nBe consistent with your use of form fields label placements and size.\n\n> [!TIP]\\\n> **Do**\n>\n> - Have one placement for labels in the same form, and consistently choose one\n> size for the entire form.\n> - Help text is used to show the user what the accepted formatting will be.\n> Placeholder text can be used when needed but help text is preferred for\n> accessibility.\n> - OK to capitalize proper nouns in labels instead of using sentence case.\n\n```jsx live\nconst App = () => (\n <Stack gap=\"400\">\n <FormField.Root isRequired>\n <FormField.Label>First name</FormField.Label>\n <FormField.Input>\n <TextInput width=\"9600\" />\n </FormField.Input>\n </FormField.Root>\n <FormField.Root isRequired>\n <FormField.Label>Social Security Number</FormField.Label>\n <FormField.Input>\n <TextInput width=\"9600\" />\n </FormField.Input>\n <FormField.Description>\n Format: XXX-XX-XXXX\n </FormField.Description>\n <FormField.InfoBox>\n Info box content.\n </FormField.InfoBox>\n </FormField.Root>\n </Stack>\n)\n```\n\n> [!CAUTION]\\\n> **Don't**\n>\n> - Use sentence case for labels. Do not capitalize every word.\n> - Do not combine top and side labels within the form.\n> - Only use description text and helper icons when it is needed.\n> - Placeholder text should give hints to the user about what is expected, not\n> be used for quirky brand copy.\n> - Do not mix form sizes.\n\n```jsx live\nconst App = () => (\n <Stack gap=\"400\">\n <FormField.Root size=\"md\" isRequired>\n <FormField.Label>First Name</FormField.Label>\n <FormField.Input>\n <TextInput placeholder=\"What should we call you?\" width=\"9600\" />\n </FormField.Input>\n </FormField.Root>\n <FormField.Root direction=\"row\" size=\"sm\" isRequired>\n <FormField.Label>Last name</FormField.Label>\n <FormField.Input>\n <TextInput placeholder=\"What's in a name?\" width=\"8000\" />\n </FormField.Input>\n </FormField.Root>\n </Stack>\n)\n```\n\n### Validation\n\nCommunicate clearly with users about how to correct form validation issues.\n\n> [!TIP]\\\n> **Do**\n>\n> - Have succinct reasons why the error happened for the user to correct.\n> - Keep previously entered information so a user can check their work to spot\n> mistakes easier.\n\n```jsx live\nconst App = () => (\n <Stack>\n <FormField.Root isRequired isInvalid>\n <FormField.Label>Social Security Number (SSN)</FormField.Label>\n <FormField.Input>\n <TextInput value=\"555-55-5555\" width=\"9600\" />\n </FormField.Input>\n <FormField.Error>\n This information does not match\n </FormField.Error>\n <FormField.InfoBox>\n Info box content.\n </FormField.InfoBox>\n </FormField.Root>\n </Stack>\n)\n```\n\n> [!CAUTION]\\\n> **Don't**\n>\n> - Don’t forget to use error messaging. Convey clearly how a user can make\n> corrections to move forward through the form.\n> - Don’t clear the previously input information if applicable, to help the user\n> understand the mistake, and provide the best user experience.\n\n```jsx live\nconst App = () => (\n <Stack>\n <FormField.Root isRequired isInvalid>\n <FormField.Label>Social Security Number (SSN)</FormField.Label>\n <FormField.Input>\n <TextInput placeholder=\"XXX-XX-XXXX\" width=\"9600\" />\n </FormField.Input>\n <FormField.InfoBox>\n Info box content.\n </FormField.InfoBox>\n </FormField.Root>\n </Stack>\n)\n```\n\n### Labels\n\nClear labels are essential for a smooth user experience. They reduce confusion,\nimprove accessibility for everyone, and build user confidence by making\ninterfaces intuitive and easy to navigate. Simply put, clear labels mean happy\nusers.\n\n> [!TIP]\\\n> **Do**\n>\n> - Label is concise and clear.\n\n```jsx live\nconst App = () => (\n <FormField.Root isRequired>\n <FormField.Label>First name</FormField.Label>\n <FormField.Input>\n <TextInput width=\"9600\" placeholder=\"John\" />\n </FormField.Input>\n <FormField.InfoBox>\n Info box content.\n </FormField.InfoBox>\n </FormField.Root>\n)\n```\n\n> [!CAUTION]\\\n> **Don't**\n>\n> - Navigation is higher hierarchy than icon button tools, this is not a common\n> pattern.\n\n```jsx live\nconst App = () => (\n <FormField.Root isRequired>\n <FormField.Label>What do we call you?</FormField.Label>\n <FormField.Input>\n <TextInput width=\"9600\" placeholder=\"John or Johnny or Jon?\" />\n </FormField.Input>\n <FormField.InfoBox>\n Info box content.\n </FormField.InfoBox>\n </FormField.Root>\n)\n```\n\n### Helper text and info button\n\nUse the right informative tool to aid your user to understand what is needed.\nHelp text should be short and is preferred when crucial information is needed.\nUse info button when supplemental information is too long for a help text,\ntooltips will by default open a dialog overlay, and can contain more detailed\ninformation, content types and formatting. See [dialog](#) for more guidelines\nconcerning the content inside the modal.\n\n> [!TIP]\\\n> **Do**\n>\n> - Maximum of 1-2 short sentences, around 20-30 words. Keep helper text below\n> 150 characters.\n> - If a long explanation is needed to explain anything related to this field,\n> use the tooltip instead of the helper text.\n> - A good example of balanced information. Helper text is being used to inform\n> all users without interaction. The info button contains supplementary\n> information.\n\n```jsx live\nconst App = () => (\n <Stack>\n <FormField.Root isRequired>\n <FormField.Label>Product discount rank</FormField.Label>\n <FormField.Input>\n <TextInput width=\"9600\" />\n </FormField.Input>\n <FormField.Description>\n Sort order values can only be a value between 1 and 2,147,483,647.\n </FormField.Description>\n <FormField.InfoBox>\n Info box content.\n </FormField.InfoBox>\n </FormField.Root>\n </Stack>\n)\n```\n\n> [!CAUTION]\\\n> **Don't**\n>\n> - Do not overload help text and do not use bullet points. Keep help text below\n> 150 characters.\n> - If information is important for users, use the help text to show to users\n> without interaction.\n> - Do not duplicate information in the help text and inside the info button.\n\n```jsx live\nconst App = () => (\n <Stack>\n <FormField.Root isRequired>\n <FormField.Label>Product discount rank</FormField.Label>\n <FormField.Input>\n <TextInput width=\"9600\" />\n </FormField.Input>\n <FormField.Description>\n Only one Product discount can be applied per product. The Sort order\n determines which Product discount applies to your product. Discounts\n with a Sort order value closer to 1 are considered first. Sort order\n values can only be a value between 0 and 1.\n <br/><br/>\n <Text fontWeight=\"700\">For example:</Text>\n <br/>\n <Text>• Product discount 1 has a Sort order value: 0.05</Text>\n <Text>• Product discount 2 has a Sort order value: 0.07</Text>\n <Text>• Both Product discounts are active and apply to the same\n product.</Text>\n <Text>• Product discount 2 will apply and Product discount 1 will not\n because 0.07 is closer to 1 than 0.05.</Text>\n\n </FormField.Description>\n <FormField.InfoBox>\n Info box content.\n </FormField.InfoBox>\n </FormField.Root>\n </Stack>\n)\n```\n",
745
+ "toc": [
746
+ {
747
+ "value": "Guidelines",
748
+ "href": "#guidelines",
749
+ "depth": 2,
750
+ "numbering": [
751
+ 1,
752
+ 1
753
+ ],
754
+ "parent": "root"
755
+ },
756
+ {
757
+ "value": "Best practices",
758
+ "href": "#best-practices",
759
+ "depth": 3,
760
+ "numbering": [
761
+ 1,
762
+ 1,
763
+ 1
764
+ ],
765
+ "parent": "root"
766
+ },
767
+ {
768
+ "value": "Labels",
769
+ "href": "#labels",
770
+ "depth": 4,
771
+ "numbering": [
772
+ 1,
773
+ 1,
774
+ 1,
775
+ 1
776
+ ],
777
+ "parent": "root"
778
+ },
779
+ {
780
+ "value": "Helper text vs info icon",
781
+ "href": "#helper-text-vs-info-icon",
782
+ "depth": 3,
783
+ "numbering": [
784
+ 1,
785
+ 1,
786
+ 2
787
+ ],
788
+ "parent": "root"
789
+ },
790
+ {
791
+ "value": "Usage",
792
+ "href": "#usage",
793
+ "depth": 3,
794
+ "numbering": [
795
+ 1,
796
+ 1,
797
+ 3
798
+ ],
799
+ "parent": "root"
800
+ },
801
+ {
802
+ "value": "Formatting",
803
+ "href": "#formatting",
804
+ "depth": 3,
805
+ "numbering": [
806
+ 1,
807
+ 1,
808
+ 4
809
+ ],
810
+ "parent": "root"
811
+ },
812
+ {
813
+ "value": "Validation",
814
+ "href": "#validation",
815
+ "depth": 3,
816
+ "numbering": [
817
+ 1,
818
+ 1,
819
+ 5
820
+ ],
821
+ "parent": "root"
822
+ },
823
+ {
824
+ "value": "Labels",
825
+ "href": "#labels-1",
826
+ "depth": 3,
827
+ "numbering": [
828
+ 1,
829
+ 1,
830
+ 6
831
+ ],
832
+ "parent": "root"
833
+ },
834
+ {
835
+ "value": "Helper text and info button",
836
+ "href": "#helper-text-and-info-button",
837
+ "depth": 3,
838
+ "numbering": [
839
+ 1,
840
+ 1,
841
+ 7
842
+ ],
843
+ "parent": "root"
844
+ }
845
+ ]
846
+ }
847
+ }
848
+ }