rift-ds 1.9.0 → 1.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 (377) hide show
  1. package/README.md +3 -3
  2. package/behaviors/useFocusScope.d.ts +12 -6
  3. package/behaviors/useFocusScope.js +12 -2
  4. package/behaviors/useLayer.d.ts +39 -15
  5. package/behaviors/useLayer.js +23 -11
  6. package/bin/templates/chat/app/api/chat/route.ts +3 -0
  7. package/chat/AssistantTurn.d.ts +18 -1
  8. package/chat/AssistantTurn.js +25 -5
  9. package/chat/ChatAgentPane.d.ts +22 -4
  10. package/chat/ChatAgentPane.js +20 -6
  11. package/chat/ChatArtifactPane.d.ts +16 -1
  12. package/chat/ChatArtifactPane.js +12 -10
  13. package/chat/ChatLauncher.d.ts +12 -5
  14. package/chat/ChatLauncher.js +3 -1
  15. package/chat/ChatProvider.d.ts +5 -4
  16. package/chat/ChatProvider.js +1 -1
  17. package/chat/ChatTabs.d.ts +6 -1
  18. package/chat/ChatTabs.js +3 -2
  19. package/chat/ChatThreads.d.ts +19 -4
  20. package/chat/ChatThreads.js +22 -3
  21. package/chat/ChatWidget.css +5 -4
  22. package/chat/ChatWidget.d.ts +119 -5
  23. package/chat/ChatWidget.js +159 -70
  24. package/chat/DemoWelcome.js +17 -5
  25. package/chat/FollowupSuggestions.d.ts +10 -4
  26. package/chat/FollowupSuggestions.js +13 -5
  27. package/chat/ResponseActions.d.ts +14 -0
  28. package/chat/ResponseActions.js +15 -6
  29. package/chat/TurnQuestion.d.ts +24 -0
  30. package/chat/TurnQuestion.js +46 -0
  31. package/chat/demo-card-components.js +2 -1
  32. package/chat/demo-script.js +256 -50
  33. package/chat/followups.d.ts +2 -2
  34. package/chat/followups.js +1 -0
  35. package/chat/index.d.ts +3 -2
  36. package/chat/index.js +11 -0
  37. package/chat/queries.d.ts +2 -2
  38. package/chat/queries.js +3 -2
  39. package/chat/questions.d.ts +97 -0
  40. package/chat/questions.js +140 -0
  41. package/chat/registry.json.d.ts +3 -2
  42. package/chat/registry.json.js +1 -1
  43. package/chat/server.d.ts +19 -0
  44. package/chat/server.js +45 -1
  45. package/chat/sim.d.ts +12 -1
  46. package/chat/sim.js +19 -3
  47. package/chat/threads.d.ts +17 -0
  48. package/chat/threads.js +22 -14
  49. package/chat/types.d.ts +58 -1
  50. package/chat/types.js +1 -0
  51. package/chat/useChat.d.ts +24 -3
  52. package/chat/useChat.js +42 -4
  53. package/components/Accordion/Accordion.d.ts +18 -3
  54. package/components/Accordion/Accordion.js +71 -69
  55. package/components/AgentPlan/AgentPlan.d.ts +16 -0
  56. package/components/AgentPlan/AgentPlan.js +8 -3
  57. package/components/AgentRail/AgentRail.d.ts +24 -4
  58. package/components/AgentRail/AgentRail.js +13 -6
  59. package/components/AgentStatus/AgentStatus.css +1 -0
  60. package/components/AiButton/AiButton.css +3 -1
  61. package/components/AiButton/AiButton.d.ts +7 -1
  62. package/components/AiButton/AiButton.js +6 -3
  63. package/components/Alert/Alert.d.ts +15 -4
  64. package/components/Alert/Alert.js +46 -40
  65. package/components/AlertDialog/AlertDialog.css +1 -1
  66. package/components/AlertDialog/AlertDialog.d.ts +21 -5
  67. package/components/AlertDialog/AlertDialog.js +34 -15
  68. package/components/AnchorNav/AnchorNav.css +1 -1
  69. package/components/AnchorNav/AnchorNav.d.ts +4 -1
  70. package/components/AnchorNav/AnchorNav.js +8 -8
  71. package/components/AppLayout/AppLayout.d.ts +10 -2
  72. package/components/AppLayout/AppLayout.js +55 -42
  73. package/components/AppSidebar/AppSidebar.css +9 -9
  74. package/components/AppSidebar/AppSidebar.d.ts +27 -2
  75. package/components/AppSidebar/AppSidebar.js +30 -15
  76. package/components/ArtifactPanel/ArtifactPanel.d.ts +3 -0
  77. package/components/ArtifactPanel/ArtifactPanel.js +6 -5
  78. package/components/Attachment/Attachment.css +4 -1
  79. package/components/Attachment/AttachmentGroup.d.ts +6 -0
  80. package/components/Attachment/AttachmentGroup.js +10 -1
  81. package/components/Attachment/AttachmentTile.d.ts +2 -0
  82. package/components/Attachment/AttachmentTile.js +3 -2
  83. package/components/Attachment/AttachmentViewer.js +4 -4
  84. package/components/Attachment/fileTypes.d.ts +8 -0
  85. package/components/Avatar/Avatar.css +3 -3
  86. package/components/Avatar/Avatar.d.ts +11 -3
  87. package/components/Avatar/Avatar.js +56 -51
  88. package/components/AvatarGroup/AvatarGroup.css +3 -3
  89. package/components/AvatarGroup/AvatarGroup.d.ts +6 -3
  90. package/components/AvatarGroup/AvatarGroup.js +5 -2
  91. package/components/Badge/Badge.d.ts +9 -2
  92. package/components/Badge/Badge.js +10 -10
  93. package/components/Banner/Banner.d.ts +2 -0
  94. package/components/Banner/Banner.js +2 -1
  95. package/components/BentoTile/BentoTile.css +527 -0
  96. package/components/BentoTile/BentoTile.d.ts +64 -0
  97. package/components/BentoTile/BentoTile.js +303 -0
  98. package/components/BentoTile/BentoTileArt.d.ts +28 -0
  99. package/components/BentoTile/BentoTileArt.js +19 -0
  100. package/components/BottomNav/BottomNav.css +3 -3
  101. package/components/BottomNav/BottomNav.d.ts +6 -0
  102. package/components/BottomNav/BottomNav.js +3 -1
  103. package/components/Breadcrumb/Breadcrumb.d.ts +16 -5
  104. package/components/Breadcrumb/Breadcrumb.js +32 -33
  105. package/components/Button/Button.css +123 -20
  106. package/components/Button/Button.d.ts +18 -3
  107. package/components/Button/Button.js +19 -2
  108. package/components/ButtonGroup/ButtonGroup.d.ts +17 -3
  109. package/components/ButtonGroup/ButtonGroup.js +24 -24
  110. package/components/CardStack/CardStack.d.ts +5 -0
  111. package/components/CardStack/CardStack.js +3 -7
  112. package/components/Carousel/Carousel.d.ts +33 -3
  113. package/components/Carousel/Carousel.js +178 -137
  114. package/components/Chart/AreaChart.d.ts +11 -3
  115. package/components/Chart/AreaChart.js +20 -11
  116. package/components/Chart/BarChart.d.ts +11 -3
  117. package/components/Chart/BarChart.js +19 -9
  118. package/components/Chart/Chart.css +1 -0
  119. package/components/Chart/ComboChart.d.ts +11 -3
  120. package/components/Chart/ComboChart.js +21 -11
  121. package/components/Chart/LineChart.d.ts +11 -3
  122. package/components/Chart/LineChart.js +19 -10
  123. package/components/Chart/PieChart.d.ts +11 -3
  124. package/components/Chart/PieChart.js +18 -9
  125. package/components/Chart/RadarChart.d.ts +11 -3
  126. package/components/Chart/RadarChart.js +20 -11
  127. package/components/Chart/RadialChart.d.ts +11 -3
  128. package/components/Chart/RadialChart.js +18 -9
  129. package/components/Chart/ScatterChart.d.ts +11 -3
  130. package/components/Chart/ScatterChart.js +23 -11
  131. package/components/Chart/StackedBarChart.d.ts +11 -3
  132. package/components/Chart/StackedBarChart.js +19 -10
  133. package/components/Chart/Treemap.d.ts +13 -3
  134. package/components/Chart/Treemap.js +23 -13
  135. package/components/Chart/palette.d.ts +9 -0
  136. package/components/Chart/palette.js +8 -1
  137. package/components/Chart/useChartAnimation.d.ts +42 -0
  138. package/components/Chart/useChartAnimation.js +32 -0
  139. package/components/ChatMessage/ChatMessage.css +1 -0
  140. package/components/ChatThread/ChatThread.css +21 -0
  141. package/components/ChatThread/ChatThread.d.ts +12 -1
  142. package/components/ChatThread/ChatThread.js +48 -1
  143. package/components/Checkbox/Checkbox.d.ts +12 -2
  144. package/components/Checkbox/Checkbox.js +13 -3
  145. package/components/Chip/Chip.css +24 -1
  146. package/components/Chip/Chip.d.ts +28 -7
  147. package/components/Chip/Chip.js +80 -64
  148. package/components/CircularButton/CircularButton.css +127 -1
  149. package/components/CircularButton/CircularButton.d.ts +18 -4
  150. package/components/CircularButton/CircularButton.js +14 -2
  151. package/components/CodeBlock/CodeBlock.d.ts +24 -3
  152. package/components/CodeBlock/CodeBlock.js +93 -80
  153. package/components/CodeDiff/CodeDiff.d.ts +30 -4
  154. package/components/CodeDiff/CodeDiff.js +64 -20
  155. package/components/ColorPicker/ColorPicker.css +1 -1
  156. package/components/ColorPicker/ColorPicker.d.ts +18 -0
  157. package/components/ColorPicker/ColorPicker.js +27 -21
  158. package/components/ColourSwatch/ColourSwatch.css +1 -1
  159. package/components/Combobox/Combobox.css +2 -1
  160. package/components/Combobox/Combobox.d.ts +26 -8
  161. package/components/Combobox/Combobox.js +30 -17
  162. package/components/CommandPalette/CommandPalette.css +13 -1
  163. package/components/CommandPalette/CommandPalette.d.ts +27 -4
  164. package/components/CommandPalette/CommandPalette.js +108 -70
  165. package/components/Composer/Composer.css +2 -1
  166. package/components/Composer/Composer.d.ts +10 -0
  167. package/components/Composer/Composer.js +7 -0
  168. package/components/ContactCard/ContactCard.css +1 -1
  169. package/components/ContactCard/ContactCard.d.ts +34 -5
  170. package/components/ContactCard/ContactCard.js +72 -58
  171. package/components/ContextMenu/ContextMenu.css +4 -4
  172. package/components/ContextMenu/ContextMenu.js +7 -10
  173. package/components/ContributionGraph/ContributionGraph.d.ts +37 -3
  174. package/components/ContributionGraph/ContributionGraph.js +32 -31
  175. package/components/DataTable/DataTable.d.ts +29 -0
  176. package/components/DataTable/DataTable.js +15 -10
  177. package/components/DateInput/DateInput.js +2 -2
  178. package/components/DatePicker/DatePicker.css +19 -4
  179. package/components/DatePicker/DatePicker.d.ts +31 -0
  180. package/components/DatePicker/DatePicker.js +145 -61
  181. package/components/Dialog/Dialog.css +1 -1
  182. package/components/Dialog/Dialog.d.ts +2 -0
  183. package/components/Dialog/Dialog.js +4 -3
  184. package/components/Divider/Divider.d.ts +10 -2
  185. package/components/Divider/Divider.js +56 -25
  186. package/components/DocumentChip/DocumentChip.d.ts +3 -1
  187. package/components/DocumentChip/DocumentChip.js +3 -2
  188. package/components/Drawer/Drawer.css +2 -1
  189. package/components/Drawer/Drawer.d.ts +2 -0
  190. package/components/Drawer/Drawer.js +4 -3
  191. package/components/Dropdown/Dropdown.css +1 -1
  192. package/components/Dropdown/Dropdown.d.ts +9 -2
  193. package/components/Dropdown/Dropdown.js +26 -16
  194. package/components/DropdownMenu/DropdownMenu.css +5 -5
  195. package/components/DropdownMenu/DropdownMenu.d.ts +13 -4
  196. package/components/DropdownMenu/DropdownMenu.js +41 -22
  197. package/components/EmptyState/EmptyState.d.ts +12 -4
  198. package/components/EmptyState/EmptyState.js +30 -26
  199. package/components/EntityCard/EntityCard.d.ts +7 -2
  200. package/components/EntityCard/EntityCard.js +19 -21
  201. package/components/EventCalendar/EventCalendar.d.ts +28 -0
  202. package/components/EventCalendar/EventCalendar.js +29 -27
  203. package/components/Figure/Figure.d.ts +14 -5
  204. package/components/Figure/Figure.js +19 -21
  205. package/components/FileInput/FileInput.d.ts +6 -0
  206. package/components/FileInput/FileInput.js +9 -9
  207. package/components/FilterBar/FilterBar.css +3 -3
  208. package/components/FilterBar/FilterBar.d.ts +6 -1
  209. package/components/FilterBar/FilterBar.js +15 -11
  210. package/components/FunnelChart/FunnelChart.d.ts +13 -1
  211. package/components/FunnelChart/FunnelChart.js +8 -1
  212. package/components/GanttChart/GanttChart.css +1 -1
  213. package/components/GanttChart/GanttChart.d.ts +19 -2
  214. package/components/GanttChart/GanttChart.js +17 -8
  215. package/components/Gauge/Gauge.d.ts +4 -1
  216. package/components/Globe/Globe.css +23 -0
  217. package/components/Globe/Globe.d.ts +19 -2
  218. package/components/Globe/Globe.js +66 -19
  219. package/components/HoverCard/HoverCard.css +1 -1
  220. package/components/HoverCard/HoverCard.d.ts +4 -1
  221. package/components/HoverCard/HoverCard.js +26 -15
  222. package/components/ImageCompare/ImageCompare.d.ts +4 -0
  223. package/components/ImageCompare/ImageCompare.js +4 -2
  224. package/components/Input/Input.js +2 -2
  225. package/components/Inspector/Inspector.css +55 -38
  226. package/components/Inspector/InspectorDropdown.d.ts +6 -1
  227. package/components/Inspector/InspectorDropdown.js +2 -0
  228. package/components/Inspector/InspectorSegmentedControl.d.ts +4 -3
  229. package/components/Inspector/InspectorSegmentedControl.js +63 -11
  230. package/components/Inspector/InspectorToggleSwitch.d.ts +4 -3
  231. package/components/Inspector/InspectorToggleSwitch.js +35 -2
  232. package/components/Instructions/Instructions.css +1 -1
  233. package/components/Instructions/Instructions.d.ts +16 -5
  234. package/components/Instructions/Instructions.js +31 -26
  235. package/components/InterruptCard/InterruptCard.d.ts +13 -2
  236. package/components/InterruptCard/InterruptCard.js +9 -7
  237. package/components/Lightbox/Lightbox.css +1 -1
  238. package/components/Lightbox/Lightbox.d.ts +8 -0
  239. package/components/Lightbox/Lightbox.js +10 -6
  240. package/components/LinkList/LinkList.css +2 -2
  241. package/components/LinkList/LinkList.d.ts +11 -2
  242. package/components/LinkList/LinkList.js +40 -36
  243. package/components/Mention/Mention.d.ts +4 -1
  244. package/components/MessageActions/MessageActions.css +8 -0
  245. package/components/MessageActions/MessageActions.d.ts +2 -0
  246. package/components/MessageActions/MessageActions.js +2 -1
  247. package/components/MessageCard/MessageCard.d.ts +4 -1
  248. package/components/Meter/Meter.d.ts +5 -1
  249. package/components/ModelPicker/ModelPicker.css +2 -2
  250. package/components/ModelPicker/ModelPicker.d.ts +12 -1
  251. package/components/ModelPicker/ModelPicker.js +27 -16
  252. package/components/MotionSwatch/MotionSwatch.d.ts +3 -1
  253. package/components/MotionSwatch/MotionSwatch.js +2 -1
  254. package/components/Nav/Nav.d.ts +2 -2
  255. package/components/Nav/Nav.js +17 -21
  256. package/components/NavList/NavList.d.ts +4 -0
  257. package/components/NavList/NavList.js +3 -1
  258. package/components/NotificationCenter/NotificationCenter.css +1 -1
  259. package/components/NotificationCenter/NotificationCenter.d.ts +48 -5
  260. package/components/NotificationCenter/NotificationCenter.js +32 -15
  261. package/components/NumberInput/NumberInput.d.ts +4 -0
  262. package/components/NumberInput/NumberInput.js +4 -2
  263. package/components/Pagination/Pagination.d.ts +33 -7
  264. package/components/Pagination/Pagination.js +67 -55
  265. package/components/PinInput/PinInput.d.ts +6 -0
  266. package/components/PinInput/PinInput.js +3 -1
  267. package/components/Popover/Popover.css +1 -1
  268. package/components/Popover/Popover.d.ts +21 -5
  269. package/components/Popover/Popover.js +102 -97
  270. package/components/ProgressBar/ProgressBar.d.ts +10 -3
  271. package/components/ProgressBar/ProgressBar.js +34 -22
  272. package/components/PromptSuggestions/PromptSuggestions.css +67 -0
  273. package/components/PromptSuggestions/PromptSuggestions.d.ts +10 -0
  274. package/components/PromptSuggestions/PromptSuggestions.js +41 -26
  275. package/components/QuestionCard/QuestionCard.css +358 -0
  276. package/components/QuestionCard/QuestionCard.d.ts +138 -0
  277. package/components/QuestionCard/QuestionCard.js +378 -0
  278. package/components/Quote/Quote.d.ts +8 -3
  279. package/components/Quote/Quote.js +18 -21
  280. package/components/RadioButton/RadioButton.d.ts +6 -1
  281. package/components/RadioButton/RadioButton.js +7 -2
  282. package/components/Rating/Rating.d.ts +6 -0
  283. package/components/Rating/Rating.js +4 -2
  284. package/components/Reasoning/Reasoning.css +1 -0
  285. package/components/Reasoning/Reasoning.d.ts +7 -1
  286. package/components/Reasoning/Reasoning.js +4 -1
  287. package/components/RichDropdown/RichDropdown.css +1 -1
  288. package/components/RichDropdown/RichDropdown.d.ts +3 -1
  289. package/components/RichDropdown/RichDropdown.js +20 -15
  290. package/components/SectionTitle/SectionTitle.d.ts +15 -3
  291. package/components/SectionTitle/SectionTitle.js +15 -17
  292. package/components/SegmentedControl/SegmentedControl.css +3 -2
  293. package/components/SegmentedControl/SegmentedControl.d.ts +49 -7
  294. package/components/SegmentedControl/SegmentedControl.js +248 -223
  295. package/components/SelectionCard/SelectionCard.d.ts +7 -1
  296. package/components/SelectionCard/SelectionCard.js +16 -2
  297. package/components/ShaderField/ShaderField.js +2 -1
  298. package/components/ShaderField/useShaderField.js +3 -2
  299. package/components/SidebarPanel/SidebarPanel.d.ts +6 -1
  300. package/components/SidebarPanel/SidebarPanel.js +2 -1
  301. package/components/Skeleton/Skeleton.d.ts +12 -3
  302. package/components/Skeleton/Skeleton.js +53 -19
  303. package/components/Slider/Slider.d.ts +11 -2
  304. package/components/Slider/Slider.js +11 -6
  305. package/components/SourceChip/SourceChip.css +1 -1
  306. package/components/SourceChip/SourceChip.d.ts +5 -2
  307. package/components/SourceChip/SourceChip.js +14 -13
  308. package/components/SourceTrail/SourceTrail.d.ts +15 -0
  309. package/components/SourceTrail/SourceTrail.js +10 -4
  310. package/components/Sparkline/Sparkline.d.ts +4 -3
  311. package/components/Sparkline/Sparkline.js +2 -1
  312. package/components/Spinner/Spinner.d.ts +21 -4
  313. package/components/Spinner/Spinner.js +38 -37
  314. package/components/SplitButton/SplitButton.d.ts +10 -1
  315. package/components/SplitButton/SplitButton.js +13 -3
  316. package/components/Stat/Stat.d.ts +7 -2
  317. package/components/Stat/Stat.js +30 -25
  318. package/components/StatusDot/StatusDot.css +1 -0
  319. package/components/Stepper/Stepper.css +13 -0
  320. package/components/Stepper/Stepper.d.ts +6 -0
  321. package/components/Stepper/Stepper.js +2 -0
  322. package/components/StreamingText/StreamingText.d.ts +4 -4
  323. package/components/StreamingText/StreamingText.js +3 -2
  324. package/components/Tabs/Tabs.d.ts +41 -6
  325. package/components/Tabs/Tabs.js +99 -69
  326. package/components/TagInput/TagInput.d.ts +2 -0
  327. package/components/TagInput/TagInput.js +7 -2
  328. package/components/Textarea/Textarea.d.ts +6 -1
  329. package/components/Textarea/Textarea.js +11 -5
  330. package/components/ThreadPanel/ThreadPanel.css +1 -1
  331. package/components/ThreadPanel/ThreadPanel.d.ts +11 -4
  332. package/components/ThreadPanel/ThreadPanel.js +3 -1
  333. package/components/ThreadTabs/ThreadTabs.d.ts +7 -2
  334. package/components/ThreadTabs/ThreadTabs.js +1 -1
  335. package/components/TimePicker/TimePicker.css +1 -1
  336. package/components/TimePicker/TimePicker.d.ts +14 -1
  337. package/components/TimePicker/TimePicker.js +22 -17
  338. package/components/Timeline/Timeline.css +2 -2
  339. package/components/Timeline/Timeline.d.ts +11 -2
  340. package/components/Timeline/Timeline.js +37 -26
  341. package/components/Toast/Toast.css +2 -2
  342. package/components/Toast/Toast.d.ts +24 -6
  343. package/components/Toast/Toast.js +50 -41
  344. package/components/ToggleGroup/ToggleGroup.css +3 -2
  345. package/components/ToggleGroup/ToggleGroup.d.ts +26 -4
  346. package/components/ToggleGroup/ToggleGroup.js +12 -5
  347. package/components/ToggleSwitch/ToggleSwitch.d.ts +6 -1
  348. package/components/ToggleSwitch/ToggleSwitch.js +7 -2
  349. package/components/ToolCall/ToolCall.js +1 -1
  350. package/components/Tooltip/Tooltip.css +5 -5
  351. package/components/Tooltip/Tooltip.d.ts +15 -4
  352. package/components/Tooltip/Tooltip.js +80 -61
  353. package/components/TopAppBar/TopAppBar.css +1 -1
  354. package/components/TopAppBar/TopAppBar.d.ts +9 -1
  355. package/components/TopAppBar/TopAppBar.js +3 -1
  356. package/components/TypographySwatch/TypographySwatch.css +1 -1
  357. package/components/UsageCard/UsageCard.d.ts +4 -1
  358. package/components/Waveform/Waveform.css +1 -0
  359. package/components/Waveform/Waveform.d.ts +1 -1
  360. package/components/WorldMap/WorldMap.d.ts +12 -0
  361. package/components/WorldMap/WorldMap.js +11 -5
  362. package/components/registry.json +44 -19
  363. package/components/registry.json.d.ts +44 -19
  364. package/components/registry.json.js +1 -1
  365. package/index.d.ts +3 -0
  366. package/index.js +7 -0
  367. package/package.json +5 -1
  368. package/tokens/breakpoints.d.ts +60 -0
  369. package/tokens/breakpoints.js +92 -0
  370. package/tokens/motion.d.ts +14 -0
  371. package/tokens/motion.js +15 -1
  372. package/tokens/registry.d.ts +1 -1
  373. package/tokens/registry.json +21 -0
  374. package/tokens/registry.json.d.ts +21 -0
  375. package/tokens/registry.json.js +1 -1
  376. package/tokens/tokens-dark.css +7 -0
  377. package/tokens/tokens-light.css +41 -0
