@lar-works/design-system 0.2.0 → 0.3.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 (433) hide show
  1. package/README.md +5 -1
  2. package/dist/actions/Button.d.ts +39 -1
  3. package/dist/actions/Button.js +39 -9
  4. package/dist/actions/Button.js.map +1 -1
  5. package/dist/actions/ButtonLink.d.ts +5 -1
  6. package/dist/actions/ButtonLink.js +28 -2
  7. package/dist/actions/ButtonLink.js.map +1 -1
  8. package/dist/actions/ButtonRecipes.js +7 -0
  9. package/dist/actions/ButtonRecipes.js.map +1 -0
  10. package/dist/actions/IconButton.d.ts +2 -2
  11. package/dist/actions/IconButton.js +1 -1
  12. package/dist/actions/IconButton.js.map +1 -1
  13. package/dist/actions/ThemeSwitch.js +1 -1
  14. package/dist/board/ActivityLine.d.ts +36 -0
  15. package/dist/board/ActivityLine.js +144 -0
  16. package/dist/board/ActivityLine.js.map +1 -0
  17. package/dist/board/ActivityTrack.d.ts +11 -0
  18. package/dist/board/ActivityTrack.js +25 -0
  19. package/dist/board/ActivityTrack.js.map +1 -0
  20. package/dist/board/AddItem.d.ts +82 -0
  21. package/dist/board/AddItem.js +185 -0
  22. package/dist/board/AddItem.js.map +1 -0
  23. package/dist/board/Archive.d.ts +21 -0
  24. package/dist/board/Archive.js +63 -0
  25. package/dist/board/Archive.js.map +1 -0
  26. package/dist/board/Attention.d.ts +66 -0
  27. package/dist/board/Attention.js +122 -0
  28. package/dist/board/Attention.js.map +1 -0
  29. package/dist/board/BoardShell.d.ts +16 -0
  30. package/dist/board/BoardShell.js +35 -0
  31. package/dist/board/BoardShell.js.map +1 -0
  32. package/dist/board/BoardTitleBar.d.ts +50 -0
  33. package/dist/board/BoardTitleBar.js +125 -0
  34. package/dist/board/BoardTitleBar.js.map +1 -0
  35. package/dist/board/ButtonKinds.d.ts +24 -0
  36. package/dist/board/ButtonKinds.js +19 -0
  37. package/dist/board/ButtonKinds.js.map +1 -0
  38. package/dist/board/Cleanup.d.ts +8 -0
  39. package/dist/board/Cleanup.js +15 -0
  40. package/dist/board/Cleanup.js.map +1 -0
  41. package/dist/board/Counters.d.ts +101 -0
  42. package/dist/board/Counters.js +202 -0
  43. package/dist/board/Counters.js.map +1 -0
  44. package/dist/board/DataAttributes.d.ts +6 -0
  45. package/dist/board/Dependencies.d.ts +17 -0
  46. package/dist/board/Dependencies.js +44 -0
  47. package/dist/board/Dependencies.js.map +1 -0
  48. package/dist/board/Desk.d.ts +52 -0
  49. package/dist/board/Desk.js +130 -0
  50. package/dist/board/Desk.js.map +1 -0
  51. package/dist/board/Dossier.d.ts +100 -0
  52. package/dist/board/Dossier.js +194 -0
  53. package/dist/board/Dossier.js.map +1 -0
  54. package/dist/board/Filters.d.ts +33 -0
  55. package/dist/board/Filters.js +64 -0
  56. package/dist/board/Filters.js.map +1 -0
  57. package/dist/board/ItemDetails.d.ts +167 -0
  58. package/dist/board/ItemDetails.js +339 -0
  59. package/dist/board/ItemDetails.js.map +1 -0
  60. package/dist/board/ItemDialog.d.ts +73 -0
  61. package/dist/board/ItemDialog.js +140 -0
  62. package/dist/board/ItemDialog.js.map +1 -0
  63. package/dist/board/ItemParts.d.ts +42 -0
  64. package/dist/board/ItemParts.js +82 -0
  65. package/dist/board/ItemParts.js.map +1 -0
  66. package/dist/board/ItemProgress.d.ts +56 -0
  67. package/dist/board/ItemProgress.js +138 -0
  68. package/dist/board/ItemProgress.js.map +1 -0
  69. package/dist/board/List.d.ts +65 -0
  70. package/dist/board/List.js +118 -0
  71. package/dist/board/List.js.map +1 -0
  72. package/dist/board/LoadingScreen.d.ts +38 -0
  73. package/dist/board/LoadingScreen.js +74 -0
  74. package/dist/board/LoadingScreen.js.map +1 -0
  75. package/dist/board/NeedsYou.d.ts +13 -0
  76. package/dist/board/NeedsYou.js +31 -0
  77. package/dist/board/NeedsYou.js.map +1 -0
  78. package/dist/board/Onboarding.d.ts +53 -0
  79. package/dist/board/Onboarding.js +122 -0
  80. package/dist/board/Onboarding.js.map +1 -0
  81. package/dist/board/PartsList.d.ts +60 -0
  82. package/dist/board/PartsList.js +115 -0
  83. package/dist/board/PartsList.js.map +1 -0
  84. package/dist/board/ProjectIcon.d.ts +51 -0
  85. package/dist/board/ProjectIcon.js +120 -0
  86. package/dist/board/ProjectIcon.js.map +1 -0
  87. package/dist/board/PullRequests.d.ts +43 -0
  88. package/dist/board/PullRequests.js +83 -0
  89. package/dist/board/PullRequests.js.map +1 -0
  90. package/dist/board/RowStyles.js +14 -0
  91. package/dist/board/RowStyles.js.map +1 -0
  92. package/dist/board/Settings.d.ts +54 -0
  93. package/dist/board/Settings.js +112 -0
  94. package/dist/board/Settings.js.map +1 -0
  95. package/dist/board/Slices.d.ts +32 -0
  96. package/dist/board/Slices.js +88 -0
  97. package/dist/board/Slices.js.map +1 -0
  98. package/dist/board/SourceIcon.d.ts +12 -0
  99. package/dist/board/SourceIcon.js +24 -0
  100. package/dist/board/SourceIcon.js.map +1 -0
  101. package/dist/board/StagePane.d.ts +43 -0
  102. package/dist/board/StagePane.js +97 -0
  103. package/dist/board/StagePane.js.map +1 -0
  104. package/dist/board/StageRow.d.ts +141 -0
  105. package/dist/board/StageRow.js +287 -0
  106. package/dist/board/StageRow.js.map +1 -0
  107. package/dist/board/StageTrack.d.ts +18 -0
  108. package/dist/board/StageTrack.js +38 -0
  109. package/dist/board/StageTrack.js.map +1 -0
  110. package/dist/board/StartControls.d.ts +30 -0
  111. package/dist/board/StartControls.js +51 -0
  112. package/dist/board/StartControls.js.map +1 -0
  113. package/dist/board/StatusColors.d.ts +5 -0
  114. package/dist/board/StatusColors.js +17 -0
  115. package/dist/board/StatusColors.js.map +1 -0
  116. package/dist/board/StatusGlyph.d.ts +18 -0
  117. package/dist/board/StatusGlyph.js +51 -0
  118. package/dist/board/StatusGlyph.js.map +1 -0
  119. package/dist/board/Threads.d.ts +13 -0
  120. package/dist/board/Threads.js +35 -0
  121. package/dist/board/Threads.js.map +1 -0
  122. package/dist/board/TrackerLabels.d.ts +27 -0
  123. package/dist/board/TrackerLabels.js +56 -0
  124. package/dist/board/TrackerLabels.js.map +1 -0
  125. package/dist/board/UpdatePill.d.ts +52 -0
  126. package/dist/board/UpdatePill.js +188 -0
  127. package/dist/board/UpdatePill.js.map +1 -0
  128. package/dist/board/Vocabulary.d.ts +56 -0
  129. package/dist/board/Vocabulary.js +104 -0
  130. package/dist/board/Vocabulary.js.map +1 -0
  131. package/dist/board/Warnings.d.ts +35 -0
  132. package/dist/board/Warnings.js +85 -0
  133. package/dist/board/Warnings.js.map +1 -0
  134. package/dist/board/WorkMap.d.ts +136 -0
  135. package/dist/board/WorkMap.js +274 -0
  136. package/dist/board/WorkMap.js.map +1 -0
  137. package/dist/board/index.d.ts +42 -0
  138. package/dist/collections/CollectionState.d.ts +10 -1
  139. package/dist/collections/CollectionState.js +12 -5
  140. package/dist/collections/CollectionState.js.map +1 -1
  141. package/dist/collections/ResultList.js +1 -1
  142. package/dist/collections/ScrollRow.js +1 -1
  143. package/dist/collections/VirtualList.js +1 -1
  144. package/dist/display/Avatar.d.ts +5 -2
  145. package/dist/display/Avatar.js +2 -2
  146. package/dist/display/Avatar.js.map +1 -1
  147. package/dist/display/Badge.d.ts +6 -1
  148. package/dist/display/Badge.js +9 -4
  149. package/dist/display/Badge.js.map +1 -1
  150. package/dist/display/CheckList.js +1 -1
  151. package/dist/display/Comment.d.ts +12 -0
  152. package/dist/display/Comment.js +39 -0
  153. package/dist/display/Comment.js.map +1 -0
  154. package/dist/display/CopyButton.d.ts +10 -2
  155. package/dist/display/CopyButton.js +29 -16
  156. package/dist/display/CopyButton.js.map +1 -1
  157. package/dist/display/Diagram.d.ts +17 -0
  158. package/dist/display/Diagram.js +49 -0
  159. package/dist/display/Diagram.js.map +1 -0
  160. package/dist/display/ImagePicker.js +1 -1
  161. package/dist/display/InfoBox.js +2 -2
  162. package/dist/display/InsetPanel.d.ts +3 -1
  163. package/dist/display/InsetPanel.js +7 -4
  164. package/dist/display/InsetPanel.js.map +1 -1
  165. package/dist/display/ItemAction.js +2 -2
  166. package/dist/display/LabelChip.d.ts +26 -0
  167. package/dist/display/LabelChip.js +41 -0
  168. package/dist/display/LabelChip.js.map +1 -0
  169. package/dist/display/LabelTint.js +60 -0
  170. package/dist/display/LabelTint.js.map +1 -0
  171. package/dist/display/Person.d.ts +5 -0
  172. package/dist/display/Person.js +19 -0
  173. package/dist/display/Person.js.map +1 -0
  174. package/dist/display/PropertySheet.js +1 -1
  175. package/dist/display/RadioChoice.d.ts +9 -2
  176. package/dist/display/RadioChoice.js +5 -1
  177. package/dist/display/RadioChoice.js.map +1 -1
  178. package/dist/display/RatingLink.js +1 -1
  179. package/dist/display/RichText.d.ts +12 -0
  180. package/dist/display/RichText.js +94 -0
  181. package/dist/display/RichText.js.map +1 -0
  182. package/dist/display/RowList.js +1 -1
  183. package/dist/display/index.d.ts +6 -1
  184. package/dist/feedback/Alert.js +1 -1
  185. package/dist/feedback/AsyncState.js +1 -1
  186. package/dist/feedback/DismissButton.d.ts +12 -0
  187. package/dist/feedback/DismissButton.js +20 -0
  188. package/dist/feedback/DismissButton.js.map +1 -0
  189. package/dist/feedback/ErrorNotification.js +2 -0
  190. package/dist/feedback/ErrorNotification.js.map +1 -1
  191. package/dist/feedback/FormResult.d.ts +16 -0
  192. package/dist/feedback/FormResult.js +30 -0
  193. package/dist/feedback/FormResult.js.map +1 -0
  194. package/dist/feedback/LiveRegion.d.ts +7 -0
  195. package/dist/feedback/LiveRegion.js +15 -0
  196. package/dist/feedback/LiveRegion.js.map +1 -0
  197. package/dist/feedback/Loading.d.ts +19 -0
  198. package/dist/feedback/Loading.js +63 -0
  199. package/dist/feedback/Loading.js.map +1 -0
  200. package/dist/feedback/Notifications.d.ts +35 -1
  201. package/dist/feedback/Notifications.js +196 -4
  202. package/dist/feedback/Notifications.js.map +1 -1
  203. package/dist/feedback/Progress.d.ts +15 -0
  204. package/dist/feedback/Progress.js +38 -0
  205. package/dist/feedback/Progress.js.map +1 -0
  206. package/dist/feedback/ProgressStatusRow.js +1 -1
  207. package/dist/feedback/StatusIndicator.d.ts +6 -1
  208. package/dist/feedback/StatusIndicator.js +19 -5
  209. package/dist/feedback/StatusIndicator.js.map +1 -1
  210. package/dist/feedback/index.d.ts +8 -4
  211. package/dist/forms/Checkbox.js +1 -1
  212. package/dist/forms/ColorSwatches.d.ts +21 -0
  213. package/dist/forms/ColorSwatches.js +26 -0
  214. package/dist/forms/ColorSwatches.js.map +1 -0
  215. package/dist/forms/FormSection.d.ts +68 -6
  216. package/dist/forms/FormSection.js +139 -8
  217. package/dist/forms/FormSection.js.map +1 -1
  218. package/dist/forms/HiddenField.d.ts +6 -0
  219. package/dist/forms/HiddenField.js +13 -0
  220. package/dist/forms/HiddenField.js.map +1 -0
  221. package/dist/forms/Input.d.ts +12 -2
  222. package/dist/forms/Input.js +10 -3
  223. package/dist/forms/Input.js.map +1 -1
  224. package/dist/forms/LabelPicker.d.ts +43 -0
  225. package/dist/forms/LabelPicker.js +107 -0
  226. package/dist/forms/LabelPicker.js.map +1 -0
  227. package/dist/forms/MarkdownEditor.d.ts +21 -0
  228. package/dist/forms/MarkdownEditor.js +175 -0
  229. package/dist/forms/MarkdownEditor.js.map +1 -0
  230. package/dist/forms/MarkdownToolbar.js +204 -0
  231. package/dist/forms/MarkdownToolbar.js.map +1 -0
  232. package/dist/forms/OptionSelect.d.ts +30 -9
  233. package/dist/forms/OptionSelect.js +53 -13
  234. package/dist/forms/OptionSelect.js.map +1 -1
  235. package/dist/forms/Select.d.ts +4 -1
  236. package/dist/forms/Select.js +3 -1
  237. package/dist/forms/Select.js.map +1 -1
  238. package/dist/forms/Switch.d.ts +4 -1
  239. package/dist/forms/Switch.js +5 -2
  240. package/dist/forms/Switch.js.map +1 -1
  241. package/dist/forms/TagInput.js +1 -1
  242. package/dist/forms/index.d.ts +7 -3
  243. package/dist/foundations/AmbientMotion.d.ts +2 -0
  244. package/dist/foundations/AmbientMotion.js +39 -0
  245. package/dist/foundations/AmbientMotion.js.map +1 -0
  246. package/dist/foundations/DesignSystemProvider.d.ts +34 -0
  247. package/dist/foundations/DesignSystemProvider.js +26 -1
  248. package/dist/foundations/DesignSystemProvider.js.map +1 -1
  249. package/dist/foundations/index.d.ts +2 -1
  250. package/dist/icons/BrandIcons.d.ts +8 -2
  251. package/dist/icons/BrandIcons.js +14 -3
  252. package/dist/icons/BrandIcons.js.map +1 -1
  253. package/dist/icons/dynamic.d.ts +2 -0
  254. package/dist/icons/dynamic.js +1 -0
  255. package/dist/icons/index.d.ts +2 -2
  256. package/dist/icons/index.js +1 -1
  257. package/dist/icons.d.ts +2 -2
  258. package/dist/icons.js +1 -1
  259. package/dist/index.d.ts +71 -10
  260. package/dist/index.js +78 -21
  261. package/dist/layout/Site.js +1 -1
  262. package/dist/layout/TitleBar.js +1 -1
  263. package/dist/layout/index.d.ts +2 -2
  264. package/dist/layout/index.js +3 -3
  265. package/dist/layout/toolbar/CommandPaletteTrigger.d.ts +17 -2
  266. package/dist/layout/toolbar/CommandPaletteTrigger.js +89 -6
  267. package/dist/layout/toolbar/CommandPaletteTrigger.js.map +1 -1
  268. package/dist/layout/toolbar/TriggerFit.js +56 -0
  269. package/dist/layout/toolbar/TriggerFit.js.map +1 -0
  270. package/dist/navigation/CollectionBrowseSelector.js +1 -1
  271. package/dist/navigation/CollectionViewToggle.d.ts +26 -0
  272. package/dist/navigation/CollectionViewToggle.js +54 -23
  273. package/dist/navigation/CollectionViewToggle.js.map +1 -1
  274. package/dist/navigation/DrilldownBrowseSelector.js +1 -1
  275. package/dist/navigation/FolderSelector.js +2 -2
  276. package/dist/navigation/SortMenu.d.ts +10 -0
  277. package/dist/navigation/SortMenu.js +33 -0
  278. package/dist/navigation/SortMenu.js.map +1 -0
  279. package/dist/navigation/index.d.ts +3 -2
  280. package/dist/overlays/CommandPalette.d.ts +38 -4
  281. package/dist/overlays/CommandPalette.js +140 -54
  282. package/dist/overlays/CommandPalette.js.map +1 -1
  283. package/dist/overlays/Drawer.js +1 -1
  284. package/dist/overlays/DropdownMenu.d.ts +7 -1
  285. package/dist/overlays/DropdownMenu.js +13 -2
  286. package/dist/overlays/DropdownMenu.js.map +1 -1
  287. package/dist/overlays/HelpTip.d.ts +8 -0
  288. package/dist/overlays/HelpTip.js +29 -0
  289. package/dist/overlays/HelpTip.js.map +1 -0
  290. package/dist/overlays/ImageViewer.js +2 -2
  291. package/dist/overlays/Modal.d.ts +5 -0
  292. package/dist/overlays/Modal.js +17 -2
  293. package/dist/overlays/Modal.js.map +1 -1
  294. package/dist/overlays/ModalExpandButton.d.ts +18 -0
  295. package/dist/overlays/ModalExpandButton.js +43 -0
  296. package/dist/overlays/ModalExpandButton.js.map +1 -0
  297. package/dist/overlays/Popover.d.ts +2 -1
  298. package/dist/overlays/Popover.js +1 -0
  299. package/dist/overlays/Popover.js.map +1 -1
  300. package/dist/overlays/index.d.ts +4 -2
  301. package/dist/showcase/Cards.js +1 -1
  302. package/dist/showcase/FeatureRow.js +1 -1
  303. package/dist/showcase/PhotoSearchConcept.js +1 -1
  304. package/dist/showcase/ProductBand.js +1 -1
  305. package/dist/showcase/Status.js +1 -1
  306. package/dist/typography/Code.d.ts +18 -0
  307. package/dist/typography/Code.js +24 -0
  308. package/dist/typography/Code.js.map +1 -0
  309. package/dist/typography/Link.d.ts +7 -2
  310. package/dist/typography/Link.js +15 -5
  311. package/dist/typography/Link.js.map +1 -1
  312. package/dist/typography/Typography.d.ts +19 -1
  313. package/dist/typography/Typography.js +11 -3
  314. package/dist/typography/Typography.js.map +1 -1
  315. package/dist/typography/index.d.ts +3 -3
  316. package/package.json +26 -3
  317. package/src/actions/Button.tsx +78 -11
  318. package/src/actions/ButtonLink.tsx +34 -0
  319. package/src/actions/ButtonRecipes.ts +10 -0
  320. package/src/actions/IconButton.tsx +7 -4
  321. package/src/board/ActivityLine.tsx +176 -0
  322. package/src/board/ActivityTrack.tsx +23 -0
  323. package/src/board/AddItem.tsx +259 -0
  324. package/src/board/Archive.tsx +75 -0
  325. package/src/board/Attention.tsx +135 -0
  326. package/src/board/BoardShell.tsx +30 -0
  327. package/src/board/BoardTitleBar.tsx +167 -0
  328. package/src/board/ButtonKinds.ts +32 -0
  329. package/src/board/Cleanup.tsx +19 -0
  330. package/src/board/Counters.tsx +224 -0
  331. package/src/board/DataAttributes.ts +3 -0
  332. package/src/board/Dependencies.tsx +49 -0
  333. package/src/board/Desk.tsx +155 -0
  334. package/src/board/Dossier.tsx +262 -0
  335. package/src/board/Filters.tsx +85 -0
  336. package/src/board/ItemDetails.tsx +435 -0
  337. package/src/board/ItemDialog.tsx +179 -0
  338. package/src/board/ItemParts.tsx +128 -0
  339. package/src/board/ItemProgress.tsx +164 -0
  340. package/src/board/List.tsx +154 -0
  341. package/src/board/LoadingScreen.tsx +78 -0
  342. package/src/board/NeedsYou.tsx +30 -0
  343. package/src/board/Onboarding.tsx +124 -0
  344. package/src/board/PartsList.tsx +160 -0
  345. package/src/board/ProjectIcon.tsx +172 -0
  346. package/src/board/PullRequests.tsx +106 -0
  347. package/src/board/RowStyles.ts +17 -0
  348. package/src/board/Settings.tsx +124 -0
  349. package/src/board/Slices.tsx +103 -0
  350. package/src/board/SourceIcon.tsx +33 -0
  351. package/src/board/StagePane.tsx +128 -0
  352. package/src/board/StageRow.tsx +320 -0
  353. package/src/board/StageTrack.tsx +61 -0
  354. package/src/board/StartControls.tsx +77 -0
  355. package/src/board/StatusColors.ts +28 -0
  356. package/src/board/StatusGlyph.tsx +70 -0
  357. package/src/board/Threads.tsx +38 -0
  358. package/src/board/TrackerLabels.tsx +75 -0
  359. package/src/board/UpdatePill.tsx +222 -0
  360. package/src/board/Vocabulary.tsx +155 -0
  361. package/src/board/Warnings.tsx +83 -0
  362. package/src/board/WorkMap.tsx +436 -0
  363. package/src/board/base.css +121 -0
  364. package/src/board/button-kinds.css +8 -0
  365. package/src/board/index.ts +224 -0
  366. package/src/board/items.css +75 -0
  367. package/src/board/loading-screen.css +171 -0
  368. package/src/board/rows.css +180 -0
  369. package/src/board/title-bar.css +56 -0
  370. package/src/board/tokens.css +52 -0
  371. package/src/board.css +19 -0
  372. package/src/collections/CollectionState.tsx +20 -7
  373. package/src/display/Avatar.tsx +6 -3
  374. package/src/display/Badge.tsx +25 -3
  375. package/src/display/Comment.tsx +26 -0
  376. package/src/display/CopyButton.tsx +48 -18
  377. package/src/display/Diagram.tsx +59 -0
  378. package/src/display/InsetPanel.tsx +4 -1
  379. package/src/display/LabelChip.tsx +73 -0
  380. package/src/display/LabelTint.ts +72 -0
  381. package/src/display/Person.tsx +11 -0
  382. package/src/display/RadioChoice.tsx +11 -2
  383. package/src/display/RichText.tsx +114 -0
  384. package/src/display/index.ts +5 -0
  385. package/src/feedback/DismissButton.tsx +28 -0
  386. package/src/feedback/ErrorNotification.ts +3 -0
  387. package/src/feedback/FormResult.tsx +50 -0
  388. package/src/feedback/LiveRegion.tsx +10 -0
  389. package/src/feedback/Loading.tsx +75 -0
  390. package/src/feedback/Notifications.tsx +267 -2
  391. package/src/feedback/Progress.tsx +44 -0
  392. package/src/feedback/StatusIndicator.tsx +34 -3
  393. package/src/feedback/index.ts +12 -2
  394. package/src/forms/ColorSwatches.tsx +50 -0
  395. package/src/forms/FormSection.tsx +245 -10
  396. package/src/forms/HiddenField.tsx +4 -0
  397. package/src/forms/Input.tsx +26 -4
  398. package/src/forms/LabelPicker.tsx +140 -0
  399. package/src/forms/MarkdownEditor.tsx +283 -0
  400. package/src/forms/MarkdownToolbar.tsx +267 -0
  401. package/src/forms/OptionSelect.tsx +110 -25
  402. package/src/forms/Select.tsx +20 -13
  403. package/src/forms/Switch.tsx +16 -2
  404. package/src/forms/index.ts +16 -2
  405. package/src/foundations/AmbientMotion.ts +51 -0
  406. package/src/foundations/DesignSystemProvider.tsx +19 -0
  407. package/src/foundations/index.ts +1 -0
  408. package/src/foundations/theme.css +64 -0
  409. package/src/icons/BrandIcons.tsx +12 -3
  410. package/src/icons/dynamic.ts +4 -0
  411. package/src/icons/index.ts +1 -1
  412. package/src/index.ts +2 -1
  413. package/src/layout/index.ts +1 -1
  414. package/src/layout/toolbar/CommandPaletteTrigger.tsx +187 -31
  415. package/src/layout/toolbar/TriggerFit.ts +84 -0
  416. package/src/navigation/CollectionViewToggle.tsx +94 -24
  417. package/src/navigation/SortMenu.tsx +41 -0
  418. package/src/navigation/index.ts +2 -1
  419. package/src/overlays/CommandPalette.tsx +190 -60
  420. package/src/overlays/DropdownMenu.tsx +12 -1
  421. package/src/overlays/HelpTip.tsx +29 -0
  422. package/src/overlays/Modal.tsx +23 -0
  423. package/src/overlays/ModalExpandButton.tsx +48 -0
  424. package/src/overlays/Popover.tsx +3 -1
  425. package/src/overlays/index.ts +9 -1
  426. package/src/showcase.css +6 -0
  427. package/src/styles.css +9 -1
  428. package/src/typography/Code.tsx +24 -0
  429. package/src/typography/Link.tsx +19 -10
  430. package/src/typography/Typography.tsx +25 -2
  431. package/src/typography/index.ts +1 -1
  432. package/dist/feedback/index.js +0 -11
  433. package/dist/typography/index.js +0 -4
@@ -0,0 +1,128 @@
1
+ // The bits every view of Lar Factory's board draws for a piece of work: its numbered title, title link, repository,
2
+ // tracker fields, kind marker, label chips and planning notes.
3
+
4
+ import { ArrowLeftRightIcon } from 'lucide-react';
5
+ import type { ReactNode } from 'react';
6
+
7
+ import { Badge } from '../display/Badge';
8
+ import type { DataAttributes } from './DataAttributes';
9
+
10
+ /** A title with its ticket's reference (`#12`) before it, muted, the way the board lists every item; captured work has
11
+ * no reference. */
12
+ export function ItemTitle({ reference, title }: { reference?: string | undefined; title: string }) {
13
+ return (
14
+ <>
15
+ {reference ? (
16
+ <>
17
+ <span className="font-normal text-(--muted-foreground) tabular-nums">{reference}</span>{' '}
18
+ </>
19
+ ) : null}
20
+ {title}
21
+ </>
22
+ );
23
+ }
24
+
25
+ /** A title with its reference as a link to its ticket in a new tab, or as text when it has no page, as a sentence names
26
+ * it. */
27
+ export function TitleLink({
28
+ reference,
29
+ title,
30
+ href,
31
+ }: {
32
+ reference?: string | undefined;
33
+ title: string;
34
+ href?: string | undefined;
35
+ }) {
36
+ const text = (
37
+ <>
38
+ {reference ? (
39
+ <>
40
+ <span className="ref">{reference}</span>{' '}
41
+ </>
42
+ ) : null}
43
+ {title}
44
+ </>
45
+ );
46
+
47
+ return href ? (
48
+ <a className="title" href={href} target="_blank" rel="noopener">
49
+ {text}
50
+ </a>
51
+ ) : (
52
+ <span className="title">{text}</span>
53
+ );
54
+ }
55
+
56
+ /** A repository as a badge: its project icon and name. */
57
+ export function RepoTag({ icon, name }: { icon: ReactNode; name: string }) {
58
+ return (
59
+ <Badge className="gap-1.5">
60
+ {icon}
61
+ {name}
62
+ </Badge>
63
+ );
64
+ }
65
+
66
+ const identities = {
67
+ row: 'flex min-w-0 items-center gap-1',
68
+ map: 'inline-flex min-w-0 items-center gap-1.5',
69
+ wrap: 'inline-flex min-w-0 items-center gap-2',
70
+ } as const;
71
+
72
+ /** A repository's project icon and name together, the name truncating: in a row's line, or roomier on the work map,
73
+ * where `title` names it in full. `wrap` is roomier still and wraps the name, anywhere if it must, for a line that
74
+ * says more than the name, such as an archived item's repository, number and state. */
75
+ export function RepoIdentity({
76
+ icon,
77
+ name,
78
+ title,
79
+ presentation = 'row',
80
+ ...data
81
+ }: {
82
+ icon: ReactNode;
83
+ name: string;
84
+ title?: string;
85
+ presentation?: 'row' | 'map' | 'wrap';
86
+ } & DataAttributes) {
87
+ return (
88
+ <span {...data} title={title} className={identities[presentation]}>
89
+ {icon}
90
+ <span className={presentation === 'wrap' ? 'min-w-0 wrap-anywhere' : 'truncate'}>{name}</span>
91
+ </span>
92
+ );
93
+ }
94
+
95
+ /** A tracker's fields for the item (such as Azure's type, state and assignee) as one muted line that truncates, its
96
+ * tooltip giving it whole. */
97
+ export function ItemFields({ text, ...data }: { text: string } & DataAttributes) {
98
+ return (
99
+ <span {...data} title={text} className="block min-w-0 truncate text-xs text-(--muted-foreground)">
100
+ {text}
101
+ </span>
102
+ );
103
+ }
104
+
105
+ /** Beside a kind badge, in muted text: the kind the ticket says instead, `said`, until someone answers. */
106
+ export function KindMarker({
107
+ said,
108
+ label,
109
+ title,
110
+ ...data
111
+ }: {
112
+ said: string;
113
+ /** The sentence assistive technology reads. */
114
+ label: string;
115
+ title: string;
116
+ } & DataAttributes) {
117
+ return (
118
+ <span
119
+ {...data}
120
+ title={title}
121
+ aria-label={label}
122
+ className="inline-flex items-center gap-0.5 text-[11px] text-(--muted-foreground)"
123
+ >
124
+ <ArrowLeftRightIcon className="size-2.5" aria-hidden="true" />
125
+ {said}
126
+ </span>
127
+ );
128
+ }
@@ -0,0 +1,164 @@
1
+ // The progress at the top of Lar Factory's item dialog: the workflow's steps as a bar, a concept's parts done, and a
2
+ // piece of work's slices as chips under their count.
3
+
4
+ import type { ReactNode } from 'react';
5
+
6
+ import type { DataAttributes } from './DataAttributes';
7
+ import type { SliceProgress } from './Slices';
8
+ import { SliceMark } from './Slices';
9
+
10
+ const PAST = 'color-mix(in srgb, var(--foreground) 28%, transparent)';
11
+
12
+ /** The dialog's progress block: the steps, the parts, the activity and the slices, stacked. */
13
+ export function ItemProgressPanel({ children, ...data }: { children: ReactNode } & DataAttributes) {
14
+ return (
15
+ <div {...data} className="grid min-w-0 grid-cols-[minmax(0,1fr)] gap-2">
16
+ {children}
17
+ </div>
18
+ );
19
+ }
20
+
21
+ /** A count's line over its bar, such as "Slices · 2/3 done": `label` in the text colour, then `children`. */
22
+ export function ProgressCount({ label, children }: { label: string; children: ReactNode }) {
23
+ return (
24
+ <p className="m-0 text-xs text-(--muted-foreground)">
25
+ <span className="font-medium text-(--foreground)">{label}</span> · {children}
26
+ </p>
27
+ );
28
+ }
29
+
30
+ /**
31
+ * The workflow's active steps as a bar: the past ones slim and darker, the upcoming faint, and the current one widest,
32
+ * named `name` with its step number, in a gradient of `color`, or `bar` (such as its slices) in that gradient's place.
33
+ * Each step's `label` is what assistive technology reads and its `title` its tooltip.
34
+ */
35
+ export function WorkflowSteps({
36
+ steps,
37
+ at,
38
+ name,
39
+ color,
40
+ bar,
41
+ }: {
42
+ steps: readonly { title: string; label: string }[];
43
+ /** The current step's index. */
44
+ at: number;
45
+ name: string;
46
+ color: string;
47
+ bar?: ReactNode;
48
+ }) {
49
+ return (
50
+ <ol className="m-0 flex list-none items-end gap-[3px] p-0" data-steps>
51
+ {steps.map((step, i) =>
52
+ i !== at ? (
53
+ <li
54
+ key={i}
55
+ title={step.title}
56
+ aria-label={step.label}
57
+ className="h-1.5 min-w-1.5 flex-1 rounded-full"
58
+ style={{ background: i < at ? PAST : 'var(--soft)' }}
59
+ />
60
+ ) : (
61
+ <li
62
+ key={i}
63
+ title={step.title}
64
+ aria-label={step.label}
65
+ aria-current="step"
66
+ className="grid min-w-26 flex-[6] gap-1"
67
+ >
68
+ <span className="flex items-baseline justify-between gap-2 text-xs leading-4">
69
+ <span className="truncate font-medium">{name}</span>
70
+ <span className="shrink-0 text-(--muted-foreground) tabular-nums">
71
+ {i + 1}/{steps.length}
72
+ </span>
73
+ </span>
74
+ {bar ? (
75
+ <div aria-hidden>{bar}</div>
76
+ ) : (
77
+ <span
78
+ className="h-1.5 rounded-full"
79
+ style={{
80
+ background: `linear-gradient(90deg, color-mix(in srgb, ${color} 55%, transparent), ${color})`,
81
+ }}
82
+ />
83
+ )}
84
+ </li>
85
+ ),
86
+ )}
87
+ </ol>
88
+ );
89
+ }
90
+
91
+ /** A concept's parts done out of its parts, as a ProgressCount over a bar in the done colour. */
92
+ export function PartsProgress({
93
+ label,
94
+ completed,
95
+ total,
96
+ children,
97
+ }: {
98
+ label: string;
99
+ completed: number;
100
+ total: number;
101
+ /** What the count says, such as "4/9 done". */
102
+ children: ReactNode;
103
+ }) {
104
+ return (
105
+ <div className="grid gap-1" data-parts-progress>
106
+ <ProgressCount label={label}>{children}</ProgressCount>
107
+ <div aria-hidden className="h-1.5 overflow-hidden rounded-full bg-(--soft)">
108
+ <div
109
+ className="h-full rounded-full bg-(--st-done)"
110
+ style={{ width: `${total > 0 ? (completed / total) * 100 : 0}%` }}
111
+ />
112
+ </div>
113
+ </div>
114
+ );
115
+ }
116
+
117
+ /** The activity under the steps: its track, then its label. */
118
+ export function ProgressActivity({ children }: { children: ReactNode }) {
119
+ return <div className="grid gap-1">{children}</div>;
120
+ }
121
+
122
+ /** The slices under the steps: their `count` line, a slice `bar` when the steps don't hold it, and a SliceChip each. */
123
+ export function SliceChips({ count, bar, children }: { count: ReactNode; bar?: ReactNode; children: ReactNode }) {
124
+ return (
125
+ <div className="grid min-w-0 grid-cols-[minmax(0,1fr)] gap-2" data-slices>
126
+ {count}
127
+ {bar && <div aria-hidden>{bar}</div>}
128
+ <ul className="m-0 flex list-none flex-wrap gap-1.5 p-0">{children}</ul>
129
+ </div>
130
+ );
131
+ }
132
+
133
+ /** A slice as a chip: where its ticket is saved, its mark, number, title (muted when done, medium while active) and
134
+ * state; `title` names it in full. */
135
+ export function SliceChip({
136
+ title,
137
+ source,
138
+ progress,
139
+ number,
140
+ name,
141
+ }: {
142
+ title: string;
143
+ source: ReactNode;
144
+ progress: SliceProgress;
145
+ number?: number | undefined;
146
+ name: string;
147
+ }) {
148
+ return (
149
+ <li
150
+ title={title}
151
+ className="inline-flex max-w-full items-center gap-1.5 rounded-full border border-(--border) bg-(--card) py-0.5 ps-1 pe-2.5 text-xs"
152
+ >
153
+ {source}
154
+ <SliceMark progress={progress} />
155
+ {!!number && <span className="shrink-0 text-(--muted-foreground) tabular-nums">#{number}</span>}
156
+ <span
157
+ className={`min-w-0 truncate ${progress === 'done' ? 'text-(--muted-foreground)' : progress === 'active' ? 'font-medium' : ''}`}
158
+ >
159
+ {name}
160
+ </span>
161
+ <span className="shrink-0 text-[11px] text-(--muted-foreground)">{progress}</span>
162
+ </li>
163
+ );
164
+ }
@@ -0,0 +1,154 @@
1
+ import type { ReactNode } from 'react';
2
+
3
+ import { Button } from '../actions/Button';
4
+ import { Badge } from '../display/Badge';
5
+ import { Loading } from '../feedback/Loading';
6
+ import { SidebarNavigationItem } from '../layout/sidebar/SidebarNavigationItem';
7
+ import { buttonKind } from './ButtonKinds';
8
+
9
+ interface ListButtonProps {
10
+ label: string;
11
+ icon: ReactNode;
12
+ /** How many items are in List; none while the first read could still add some, which shows a loading cue. */
13
+ count: number | undefined;
14
+ loadingLabel: string;
15
+ onOpen: () => void;
16
+ }
17
+
18
+ /** The title bar's List button, "List <count>": an App control whose label folds away, for screen readers only, on a
19
+ * title bar under 70rem. */
20
+ export function ListButton({ label, icon, count, loadingLabel, onOpen }: ListButtonProps) {
21
+ return (
22
+ <Button {...buttonKind('control')} className="list-button px-2" leftIcon={icon} title={label} onClick={onOpen}>
23
+ <span className="@max-[70rem]:sr-only">{label}</span>
24
+ {count === undefined ? <Loading presentation="inline" title={loadingLabel} /> : <Badge>{count}</Badge>}
25
+ </Button>
26
+ );
27
+ }
28
+
29
+ /** A group in the List's left pane: its icon, its name and how many of its items match; a group still reading shows
30
+ * no count. */
31
+ export function ListGroupItem({
32
+ label,
33
+ count,
34
+ icon,
35
+ active,
36
+ onPick,
37
+ }: {
38
+ label: string;
39
+ count?: number;
40
+ icon: ReactNode;
41
+ active: boolean;
42
+ onPick: () => void;
43
+ }) {
44
+ return (
45
+ <SidebarNavigationItem active={active} onClick={onPick}>
46
+ {icon}
47
+ <span className="name min-w-0 flex-1 truncate text-left">{label}</span>
48
+ {count !== undefined && <span className="count text-base-700 text-xs tabular-nums">{count}</span>}
49
+ </SidebarNavigationItem>
50
+ );
51
+ }
52
+
53
+ interface ListHeaderProps {
54
+ /** The search field, and beside it Add item. */
55
+ search: ReactNode;
56
+ add: ReactNode;
57
+ /** The chosen group's name and how many of its items show; no count while it's still reading. */
58
+ title: string;
59
+ count?: number;
60
+ /** After the count: a toggle that scopes the board to the group, and at the right the sort menu. */
61
+ scope?: ReactNode;
62
+ sort: ReactNode;
63
+ filters: ReactNode;
64
+ }
65
+
66
+ /** The List's right pane's head: the search with Add item, then the chosen group with its count, scope toggle and sort,
67
+ * then the filters. */
68
+ export function ListHeader({ search, add, title, count, scope, sort, filters }: ListHeaderProps) {
69
+ return (
70
+ <div className="flex shrink-0 flex-col gap-2 px-5 sm:px-6">
71
+ <div className="flex items-center gap-2 [&>[data-slot=button]]:shrink-0">
72
+ {search}
73
+ {add}
74
+ </div>
75
+ <div className="flex min-w-0 items-center gap-2">
76
+ <span className="text-base-content truncate text-sm font-semibold">{title}</span>
77
+ {count !== undefined && <Badge>{count}</Badge>}
78
+ {scope}
79
+ <span className="sort ml-auto">{sort}</span>
80
+ </div>
81
+ {filters}
82
+ </div>
83
+ );
84
+ }
85
+
86
+ interface ListItemRowProps {
87
+ /** The item's id, as `data-item`. */
88
+ item: string;
89
+ /** Its title in full, for the tooltip. */
90
+ name: string;
91
+ onOpen: () => void;
92
+ /** Where the item comes from. */
93
+ source: ReactNode;
94
+ /** The ticket's reference, such as "#61", before the title; none for an item with no ticket. */
95
+ reference?: string;
96
+ title: string;
97
+ /** The repository's icon, when the list mixes repositories, and the meta line's text: its name and age. */
98
+ repoIcon?: ReactNode;
99
+ meta: string;
100
+ /** After the meta line: the item's kind, labels and sync state. */
101
+ chips?: ReactNode;
102
+ /** More under the meta line, such as a work item's fields. */
103
+ details?: ReactNode;
104
+ }
105
+
106
+ /** An item in the List's right pane, opening the item dialog. */
107
+ export function ListItemRow({
108
+ item,
109
+ name,
110
+ onOpen,
111
+ source,
112
+ reference,
113
+ title,
114
+ repoIcon,
115
+ meta,
116
+ chips,
117
+ details,
118
+ }: ListItemRowProps) {
119
+ return (
120
+ <button
121
+ type="button"
122
+ onClick={onOpen}
123
+ data-item={item}
124
+ title={name}
125
+ className="hover:bg-base-200/70 focus-visible:outline-primary flex w-full min-w-0 items-start gap-2 rounded-md px-2 py-1.5 text-left focus-visible:outline-2 focus-visible:-outline-offset-2"
126
+ >
127
+ {source}
128
+ <span className="min-w-0 flex-1">
129
+ <span className="text-base-content block truncate text-[13px] leading-5 font-medium">
130
+ {reference ? <span className="text-base-700 font-normal">{reference} </span> : null}
131
+ {title}
132
+ </span>
133
+ <span className="flex min-w-0 flex-wrap items-center gap-x-1.5 gap-y-1">
134
+ <span className="text-base-700 me-1 flex min-w-0 items-center gap-1 text-[11px] leading-4">
135
+ {repoIcon}
136
+ <span className="min-w-0 truncate tabular-nums">{meta}</span>
137
+ </span>
138
+ {chips}
139
+ </span>
140
+ {details}
141
+ </span>
142
+ </button>
143
+ );
144
+ }
145
+
146
+ /** What the List says in place of items: nothing matches, nothing in List, or still loading. With `reading`, it
147
+ * follows items as more may arrive. */
148
+ export function ListNote({ children, reading = false }: { children: ReactNode; reading?: boolean }) {
149
+ return (
150
+ <p className={`text-base-700 m-0 p-4 text-sm ${reading ? '' : 'empty'}`} data-reading={reading || undefined}>
151
+ {children}
152
+ </p>
153
+ );
154
+ }
@@ -0,0 +1,78 @@
1
+ /** The Lar mark's paths on its viewBox, drawn in the order the screen animates them. */
2
+ export interface LoadingMark {
3
+ viewBox: string;
4
+ /** The block, which springs in first, in the brand's block colour. */
5
+ block: string;
6
+ blockColor: string;
7
+ /** The L's centre line, which a stroke `bar` wide traces around the block. */
8
+ centreLine: string;
9
+ bar: number;
10
+ /** The filled L, which stands in for the trace once it is drawn. */
11
+ l: string;
12
+ }
13
+
14
+ /** A line of the screen's step text; a new `id` rolls it in. */
15
+ export interface LoadingLine {
16
+ id: number;
17
+ text: string;
18
+ }
19
+
20
+ interface LoadingScreenProps {
21
+ mark: LoadingMark;
22
+ /** The product's name after the lockup's "ar", such as "Factory". */
23
+ product: string;
24
+ /** Whether the mark is already drawn, as by the desktop's starting page; otherwise it plays its draw. */
25
+ drawn: boolean;
26
+ /** Fades the screen out, once. */
27
+ leaving: boolean;
28
+ /** The step line, and for a moment after a change the old one rolling out. */
29
+ line: LoadingLine;
30
+ leavingLine?: LoadingLine;
31
+ /** Whether the line rolled in; the first line and every line under reduced motion just show. */
32
+ rolled: boolean;
33
+ }
34
+
35
+ /**
36
+ * The board's loading screen: the Lar lockup, whose L draws itself around the block, over one line naming the first
37
+ * read's step. It covers the window, drags it, and fades out once.
38
+ */
39
+ export function LoadingScreen({ mark, product, drawn, leaving, line, leavingLine, rolled }: LoadingScreenProps) {
40
+ return (
41
+ <div className={`loading-screen ${drawn ? 'is-drawn' : ''} ${leaving ? 'is-leaving' : ''}`}>
42
+ <div className="loading-lockup">
43
+ <div className="loading-wordmark">
44
+ <svg className="loading-mark" viewBox={mark.viewBox} aria-hidden>
45
+ <path className="loading-mark-block" d={mark.block} fill={mark.blockColor} />
46
+ <path
47
+ className="loading-mark-trace"
48
+ d={mark.centreLine}
49
+ pathLength={1}
50
+ fill="none"
51
+ stroke="currentColor"
52
+ strokeWidth={mark.bar}
53
+ strokeLinecap="butt"
54
+ strokeLinejoin="miter"
55
+ />
56
+ <path className="loading-mark-fill" d={mark.l} fill="currentColor" />
57
+ </svg>
58
+ <span className="loading-lar">
59
+ <span className="loading-lar-slide">ar</span>
60
+ </span>
61
+ <span className="loading-factory">{product}</span>
62
+ </div>
63
+ <p className="loading-line" role="status">
64
+ <span className="loading-line-slot">
65
+ {leavingLine && (
66
+ <span key={leavingLine.id} className="loading-roll-out" aria-hidden>
67
+ {leavingLine.text}
68
+ </span>
69
+ )}
70
+ <span key={line.id} className={rolled ? 'loading-roll-in' : undefined}>
71
+ {line.text}
72
+ </span>
73
+ </span>
74
+ </p>
75
+ </div>
76
+ </div>
77
+ );
78
+ }
@@ -0,0 +1,30 @@
1
+ // Why a piece of work waits on the user, in the item dialog: the reason and the choices the board offers for it.
2
+
3
+ import type { ReactNode } from 'react';
4
+
5
+ import { WARNING_PANEL } from './RowStyles';
6
+
7
+ /** The reason a piece of work needs you, in the warning tone, then the `actions` that answer it and any `result`. */
8
+ export function NeedsYouNotice({
9
+ reason,
10
+ actions,
11
+ children,
12
+ }: {
13
+ reason: ReactNode;
14
+ actions: ReactNode;
15
+ /** What the last choice left to say, under the actions. */
16
+ children?: ReactNode;
17
+ }) {
18
+ return (
19
+ <div className={`grid gap-2 ${WARNING_PANEL}`} data-needs-you-reason>
20
+ <p className="m-0 font-medium text-(--warning-foreground)">{reason}</p>
21
+ <span className="flex flex-wrap gap-1.5">{actions}</span>
22
+ {children}
23
+ </div>
24
+ );
25
+ }
26
+
27
+ /** What a choice's cleanup left to say, announced. */
28
+ export function NeedsYouResult({ children }: { children: ReactNode }) {
29
+ return <p role="alert">{children}</p>;
30
+ }
@@ -0,0 +1,124 @@
1
+ // Lar Factory's onboarding: the empty board's area, the cards of Projects still setting up, the setup dialog's
2
+ // progress and steps, and the T3 projects its first step lists.
3
+
4
+ import { FolderPlusIcon } from 'lucide-react';
5
+ import type { ReactNode } from 'react';
6
+
7
+ import { Badge } from '../display/Badge';
8
+ import type { DataAttributes } from './DataAttributes';
9
+
10
+ /** The board's main area while it has nothing to show, such as before its first Project: it scrolls on its own. */
11
+ export function EmptyBoard({ children, ...data }: { children: ReactNode } & DataAttributes) {
12
+ return (
13
+ <div {...data} className="min-h-0 flex-1 overflow-y-auto">
14
+ {children}
15
+ </div>
16
+ );
17
+ }
18
+
19
+ /** The cards of Projects still setting up, above the board: at most about a third of its height, then scrolling. */
20
+ export function SetupCardList({ children }: { children: ReactNode }) {
21
+ return <div className="grid max-h-[35%] shrink-0 gap-2 overflow-y-auto">{children}</div>;
22
+ }
23
+
24
+ /** The setup dialog's place under its title: the Project's `icon` beside the `place` line, over the `progress` bar. */
25
+ export function SetupHeader({ icon, place, progress }: { icon?: ReactNode; place: ReactNode; progress: ReactNode }) {
26
+ return (
27
+ <div className="grid shrink-0 gap-2 px-5 pb-4 sm:px-6">
28
+ <div className="flex min-w-0 items-center gap-2">
29
+ {icon}
30
+ {place}
31
+ </div>
32
+ {progress}
33
+ </div>
34
+ );
35
+ }
36
+
37
+ /** A setup step's parts, one under the other: close together for a list of `checks`, further apart for a `form`'s
38
+ * groups. */
39
+ export function SetupStep({
40
+ presentation = 'checks',
41
+ children,
42
+ ...data
43
+ }: { presentation?: 'checks' | 'form'; children: ReactNode } & DataAttributes) {
44
+ return (
45
+ <div {...data} className={`grid min-w-0 ${presentation === 'form' ? 'gap-5' : 'gap-3'}`}>
46
+ {children}
47
+ </div>
48
+ );
49
+ }
50
+
51
+ /**
52
+ * A T3 project on one line: its `icon`, its `name` and `badge`, then its `path`, which gives way first, with the
53
+ * `fullPath` on hover and for screen readers. A long name leaves room for some path beside the badge on a narrow page,
54
+ * and takes at most half the line from sm up.
55
+ */
56
+ export function ProjectLine({
57
+ icon,
58
+ name,
59
+ badge,
60
+ path,
61
+ fullPath,
62
+ }: {
63
+ icon: ReactNode;
64
+ name: string;
65
+ badge?: string | null | undefined;
66
+ path: string;
67
+ fullPath: string;
68
+ }) {
69
+ return (
70
+ <span className="flex min-w-0 flex-1 items-center gap-2 text-sm">
71
+ {icon}
72
+ <span title={name} className="max-w-[30%] shrink-0 truncate font-medium sm:max-w-1/2">
73
+ {name}
74
+ </span>
75
+ {badge && (
76
+ <span className="shrink-0 whitespace-nowrap">
77
+ <Badge>{badge}</Badge>
78
+ </span>
79
+ )}
80
+ <span
81
+ data-project-path
82
+ aria-hidden
83
+ title={fullPath}
84
+ className="text-base-700 min-w-0 flex-1 truncate text-xs"
85
+ >
86
+ {path}
87
+ </span>
88
+ <span className="sr-only">{fullPath}</span>
89
+ </span>
90
+ );
91
+ }
92
+
93
+ /** The choice that adds a folder as a new project: the folder icon, its `title`, then a muted `hint` that gives way. */
94
+ export function AddFolderLine({ title, hint }: { title: string; hint: string }) {
95
+ return (
96
+ <span className="flex min-w-0 flex-1 items-center gap-2">
97
+ <FolderPlusIcon aria-hidden className="size-4 shrink-0" />
98
+ <span className="min-w-0 font-medium wrap-anywhere">{title}</span>
99
+ <span className="text-base-700 min-w-0 flex-1 truncate text-xs">{hint}</span>
100
+ </span>
101
+ );
102
+ }
103
+
104
+ /** What a choice asks for once picked, such as the folder to add, framed under the choices. */
105
+ export function ChoiceDetails({ children }: { children: ReactNode }) {
106
+ return <div className="grid gap-3 rounded-lg border p-3">{children}</div>;
107
+ }
108
+
109
+ /** A list of projects that can't be picked, such as in a framed Disclosure. */
110
+ export function ProjectList({ children }: { children: ReactNode }) {
111
+ return <ul className="m-0 grid min-w-0 list-none gap-2 p-0">{children}</ul>;
112
+ }
113
+
114
+ /** A project in a ProjectList, with the `reason` it can't be picked under it, lined up with its name. */
115
+ export function ProjectListItem({ reason, children }: { reason?: string | undefined; children: ReactNode }) {
116
+ if (reason === undefined) return <li className="flex min-w-0">{children}</li>;
117
+
118
+ return (
119
+ <li className="grid min-w-0 gap-0.5">
120
+ {children}
121
+ <span className="text-base-700 pl-6 text-xs">{reason}</span>
122
+ </li>
123
+ );
124
+ }