package/README.md CHANGED
@@ -13,7 +13,7 @@ An open source React design system built for AI products and coding agents: comp
13
13
 
14
14
  ## Why Rift DS
15
15
 
16
- - **<!-- component-count -->152<!-- /component-count --> components.** Buttons, forms and tables through to charts, navigation and overlays, each typed and documented with live examples. React is the only required peer dependency.
16
+ - **<!-- component-count -->155<!-- /component-count --> components.** Buttons, forms and tables through to charts, navigation and overlays, each typed and documented with live examples. Every one forwards a ref and your own attributes to its element, state you can own works controlled or uncontrolled (a modal opens when your app says so, by design), and every word a component writes has a prop you can localise. The build checks the first two on every component, and the words wherever they sit in markup. React and React DOM are the only required peer dependencies.
17
17
  - **AI patterns, the whole chat and templates, ready to use.** Composer, streaming chat thread, tool calls, reasoning and thread panel are in the box, the complete AI chat ships assembled as one widget that one command scaffolds, and the docs site has complete template screens built from them.
18
18
  - **Fully themeable.** The shipped themes are complete looks to start from, each in light and dark. One `data-brand` attribute applies a theme, and a few CSS overrides make your own.
19
19
  - **Ready for coding agents.** One command installs the agent skills, and a public MCP endpoint serves every component's props, so your agent builds with the library as it actually is. No key, no account.
@@ -94,13 +94,13 @@ import 'rift-ds/tokens/presets/presets.css';
94
94
 
95
95
  ## Components
96
96
 
97
- <!-- component-count -->152<!-- /component-count --> components, including a chat set for AI products (Chat thread, Composer, Tool call, Reasoning, Thread panel) and Shader field, a WebGL2 ambient background whose light sources read your colour tokens at runtime, so it re-themes with everything else. Details and live examples are on the [docs site](https://rift-ds.com/components).
97
+ <!-- component-count -->155<!-- /component-count --> components, including a chat set for AI products (Chat thread, Composer, Tool call, Reasoning, Thread panel) and Shader field, a WebGL2 ambient background whose light sources read your colour tokens at runtime, so it re-themes with everything else. Details and live examples are on the [docs site](https://rift-ds.com/components).
98
98
 
99
99
  <details>
100
100
  <summary>The full list</summary>
101
101
 
102
102
  <!-- component-list:start -->
103
- Accordion · Agent plan · Agent rail · Agent status · AI button · Alert · Alert dialog · Anchor nav · Animated number · App layout · App sidebar · Area chart · Artifact card · Artifact panel · Attachment drop zone · Attachment group · Attachment tile · Attachment viewer · Avatar · Avatar group · Badge · Banner · Bar chart · Bottom nav · Breadcrumb · Button · Button group · Card · Card stack · Carousel · Chat header · Chat marker · Chat message · Chat thread · Checkbox · Chip · Circular button · Code block · Code diff · Colour picker · Combo chart · Combobox · Command palette · Composer · Contact card · Context menu · Contribution graph · Data table · Date input · Date picker · Dialog · Divider · Document chip · Drawer · Dropdown · Dropdown menu · Empty state · Entity card · Event calendar · Field · Figure · File input · Filter bar · Funnel chart · Gantt chart · Gauge · Globe · Hover card · Image compare · Input · Inspector colour picker · Inspector dropdown · Inspector input · Inspector section · Inspector segments · Inspector slider · Inspector toggle switch · Instructions · Interrupt card · Kbd · Legend tile · Lightbox · Line chart · Link list · Map callout · Map legend · Mention · Message actions · Message card · Meter · Model picker · Nav · Nav list · Notification centre · Number input · Pagination · Panel · Pie chart · Pin input · Pixel avatar · Popover · Progress bar · Prompt suggestions · Prose · Quote · Radar chart · Radial chart · Radio button · Rating · Reasoning · Rich dropdown · Scatter chart · Section title · Segmented control · Selection card · Shader field · Sidebar panel · Skeleton · Slider · Source chip · Source trail · Sparkline · Spinner · Split button · Split pane · Stacked bar chart · Stat · Status dot · Stepper · Streaming text · Swatch · Table · Tabs · Tag input · Textarea · Thread panel · Thread tabs · Time picker · Timeline · Toast · Toggle group · Toggle switch · Tool call · Toolbar · Tooltip · Top app bar · Tree view · Treemap · Usage card · Waveform · Widget · World map
103
+ Accordion · Agent plan · Agent rail · Agent status · AI button · Alert · Alert dialog · Anchor nav · Animated number · App layout · App sidebar · Area chart · Artifact card · Artifact panel · Attachment drop zone · Attachment group · Attachment tile · Attachment viewer · Avatar · Avatar group · Badge · Banner · Bar chart · Bento tile · Bento tile art · Bottom nav · Breadcrumb · Button · Button group · Card · Card stack · Carousel · Chat header · Chat marker · Chat message · Chat thread · Checkbox · Chip · Circular button · Code block · Code diff · Colour picker · Combo chart · Combobox · Command palette · Composer · Contact card · Context menu · Contribution graph · Data table · Date input · Date picker · Dialog · Divider · Document chip · Drawer · Dropdown · Dropdown menu · Empty state · Entity card · Event calendar · Field · Figure · File input · Filter bar · Funnel chart · Gantt chart · Gauge · Globe · Hover card · Image compare · Input · Inspector colour picker · Inspector dropdown · Inspector input · Inspector section · Inspector segments · Inspector slider · Inspector toggle switch · Instructions · Interrupt card · Kbd · Legend tile · Lightbox · Line chart · Link list · Map callout · Map legend · Mention · Message actions · Message card · Meter · Model picker · Nav · Nav list · Notification centre · Number input · Pagination · Panel · Pie chart · Pin input · Pixel avatar · Popover · Progress bar · Prompt suggestions · Prose · Question card · Quote · Radar chart · Radial chart · Radio button · Rating · Reasoning · Rich dropdown · Scatter chart · Section title · Segmented control · Selection card · Shader field · Sidebar panel · Skeleton · Slider · Source chip · Source trail · Sparkline · Spinner · Split button · Split pane · Stacked bar chart · Stat · Status dot · Stepper · Streaming text · Swatch · Table · Tabs · Tag input · Textarea · Thread panel · Thread tabs · Time picker · Timeline · Toast · Toggle group · Toggle switch · Tool call · Toolbar · Tooltip · Top app bar · Tree view · Treemap · Usage card · Waveform · Widget · World map
104
104
  <!-- component-list:end -->
105
105
 
106
106
  </details>
@@ -2,11 +2,15 @@
2
2
  * Focus containment for modal overlays: initial focus, Tab wrapping, focus
3
3
  * restore, and background isolation.
4
4
  *
5
- * Restore is guarded by `document.contains` — the element that opened a
6
- * dialog can be gone by the time it closes (a row the dialog itself deleted),
7
- * and restoring into a detached node silently drops focus to `<body>`. It
8
- * also runs when the component unmounts while open, which the per-component
9
- * implementations this replaces never handled.
5
+ * Restore is guarded twice. The element that opened a dialog can be gone by
6
+ * the time it closes (a row the dialog itself deleted), and it can still be in
7
+ * the document but hidden: a button inside a popover that closed underneath
8
+ * the dialog sits in a `display: none` panel, and `.focus()` on it silently
9
+ * drops focus to `<body>`. A detached element is skipped; a hidden one hands
10
+ * focus to the first visible control of its nearest visible ancestor, which
11
+ * for a closed popover is its trigger. It also runs when the component
12
+ * unmounts while open, which the per-component implementations this replaced
13
+ * never handled.
10
14
  *
11
15
  * Background isolation uses `inert`, not `aria-hidden`: a JS focus trap only
12
16
  * fences the Tab key, while a screen reader's virtual cursor walks the page
@@ -17,7 +21,9 @@
17
21
  * inert set is recomputed only when a scope activates or deactivates, so a
18
22
  * portal that mounts *while* a modal is open (a toast, say) is not inerted
19
23
  * until the stack next changes — under `aria-modal` that content is outside
20
- * the dialog's world anyway.
24
+ * the dialog's world anyway. Live regions are never inerted: a toast region
25
+ * (`aria-live`, a direct child of the body) must keep announcing, and keep
26
+ * its actions pressable, while a modal is open.
21
27
  */
22
28
  type FocusScopeOptions = {
23
29
  /** Whether the scope is active — the overlay's open state. */
@@ -8,6 +8,7 @@ const applyInert = () => {
8
8
  for (const child of Array.from(document.body.children)) {
9
9
  if (!(child instanceof HTMLElement)) continue;
10
10
  if (child.tagName === "SCRIPT" || child.tagName === "STYLE") continue;
11
+ if (child.hasAttribute("aria-live")) continue;
11
12
  const shouldBeInert = top !== void 0 && !child.contains(top.panel);
12
13
  if (shouldBeInert && !child.inert) {
13
14
  child.inert = true;
@@ -22,6 +23,15 @@ const applyInert = () => {
22
23
  inerted.clear();
23
24
  }
24
25
  };
26
+ const isVisible = (el) => el.getClientRects().length > 0;
27
+ const restoreTarget = (previous) => {
28
+ if (!document.contains(previous)) return null;
29
+ if (isVisible(previous)) return previous;
30
+ for (let el = previous.parentElement; el && el !== document.body; el = el.parentElement) {
31
+ if (isVisible(el)) return getFocusable(el)[0] ?? null;
32
+ }
33
+ return null;
34
+ };
25
35
  function useFocusScope(ref, options) {
26
36
  const optionsRef = useRef(options);
27
37
  useEffect(() => {
@@ -71,8 +81,8 @@ function useFocusScope(ref, options) {
71
81
  inertScopes.splice(index, 1);
72
82
  applyInert();
73
83
  }
74
- if (optionsRef.current.restoreFocus !== false && previousFocus && document.contains(previousFocus)) {
75
- previousFocus.focus();
84
+ if (optionsRef.current.restoreFocus !== false && previousFocus) {
85
+ restoreTarget(previousFocus)?.focus();
76
86
  }
77
87
  };
78
88
  }, [active, ref]);
@@ -1,19 +1,33 @@
1
1
  /**
2
2
  * The dismissal layer stack — the single owner of the document-level Escape
3
- * and outside-press listeners for every overlay in the library.
3
+ * and outside-press listeners for every overlay in the library, modal and
4
+ * non-modal alike.
4
5
  *
5
6
  * Before this existed, each open overlay registered its own document keydown,
6
- * so Escape over a stacked Dialog-in-Drawer closed both at once. The stack
7
- * routes each interaction to the **topmost** open layer only: Escape
8
- * dismisses it (or is swallowed when it is not Escape-dismissible — a lower
9
- * layer must never close through a blocking one), and an outside press
10
- * dismisses it only when the press lands outside every element the layer
11
- * claims. Layers below are untouched; one press, one layer.
7
+ * so Escape over a stacked Dialog-in-Drawer closed both at once, and a
8
+ * popover or menu open inside a Dialog closed together with it. The stack
9
+ * routes each interaction by stack order:
10
+ *
11
+ * - **Escape** goes to the topmost open layer only: it dismisses it, or is
12
+ * swallowed when that layer is not Escape-dismissible (a lower layer must
13
+ * never close through a blocking one). One press, one layer. An Escape a
14
+ * component has already handled (`event.preventDefault()`, say an input
15
+ * clearing its own text) is left alone.
16
+ * - **An outside press** walks down from the top: every layer the press
17
+ * lands outside of, and that opts into light dismiss, closes; the walk
18
+ * stops at the first layer that contains the press or does not
19
+ * light-dismiss (a modal, which owns its backdrop). So a press on a
20
+ * Dialog's body closes the menus open above it and leaves the Dialog.
21
+ * - **Backdrop clicks** stay with the modal that draws the backdrop, but a
22
+ * press that began while another layer was on top was that layer's press:
23
+ * `ownsPress()` tells the modal so, and it keeps itself open. Without it, a
24
+ * press on the backdrop closed the open menu at pointerdown and then the
25
+ * Dialog on click, two layers for one press.
12
26
  *
13
27
  * Exactly two document listeners exist while any layer is open, and none
14
- * while the stack is empty. Registration order is stack order — overlays
15
- * portal into `document.body` in the order they open, so stack order and
16
- * paint order agree without reading z-index.
28
+ * while the stack is empty. Registration order is stack order: overlays open
29
+ * in the order they are stacked, so stack order and paint order agree
30
+ * without reading z-index.
17
31
  */
18
32
  type LayerOptions = {
19
33
  /** The overlay's open state — the layer registers while true. */
@@ -23,21 +37,31 @@ type LayerOptions = {
23
37
  /** Whether Escape dismisses this layer. Default true. */
24
38
  dismissOnEscape?: boolean;
25
39
  /**
26
- * Whether a pointerdown outside `getElements()` dismisses this layer.
27
- * Default false — modal components keep their own backdrop click handler,
28
- * which is part of their DOM and needs no document listener.
40
+ * Whether a pointerdown outside `getElements()` dismisses this layer (light
41
+ * dismiss: popovers, menus, listboxes). Default false — modal components
42
+ * keep their own backdrop click handler, which is part of their DOM, and
43
+ * gate it on `ownsPress()`.
29
44
  */
30
45
  dismissOnOutsidePress?: boolean;
31
46
  /**
32
47
  * The elements that count as "inside" for outside-press checks — typically
33
- * the panel and its trigger. Only read when `dismissOnOutsidePress` is on.
48
+ * the panel and its trigger. Read when `dismissOnOutsidePress` is on, and
49
+ * also to stop the outside-press walk at a layer that contains the press.
34
50
  */
35
51
  getElements?: () => (HTMLElement | null | undefined)[];
36
52
  };
53
+ export type LayerHandle = {
54
+ /**
55
+ * Whether the current press belongs to this layer: it was the topmost
56
+ * layer when the press began (or, outside a press, is topmost now). Gate a
57
+ * backdrop click on it.
58
+ */
59
+ ownsPress: () => boolean;
60
+ };
37
61
  /**
38
62
  * Register an overlay on the dismissal stack while `open` is true. Options
39
63
  * are read at event time, so a `dismissOnEscape` toggle takes effect without
40
64
  * re-registering (which would wrongly move the layer to the top).
41
65
  */
42
- export declare function useLayer(options: LayerOptions): void;
66
+ export declare function useLayer(options: LayerOptions): LayerHandle;
43
67
  export {};
@@ -1,39 +1,43 @@
1
1
  "use client";
2
- import { useRef, useEffect } from "react";
2
+ import { useRef, useEffect, useCallback } from "react";
3
3
  const layers = [];
4
4
  let listenersInstalled = false;
5
+ let pressOwner = null;
6
+ const contains = (layer, target) => (layer.optionsRef.current.getElements?.() ?? []).some((el) => el?.contains(target));
5
7
  const handleKeyDown = (event) => {
6
- if (event.key !== "Escape") return;
8
+ if (event.key !== "Escape" || event.defaultPrevented) return;
7
9
  const top = layers[layers.length - 1];
8
10
  if (!top) return;
9
11
  const options = top.optionsRef.current;
10
- if (options.dismissOnEscape === false) return;
11
12
  event.preventDefault();
13
+ if (options.dismissOnEscape === false) return;
12
14
  options.onDismiss?.();
13
15
  };
14
16
  const handlePointerDown = (event) => {
15
- const top = layers[layers.length - 1];
16
- if (!top) return;
17
- const options = top.optionsRef.current;
18
- if (!options.dismissOnOutsidePress) return;
17
+ pressOwner = layers[layers.length - 1] ?? null;
19
18
  const target = event.target instanceof Node ? event.target : null;
20
19
  if (!target) return;
21
- const inside = (options.getElements?.() ?? []).some((el) => el?.contains(target));
22
- if (!inside) options.onDismiss?.();
20
+ for (const layer of [...layers].reverse()) {
21
+ const options = layer.optionsRef.current;
22
+ if (!options.dismissOnOutsidePress || contains(layer, target)) break;
23
+ options.onDismiss?.();
24
+ }
23
25
  };
24
26
  const syncListeners = () => {
25
27
  if (layers.length > 0 && !listenersInstalled) {
26
28
  document.addEventListener("keydown", handleKeyDown);
27
- document.addEventListener("pointerdown", handlePointerDown);
29
+ document.addEventListener("pointerdown", handlePointerDown, true);
28
30
  listenersInstalled = true;
29
31
  } else if (layers.length === 0 && listenersInstalled) {
30
32
  document.removeEventListener("keydown", handleKeyDown);
31
- document.removeEventListener("pointerdown", handlePointerDown);
33
+ document.removeEventListener("pointerdown", handlePointerDown, true);
32
34
  listenersInstalled = false;
35
+ pressOwner = null;
33
36
  }
34
37
  };
35
38
  function useLayer(options) {
36
39
  const optionsRef = useRef(options);
40
+ const layerRef = useRef(null);
37
41
  useEffect(() => {
38
42
  optionsRef.current = options;
39
43
  });
@@ -41,14 +45,22 @@ function useLayer(options) {
41
45
  useEffect(() => {
42
46
  if (!open) return;
43
47
  const layer = { optionsRef };
48
+ layerRef.current = layer;
44
49
  layers.push(layer);
45
50
  syncListeners();
46
51
  return () => {
47
52
  const index = layers.indexOf(layer);
48
53
  if (index !== -1) layers.splice(index, 1);
54
+ layerRef.current = null;
49
55
  syncListeners();
50
56
  };
51
57
  }, [open]);
58
+ const ownsPress = useCallback(() => {
59
+ const layer = layerRef.current;
60
+ if (!layer) return false;
61
+ return pressOwner ? pressOwner === layer : layers[layers.length - 1] === layer;
62
+ }, []);
63
+ return { ownsPress };
52
64
  }
53
65
  export {
54
66
  useLayer
@@ -23,6 +23,9 @@ const handler = createChatHandler({
23
23
  models: CHAT_MODELS,
24
24
  defaultModel: DEFAULT_CHAT_MODEL,
25
25
  // tools: [], // Deterministic lookups the model may call; a tool can answer with a card.
26
+ // A reply can end in a question with answers to pick, drawn as a card the
27
+ // visitor taps. Asking ends the exchange; the answer arrives as the next message.
28
+ askUser: true,
26
29
  guardrails,
27
30
  });
28
31
 
@@ -1,5 +1,22 @@
1
+ import { CodeBlockProps } from '../components/CodeBlock/CodeBlock';
2
+ import { PromptSuggestionsProps } from '../components/PromptSuggestions/PromptSuggestions';
3
+ import { QuestionCardLabels } from '../components/QuestionCard/QuestionCard';
1
4
  import { ChatTurn, LiveResponse } from './types';
2
- export declare function AssistantTurn({ turn, live }: {
5
+ /** The words an assistant turn's parts write, set from ChatWidget's label props. Every key left out keeps the part's English. */
6
+ export interface AssistantTurnLabels {
7
+ /** The fenced-code CodeBlocks in a reply; `codeLabel` is given the fence's language. */
8
+ codeBlock?: Pick<CodeBlockProps, 'copyLabel' | 'copyText' | 'copiedLabel'> & {
9
+ codeLabel?: (language: string | undefined) => string;
10
+ };
11
+ /** The reasoning disclosure's summary once thinking is over, given the seconds it took when known. */
12
+ reasoning?: (durationSeconds: number | undefined) => string;
13
+ /** The question card a reply ends in. */
14
+ questionCard?: Partial<QuestionCardLabels>;
15
+ /** The follow-up row's hidden "(chosen)" text. */
16
+ promptSuggestions?: Pick<PromptSuggestionsProps, 'chosenLabel'>;
17
+ }
18
+ export declare function AssistantTurn({ turn, live, labels, }: {
3
19
  turn?: ChatTurn;
4
20
  live?: LiveResponse;
21
+ labels?: AssistantTurnLabels;
5
22
  }): import("react").JSX.Element;
@@ -1,5 +1,6 @@
1
1
  "use client";
2
2
  import { jsx, jsxs, Fragment } from "react/jsx-runtime";
3
+ import { createContext, useContext } from "react";
3
4
  import ReactMarkdown from "react-markdown";
4
5
  import remarkGfm from "remark-gfm";
5
6
  import { AgentStatus } from "../components/AgentStatus/AgentStatus.js";
@@ -12,6 +13,8 @@ import { DOCK_QUERY } from "./queries.js";
12
13
  import { FollowupSuggestions } from "./FollowupSuggestions.js";
13
14
  import { ResponseActions } from "./ResponseActions.js";
14
15
  import { TurnCard } from "./TurnContent.js";
16
+ import { TurnQuestion } from "./TurnQuestion.js";
17
+ const CodeBlockLabelsContext = createContext(void 0);
15
18
  function MarkdownLink({ href, children }) {
16
19
  const { view, setOpen, renderLink, isInternalHref } = useChatWidget();
17
20
  if (!href || !isInternalHref(href)) return /* @__PURE__ */ jsx(Fragment, { children });
@@ -25,26 +28,39 @@ function MarkdownLink({ href, children }) {
25
28
  }
26
29
  const hastText = (node) => node.type === "text" ? node.value ?? "" : (node.children ?? []).map(hastText).join("");
27
30
  function MarkdownPre({ node, children, ...props }) {
31
+ const { codeLabel, ...labels } = useContext(CodeBlockLabelsContext) ?? {};
28
32
  const code = node?.children?.find(
29
33
  (child) => child.type === "element" && child.tagName === "code"
30
34
  );
31
35
  if (!code) return /* @__PURE__ */ jsx("pre", { ...props, children });
32
36
  const classes = code.properties?.className;
33
37
  const language = (Array.isArray(classes) ? classes : []).map(String).find((name) => name.startsWith("language-"))?.slice("language-".length);
34
- return /* @__PURE__ */ jsx(CodeBlock, { code: hastText(code).replace(/\n$/, ""), language });
38
+ return /* @__PURE__ */ jsx(
39
+ CodeBlock,
40
+ {
41
+ ...labels,
42
+ codeLabel: codeLabel?.(language),
43
+ code: hastText(code).replace(/\n$/, ""),
44
+ language
45
+ }
46
+ );
35
47
  }
36
48
  const markdownComponents = {
37
49
  a: MarkdownLink,
38
50
  pre: MarkdownPre,
39
51
  table: ({ children, ...props }) => /* @__PURE__ */ jsx("table", { tabIndex: 0, ...props, children })
40
52
  };
41
- function AssistantTurn({ turn, live }) {
53
+ function AssistantTurn({
54
+ turn,
55
+ live,
56
+ labels
57
+ }) {
42
58
  const thinking = live?.phase === "thinking";
43
59
  const tracePoints = live ? live.tracePoints : turn?.tracePoints ?? [];
44
60
  const durationSeconds = live ? live.durationSeconds : turn?.durationSeconds;
45
61
  const text = live ? live.text : turn?.text ?? "";
46
62
  const { turns, live: liveTurn, freshFollowupsId } = useChatWidget();
47
- const followupsPending = !!turn && turn.text !== "" && !!turn.exchangeId && !turn.followups && !liveTurn && turns[turns.length - 1]?.id === turn.id;
63
+ const followupsPending = !!turn && turn.text !== "" && !!turn.exchangeId && !turn.followups && !turn.question && !liveTurn && turns[turns.length - 1]?.id === turn.id;
48
64
  return /* @__PURE__ */ jsx(
49
65
  ChatMessage,
50
66
  {
@@ -56,7 +72,9 @@ function AssistantTurn({ turn, live }) {
56
72
  {
57
73
  turnId: turn.id,
58
74
  suggestions: turn.followups,
59
- entrance: turn.id === freshFollowupsId
75
+ chosen: turn.followupChosen,
76
+ entrance: turn.id === freshFollowupsId,
77
+ chosenLabel: labels?.promptSuggestions?.chosenLabel
60
78
  }
61
79
  ) : followupsPending && turn ? /* @__PURE__ */ jsx(FollowupSuggestions, { turnId: turn.id, suggestions: [], pending: true }) : void 0,
62
80
  children: /* @__PURE__ */ jsxs("div", { className: "ds-chat-widget__response", children: [
@@ -66,13 +84,15 @@ function AssistantTurn({ turn, live }) {
66
84
  streaming: thinking,
67
85
  summaryOnly: tracePoints.length === 0,
68
86
  duration: durationSeconds,
87
+ label: labels?.reasoning && !thinking ? labels.reasoning(durationSeconds) : void 0,
69
88
  summary: thinking && live ? /* @__PURE__ */ jsx(AgentStatus, { state: "working", label: live.statusLabel }) : void 0,
70
89
  children: tracePoints.length > 0 && /* @__PURE__ */ jsx("ul", { children: tracePoints.map((point, index) => /* @__PURE__ */ jsx("li", { children: point }, `${index}-${point.slice(0, 24)}`)) })
71
90
  }
72
91
  ),
73
92
  turn?.content,
74
93
  turn?.card && /* @__PURE__ */ jsx(TurnCard, { card: turn.card }),
75
- text !== "" && /* @__PURE__ */ jsx(Prose, { children: /* @__PURE__ */ jsx(ReactMarkdown, { remarkPlugins: [remarkGfm], components: markdownComponents, children: text }) })
94
+ text !== "" && /* @__PURE__ */ jsx(CodeBlockLabelsContext.Provider, { value: labels?.codeBlock, children: /* @__PURE__ */ jsx(Prose, { children: /* @__PURE__ */ jsx(ReactMarkdown, { remarkPlugins: [remarkGfm], components: markdownComponents, children: text }) }) }),
95
+ turn?.question && /* @__PURE__ */ jsx(TurnQuestion, { turn, labels: labels?.questionCard })
76
96
  ] })
77
97
  }
78
98
  );
@@ -1,17 +1,35 @@
1
- import { AgentRailProfile, AgentRailTab } from '../components/AgentRail/AgentRail';
1
+ import { AgentRailProfile, AgentRailProps, AgentRailTab } from '../components/AgentRail/AgentRail';
2
2
  export interface ChatAgentPaneProps {
3
3
  /** The agent this pane belongs to: the portrait block at the top. */
4
4
  profile: AgentRailProfile;
5
5
  /** The panes, in display order: activity, approvals, automations, personalisation, or whatever the agent has. */
6
6
  tabs: AgentRailTab[];
7
- /** The tab on stage, when the host owns the state; otherwise the pane keeps its own. */
8
- activeTab?: string;
7
+ /** The tab on stage, when the host owns the state; otherwise the pane keeps its own, seeded from `defaultValue`. */
8
+ value?: string;
9
+ /** The tab on stage first when the pane keeps its own state. Defaults to the first tab. */
10
+ defaultValue?: string;
9
11
  /** Fires with the chosen tab's id. */
12
+ onValueChange?: (id: string) => void;
13
+ /**
14
+ * Legacy name for `value`.
15
+ *
16
+ * @deprecated Use `value` instead.
17
+ */
18
+ activeTab?: string;
19
+ /**
20
+ * Legacy change callback; fires alongside `onValueChange`.
21
+ *
22
+ * @deprecated Use `onValueChange` instead.
23
+ */
10
24
  onTabChange?: (id: string) => void;
11
25
  /** The widget seated the pane as a bottom sheet, where it fills the width instead of holding its own column. */
12
26
  overlay: boolean;
13
27
  /** Fires from the pane's own close button, a cross in its top trailing corner. Omit for a pane with no close of its own. */
14
28
  onClose?: () => void;
29
+ /** Accessible name of the pane's own close button. Defaults to "Close the agent panel". */
30
+ closeLabel?: string;
31
+ /** The words the AgentRail writes, merged over its English defaults: the tab strip's name ("Agent views"). */
32
+ agentRailLabels?: Pick<AgentRailProps, 'tabsLabel'>;
15
33
  }
16
34
  /**
17
35
  * The built-in agent pane: an AgentRail the widget seats on the
@@ -21,4 +39,4 @@ export interface ChatAgentPaneProps {
21
39
  * pane carries a close of its own in its top corner, where a panel's way
22
40
  * out is looked for.
23
41
  */
24
- export declare function ChatAgentPane({ profile, tabs, activeTab, onTabChange, overlay, onClose }: ChatAgentPaneProps): import("react").JSX.Element;
42
+ export declare function ChatAgentPane({ profile, tabs, value, defaultValue, onValueChange, activeTab, onTabChange, overlay, onClose, closeLabel, agentRailLabels, }: ChatAgentPaneProps): import("react").JSX.Element;
@@ -3,21 +3,35 @@ import { jsx } from "react/jsx-runtime";
3
3
  import { useState } from "react";
4
4
  import { AgentRail } from "../components/AgentRail/AgentRail.js";
5
5
  import "./ChatAgentPane.css";
6
- function ChatAgentPane({ profile, tabs, activeTab, onTabChange, overlay, onClose }) {
7
- const [ownTab, setOwnTab] = useState(tabs[0]?.id ?? "");
8
- const current = activeTab ?? ownTab;
6
+ function ChatAgentPane({
7
+ profile,
8
+ tabs,
9
+ value,
10
+ defaultValue,
11
+ onValueChange,
12
+ activeTab,
13
+ onTabChange,
14
+ overlay,
15
+ onClose,
16
+ closeLabel = "Close the agent panel",
17
+ agentRailLabels
18
+ }) {
19
+ const [ownTab, setOwnTab] = useState(defaultValue ?? tabs[0]?.id ?? "");
20
+ const current = value ?? activeTab ?? ownTab;
9
21
  return /* @__PURE__ */ jsx(
10
22
  AgentRail,
11
23
  {
24
+ ...agentRailLabels,
12
25
  className: overlay ? "ds-chat-agent-pane--sheet" : void 0,
13
26
  profile,
14
27
  tabs,
15
- activeTab: current,
28
+ value: current,
16
29
  onCollapse: onClose,
17
30
  collapseVariant: "close",
18
- collapseLabel: "Close the agent panel",
19
- onTabChange: (id) => {
31
+ collapseLabel: closeLabel,
32
+ onValueChange: (id) => {
20
33
  setOwnTab(id);
34
+ onValueChange?.(id);
21
35
  onTabChange?.(id);
22
36
  }
23
37
  }
@@ -1,3 +1,4 @@
1
+ import { ArtifactPanelProps } from '../components/ArtifactPanel/ArtifactPanel';
1
2
  import { ChatArtifact } from './types';
2
3
  export interface ChatArtifactPaneProps {
3
4
  /** The artifact on stage, or null for the empty state: the panel opened before the conversation has made anything. */
@@ -8,6 +9,20 @@ export interface ChatArtifactPaneProps {
8
9
  onExpandedChange?: (expanded: boolean) => void;
9
10
  /** Fires from the pane's close button; omit where another control closes the seat. */
10
11
  onClose?: () => void;
12
+ /** The panel's title while nothing is on stage. Defaults to "Artifacts". */
13
+ emptyPanelTitle?: string;
14
+ /** The empty state's heading. Defaults to "Nothing here yet". */
15
+ emptyTitle?: string;
16
+ /** The empty state's description. Defaults to "What the chat makes for you, like a dashboard or a page, opens in this panel." */
17
+ emptyDescription?: string;
18
+ /**
19
+ * The words the ArtifactPanel writes, merged over its English defaults:
20
+ * the view switch's segments and name ("Preview", "Code", "Artifact
21
+ * view"), the expand toggle and close button's names ("Expand the
22
+ * artifact", "Collapse the artifact", "Close the artifact"), and the code
23
+ * view's copy button and region (`codeBlockLabels`).
24
+ */
25
+ artifactPanelLabels?: Pick<ArtifactPanelProps, 'previewLabel' | 'codeLabel' | 'viewLabel' | 'expandLabel' | 'collapseLabel' | 'closeLabel' | 'codeBlockLabels'>;
11
26
  }
12
27
  /**
13
28
  * The built-in artifact pane: an ArtifactPanel drawn from a `ChatArtifact`.
@@ -15,4 +30,4 @@ export interface ChatArtifactPaneProps {
15
30
  * otherwise the artifact's document, URL or source decides the preview. The
16
31
  * widget owns the seat (beside the conversation, or a sheet over it).
17
32
  */
18
- export declare function ChatArtifactPane({ artifact, expanded, onExpandedChange, onClose }: ChatArtifactPaneProps): import("react").JSX.Element;
33
+ export declare function ChatArtifactPane({ artifact, expanded, onExpandedChange, onClose, emptyPanelTitle, emptyTitle, emptyDescription, artifactPanelLabels, }: ChatArtifactPaneProps): import("react").JSX.Element;
@@ -4,18 +4,19 @@ import { ArtifactPanel } from "../components/ArtifactPanel/ArtifactPanel.js";
4
4
  import { EmptyState } from "../components/EmptyState/EmptyState.js";
5
5
  import { useChatWidget } from "./context.js";
6
6
  const FRAMEABLE_URL = /^(?:https?:\/\/|\/(?!\/))/i;
7
- function ChatArtifactPane({ artifact, expanded, onExpandedChange, onClose }) {
7
+ function ChatArtifactPane({
8
+ artifact,
9
+ expanded,
10
+ onExpandedChange,
11
+ onClose,
12
+ emptyPanelTitle = "Artifacts",
13
+ emptyTitle = "Nothing here yet",
14
+ emptyDescription = "What the chat makes for you, like a dashboard or a page, opens in this panel.",
15
+ artifactPanelLabels
16
+ }) {
8
17
  const { artifactRenderers } = useChatWidget();
9
18
  if (!artifact) {
10
- return /* @__PURE__ */ jsx(ArtifactPanel, { title: "Artifacts", icon: "space_dashboard", onClose, children: /* @__PURE__ */ jsx("div", { className: "ds-chat-widget__artifact-empty", children: /* @__PURE__ */ jsx(
11
- EmptyState,
12
- {
13
- size: "compact",
14
- icon: "draft",
15
- title: "Nothing here yet",
16
- description: "What the chat makes for you, like a dashboard or a page, opens in this panel."
17
- }
18
- ) }) });
19
+ return /* @__PURE__ */ jsx(ArtifactPanel, { ...artifactPanelLabels, title: emptyPanelTitle, icon: "space_dashboard", onClose, children: /* @__PURE__ */ jsx("div", { className: "ds-chat-widget__artifact-empty", children: /* @__PURE__ */ jsx(EmptyState, { size: "compact", icon: "draft", title: emptyTitle, description: emptyDescription }) }) });
19
20
  }
20
21
  const custom = Object.hasOwn(artifactRenderers, artifact.kind);
21
22
  const render = artifactRenderers[artifact.kind];
@@ -23,6 +24,7 @@ function ChatArtifactPane({ artifact, expanded, onExpandedChange, onClose }) {
23
24
  return /* @__PURE__ */ jsx(
24
25
  ArtifactPanel,
25
26
  {
27
+ ...artifactPanelLabels,
26
28
  title: artifact.title,
27
29
  meta: artifact.meta,
28
30
  icon: artifact.icon,
@@ -1,5 +1,5 @@
1
1
  import { ReactNode } from 'react';
2
- import { AiButtonSummary } from '../components/AiButton/AiButton';
2
+ import { AiButtonProps, AiButtonSummary } from '../components/AiButton/AiButton';
3
3
  import { ChatWidgetProps } from './ChatWidget';
4
4
  /** The id the panel carries, for a host control's `aria-controls`. */
5
5
  export declare const CHAT_PANEL_ID = "ds-chat-panel";
@@ -11,8 +11,10 @@ export interface ChatLauncherProps {
11
11
  /**
12
12
  * A TLDR panel the button summons on hover: a pre-written summary and
13
13
  * prompt chips. A tapped chip opens the chat and sends the chip's
14
- * `prompt`. Hover-capable devices only: the launcher never renders it on
15
- * touch, and never in server HTML.
14
+ * `prompt`. The launcher hands it to the closed button's AiButton, which
15
+ * opens the panel on pointer hover; it does no device or hydration gating
16
+ * of its own, so a host that wants the panel on hover-capable devices only,
17
+ * or kept out of server HTML, passes `summary` only there.
16
18
  */
17
19
  summary?: AiButtonSummary & {
18
20
  chips?: {
@@ -21,7 +23,10 @@ export interface ChatLauncherProps {
21
23
  prompt: string;
22
24
  }[];
23
25
  };
24
- /** Render nothing at all: for routes that carry no chrome. */
26
+ /**
27
+ * Render nothing at all: for routes that carry no chrome.
28
+ * Note: not the native `hidden` attribute, which keeps an element mounted and only hides it; the launcher unmounts its button and panel, and spreads no native attributes.
29
+ */
25
30
  hidden?: boolean;
26
31
  /** The panel's DOM id, for a host control's `aria-controls`. */
27
32
  panelId?: string;
@@ -33,6 +38,8 @@ export interface ChatLauncherProps {
33
38
  hostAttribute?: string | false;
34
39
  /** Accessible name for the panel. */
35
40
  panelLabel?: string;
41
+ /** The words of the floating button's summary panel, over AiButton's English defaults: the panel's name, given the summary's title ("Summary: <title>"), its dismiss button ("Dismiss summary") and its chips' group ("Suggested prompts"). */
42
+ aiButtonLabels?: Pick<AiButtonProps, 'summaryRegionLabel' | 'dismissLabel' | 'suggestionsLabel'>;
36
43
  /** Everything the widget takes. The launcher sets the responsive ones itself. */
37
44
  widget?: Omit<ChatWidgetProps, 'fullscreenEnabled' | 'placementEnabled' | 'compact' | 'phone'>;
38
45
  /** Rendered inside the panel after the widget: for a host's extra chrome. */
@@ -61,4 +68,4 @@ export interface ChatLauncherProps {
61
68
  * touch the host's body). The panel's geometry reads `--ds-chat-width`,
62
69
  * `--ds-chat-inset` and `--ds-chat-float-height`, defaulted on `:root`.
63
70
  */
64
- export declare function ChatLauncher({ label, icon, summary, hidden, panelId, hostAttribute, panelLabel, widget, children, }: ChatLauncherProps): import("react").JSX.Element | null;
71
+ export declare function ChatLauncher({ label, icon, summary, hidden, panelId, hostAttribute, panelLabel, aiButtonLabels, widget, children, }: ChatLauncherProps): import("react").JSX.Element | null;
@@ -42,6 +42,7 @@ function ChatLauncher({
42
42
  panelId = CHAT_PANEL_ID,
43
43
  hostAttribute = "data-chat",
44
44
  panelLabel = "Chat",
45
+ aiButtonLabels,
45
46
  widget,
46
47
  children
47
48
  }) {
@@ -223,6 +224,7 @@ function ChatLauncher({
223
224
  return /* @__PURE__ */ jsx("div", { className: "ds-chat-launcher__fab", children: /* @__PURE__ */ jsx(
224
225
  AiButton,
225
226
  {
227
+ ...aiButtonLabels,
226
228
  label,
227
229
  icon,
228
230
  "aria-expanded": false,
@@ -244,7 +246,7 @@ function ChatLauncher({
244
246
  }
245
247
  const handleKeyDown = (event) => {
246
248
  if (event.key === "Escape") {
247
- setOpen(false);
249
+ if (!event.defaultPrevented) setOpen(false);
248
250
  return;
249
251
  }
250
252
  if (modal && event.key === "Tab" && panelRef.current) {
@@ -18,11 +18,12 @@ export interface ChatProviderProps {
18
18
  defaultPlacement?: ChatPlacement;
19
19
  /**
20
20
  * Where follow-up questions come from after an answer commits: a source
21
- * function, an endpoint for the built-in fetcher, or `false` for none.
22
- * Defaults to the fetcher against `/api/chat/followups`.
21
+ * function, an endpoint for the built-in fetcher, or `false` for none:
22
+ * with `false` no chips show under an answer at all, not even the written
23
+ * `fallbackFollowups`. Defaults to the fetcher against `/api/chat/followups`.
23
24
  */
24
25
  followups?: FollowupsSource | string | false;
25
- /** The written questions offered when the source returns none. */
26
+ /** The written questions offered when the source returns none or fails. Unused when `followups` is `false`. */
26
27
  fallbackFollowups?: readonly string[];
27
28
  /**
28
29
  * Where a thumbs verdict goes: a sink function, an endpoint for the
@@ -41,7 +42,7 @@ export interface ChatProviderProps {
41
42
  isInternalHref?: (href: string) => boolean;
42
43
  /** Seeds the thread lifecycle behind the `threads` and `tabs` slots. */
43
44
  threads?: ThreadsOptions;
44
- /** Replacement copy for the hook's placeholder replies. */
45
+ /** Replacement copy for the words the hook writes itself, merged over the English defaults: the status line of a reply that has not started ("Thinking") and the placeholder replies for an empty, stopped or failed turn. */
45
46
  placeholders?: Partial<ChatPlaceholderCopy>;
46
47
  children: ReactNode;
47
48
  }