@adres/mgda-ui 0.0.0-stage → 0.0.2

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 (325) hide show
  1. package/brand-knowledge.json +451 -0
  2. package/knowledge/accordion.md +135 -0
  3. package/knowledge/activity-rings.md +123 -0
  4. package/knowledge/alert.md +184 -0
  5. package/knowledge/answer-actions.md +217 -0
  6. package/knowledge/aspect-ratio.md +82 -0
  7. package/knowledge/avatar.md +158 -0
  8. package/knowledge/badge.md +172 -0
  9. package/knowledge/bar-graph.md +167 -0
  10. package/knowledge/bento-grid.md +115 -0
  11. package/knowledge/blockquote.md +153 -0
  12. package/knowledge/box-list.md +177 -0
  13. package/knowledge/bullet-list.md +128 -0
  14. package/knowledge/button-group.md +179 -0
  15. package/knowledge/button.md +231 -0
  16. package/knowledge/calendar.md +168 -0
  17. package/knowledge/card.md +321 -0
  18. package/knowledge/cards-nav.md +170 -0
  19. package/knowledge/chain-of-thought.md +164 -0
  20. package/knowledge/chat-container.md +135 -0
  21. package/knowledge/chat-message.md +224 -0
  22. package/knowledge/checkbox-card.md +172 -0
  23. package/knowledge/checkbox.md +111 -0
  24. package/knowledge/citations.md +241 -0
  25. package/knowledge/combobox.md +265 -0
  26. package/knowledge/countdown-pill.md +153 -0
  27. package/knowledge/cta.md +118 -0
  28. package/knowledge/data-list.md +173 -0
  29. package/knowledge/data-table.md +220 -0
  30. package/knowledge/dialog.md +249 -0
  31. package/knowledge/drawer.md +236 -0
  32. package/knowledge/dropdown-menu.md +238 -0
  33. package/knowledge/dropzone.md +153 -0
  34. package/knowledge/email-chips-input.md +161 -0
  35. package/knowledge/empty-state.md +106 -0
  36. package/knowledge/entity-header.md +166 -0
  37. package/knowledge/feature-grid.md +120 -0
  38. package/knowledge/feedback-bar.md +127 -0
  39. package/knowledge/footer.md +116 -0
  40. package/knowledge/heading.md +189 -0
  41. package/knowledge/hero.md +361 -0
  42. package/knowledge/input-button.md +187 -0
  43. package/knowledge/input-group.md +185 -0
  44. package/knowledge/input.md +256 -0
  45. package/knowledge/inset.md +177 -0
  46. package/knowledge/kpi-card.md +206 -0
  47. package/knowledge/list-nav.md +181 -0
  48. package/knowledge/logo-cloud.md +102 -0
  49. package/knowledge/media-gallery.md +158 -0
  50. package/knowledge/message-actions.md +175 -0
  51. package/knowledge/nav-sidebar.md +225 -0
  52. package/knowledge/number-stepper.md +159 -0
  53. package/knowledge/page-header.md +109 -0
  54. package/knowledge/pagination.md +225 -0
  55. package/knowledge/popover.md +159 -0
  56. package/knowledge/pricing.md +132 -0
  57. package/knowledge/progress.md +156 -0
  58. package/knowledge/prompt-input.md +337 -0
  59. package/knowledge/prompt-suggestions.md +168 -0
  60. package/knowledge/quota-bar.md +160 -0
  61. package/knowledge/quote.md +116 -0
  62. package/knowledge/radio-card.md +172 -0
  63. package/knowledge/radio-group.md +135 -0
  64. package/knowledge/reasoning.md +142 -0
  65. package/knowledge/search.md +131 -0
  66. package/knowledge/section-nav.md +162 -0
  67. package/knowledge/segmented-control.md +181 -0
  68. package/knowledge/select-button.md +205 -0
  69. package/knowledge/select.md +210 -0
  70. package/knowledge/separator.md +75 -0
  71. package/knowledge/shimmer-text.md +140 -0
  72. package/knowledge/sidebar.md +227 -0
  73. package/knowledge/skeleton.md +142 -0
  74. package/knowledge/slider.md +133 -0
  75. package/knowledge/slideshow.md +159 -0
  76. package/knowledge/source.md +156 -0
  77. package/knowledge/spinner.md +120 -0
  78. package/knowledge/stat-strip.md +128 -0
  79. package/knowledge/stats.md +117 -0
  80. package/knowledge/step-indicator.md +157 -0
  81. package/knowledge/switch.md +88 -0
  82. package/knowledge/table.md +190 -0
  83. package/knowledge/tabs.md +169 -0
  84. package/knowledge/testimonials.md +115 -0
  85. package/knowledge/text-link.md +192 -0
  86. package/knowledge/text.md +194 -0
  87. package/knowledge/thinking-bar.md +115 -0
  88. package/knowledge/thinking-steps.md +140 -0
  89. package/knowledge/toaster.md +127 -0
  90. package/knowledge/toggle.md +113 -0
  91. package/knowledge/tool-call-card.md +241 -0
  92. package/knowledge/tooltip.md +120 -0
  93. package/knowledge/top-nav.md +138 -0
  94. package/knowledge.json +19854 -0
  95. package/package.json +94 -4
  96. package/src/components/accordion.stories.tsx +46 -0
  97. package/src/components/accordion.tsx +74 -0
  98. package/src/components/activity-rings.stories.tsx +73 -0
  99. package/src/components/activity-rings.tsx +121 -0
  100. package/src/components/alert.stories.tsx +43 -0
  101. package/src/components/alert.tsx +132 -0
  102. package/src/components/answer-actions.stories.tsx +54 -0
  103. package/src/components/answer-actions.test.tsx +37 -0
  104. package/src/components/answer-actions.tsx +313 -0
  105. package/src/components/aspect-ratio.stories.tsx +32 -0
  106. package/src/components/aspect-ratio.tsx +5 -0
  107. package/src/components/avatar.stories.tsx +40 -0
  108. package/src/components/avatar.tsx +154 -0
  109. package/src/components/badge.stories.tsx +27 -0
  110. package/src/components/badge.tsx +63 -0
  111. package/src/components/bar-graph.stories.tsx +28 -0
  112. package/src/components/bar-graph.tsx +204 -0
  113. package/src/components/bento-grid.stories.tsx +23 -0
  114. package/src/components/bento-grid.tsx +67 -0
  115. package/src/components/blockquote.stories.tsx +28 -0
  116. package/src/components/blockquote.tsx +88 -0
  117. package/src/components/box-list.stories.tsx +25 -0
  118. package/src/components/box-list.tsx +108 -0
  119. package/src/components/bullet-list.stories.tsx +22 -0
  120. package/src/components/bullet-list.tsx +101 -0
  121. package/src/components/button-group.stories.tsx +31 -0
  122. package/src/components/button-group.tsx +156 -0
  123. package/src/components/button.stories.tsx +66 -0
  124. package/src/components/button.test.ts +17 -0
  125. package/src/components/button.tsx +139 -0
  126. package/src/components/calendar.stories.tsx +25 -0
  127. package/src/components/calendar.tsx +367 -0
  128. package/src/components/card.stories.tsx +44 -0
  129. package/src/components/card.tsx +392 -0
  130. package/src/components/cards-nav.stories.tsx +35 -0
  131. package/src/components/cards-nav.tsx +115 -0
  132. package/src/components/chain-of-thought.stories.tsx +67 -0
  133. package/src/components/chain-of-thought.test.tsx +50 -0
  134. package/src/components/chain-of-thought.tsx +170 -0
  135. package/src/components/chat-container.stories.tsx +47 -0
  136. package/src/components/chat-container.test.tsx +49 -0
  137. package/src/components/chat-container.tsx +222 -0
  138. package/src/components/chat-message.stories.tsx +52 -0
  139. package/src/components/chat-message.test.tsx +36 -0
  140. package/src/components/chat-message.tsx +163 -0
  141. package/src/components/checkbox-card.stories.tsx +27 -0
  142. package/src/components/checkbox-card.tsx +200 -0
  143. package/src/components/checkbox.stories.tsx +26 -0
  144. package/src/components/checkbox.tsx +61 -0
  145. package/src/components/citations.stories.tsx +64 -0
  146. package/src/components/citations.test.tsx +61 -0
  147. package/src/components/citations.tsx +220 -0
  148. package/src/components/combobox.stories.tsx +184 -0
  149. package/src/components/combobox.test.tsx +82 -0
  150. package/src/components/combobox.tsx +407 -0
  151. package/src/components/countdown-pill.stories.tsx +24 -0
  152. package/src/components/countdown-pill.tsx +129 -0
  153. package/src/components/cta.stories.tsx +29 -0
  154. package/src/components/cta.tsx +52 -0
  155. package/src/components/data-list.stories.tsx +50 -0
  156. package/src/components/data-list.test.tsx +35 -0
  157. package/src/components/data-list.tsx +181 -0
  158. package/src/components/data-table.stories.tsx +29 -0
  159. package/src/components/data-table.tsx +200 -0
  160. package/src/components/dialog.stories.tsx +42 -0
  161. package/src/components/dialog.tsx +200 -0
  162. package/src/components/drawer.stories.tsx +48 -0
  163. package/src/components/drawer.tsx +385 -0
  164. package/src/components/dropdown-menu.stories.tsx +41 -0
  165. package/src/components/dropdown-menu.tsx +252 -0
  166. package/src/components/dropzone.stories.tsx +19 -0
  167. package/src/components/dropzone.tsx +250 -0
  168. package/src/components/email-chips-input.stories.tsx +135 -0
  169. package/src/components/email-chips-input.tsx +210 -0
  170. package/src/components/empty-state.stories.tsx +22 -0
  171. package/src/components/empty-state.tsx +35 -0
  172. package/src/components/entity-header.stories.tsx +43 -0
  173. package/src/components/entity-header.test.tsx +35 -0
  174. package/src/components/entity-header.tsx +92 -0
  175. package/src/components/feature-grid.stories.tsx +25 -0
  176. package/src/components/feature-grid.tsx +87 -0
  177. package/src/components/feedback-bar.stories.tsx +25 -0
  178. package/src/components/feedback-bar.test.tsx +24 -0
  179. package/src/components/feedback-bar.tsx +62 -0
  180. package/src/components/footer.stories.tsx +23 -0
  181. package/src/components/footer.tsx +78 -0
  182. package/src/components/heading.stories.tsx +45 -0
  183. package/src/components/heading.test.tsx +22 -0
  184. package/src/components/heading.tsx +77 -0
  185. package/src/components/hero.stories.tsx +38 -0
  186. package/src/components/hero.tsx +498 -0
  187. package/src/components/input-button.stories.tsx +19 -0
  188. package/src/components/input-button.tsx +112 -0
  189. package/src/components/input-group.stories.tsx +38 -0
  190. package/src/components/input-group.tsx +157 -0
  191. package/src/components/input.stories.tsx +31 -0
  192. package/src/components/input.tsx +284 -0
  193. package/src/components/inset.stories.tsx +29 -0
  194. package/src/components/inset.tsx +70 -0
  195. package/src/components/kpi-card.stories.tsx +29 -0
  196. package/src/components/kpi-card.tsx +284 -0
  197. package/src/components/list-nav.stories.tsx +22 -0
  198. package/src/components/list-nav.tsx +145 -0
  199. package/src/components/logo-cloud.stories.tsx +23 -0
  200. package/src/components/logo-cloud.tsx +42 -0
  201. package/src/components/media-gallery.stories.tsx +25 -0
  202. package/src/components/media-gallery.tsx +347 -0
  203. package/src/components/message-actions.stories.tsx +45 -0
  204. package/src/components/message-actions.test.tsx +32 -0
  205. package/src/components/message-actions.tsx +119 -0
  206. package/src/components/nav-sidebar.stories.tsx +58 -0
  207. package/src/components/nav-sidebar.test.tsx +54 -0
  208. package/src/components/nav-sidebar.tsx +462 -0
  209. package/src/components/number-stepper.stories.tsx +19 -0
  210. package/src/components/number-stepper.tsx +158 -0
  211. package/src/components/page-header.stories.tsx +25 -0
  212. package/src/components/page-header.tsx +64 -0
  213. package/src/components/pagination.stories.tsx +110 -0
  214. package/src/components/pagination.test.tsx +46 -0
  215. package/src/components/pagination.tsx +144 -0
  216. package/src/components/popover.stories.tsx +26 -0
  217. package/src/components/popover.tsx +62 -0
  218. package/src/components/pricing.stories.tsx +42 -0
  219. package/src/components/pricing.tsx +130 -0
  220. package/src/components/progress.stories.tsx +22 -0
  221. package/src/components/progress.tsx +189 -0
  222. package/src/components/prompt-input.stories.tsx +62 -0
  223. package/src/components/prompt-input.test.tsx +106 -0
  224. package/src/components/prompt-input.tsx +343 -0
  225. package/src/components/prompt-suggestions.stories.tsx +53 -0
  226. package/src/components/prompt-suggestions.test.tsx +37 -0
  227. package/src/components/prompt-suggestions.tsx +122 -0
  228. package/src/components/quota-bar.stories.tsx +19 -0
  229. package/src/components/quota-bar.tsx +191 -0
  230. package/src/components/quote.stories.tsx +18 -0
  231. package/src/components/quote.tsx +43 -0
  232. package/src/components/radio-card.stories.tsx +27 -0
  233. package/src/components/radio-card.tsx +225 -0
  234. package/src/components/radio-group.stories.tsx +32 -0
  235. package/src/components/radio-group.tsx +68 -0
  236. package/src/components/reasoning.stories.tsx +50 -0
  237. package/src/components/reasoning.test.tsx +48 -0
  238. package/src/components/reasoning.tsx +143 -0
  239. package/src/components/search.stories.tsx +18 -0
  240. package/src/components/search.tsx +133 -0
  241. package/src/components/section-nav.stories.tsx +59 -0
  242. package/src/components/section-nav.test.tsx +36 -0
  243. package/src/components/section-nav.tsx +146 -0
  244. package/src/components/segmented-control.stories.tsx +22 -0
  245. package/src/components/segmented-control.tsx +301 -0
  246. package/src/components/select-button.stories.tsx +27 -0
  247. package/src/components/select-button.tsx +174 -0
  248. package/src/components/select.stories.tsx +27 -0
  249. package/src/components/select.tsx +198 -0
  250. package/src/components/separator.stories.tsx +22 -0
  251. package/src/components/separator.tsx +23 -0
  252. package/src/components/shimmer-text.stories.tsx +23 -0
  253. package/src/components/shimmer-text.test.tsx +35 -0
  254. package/src/components/shimmer-text.tsx +43 -0
  255. package/src/components/sidebar.stories.tsx +25 -0
  256. package/src/components/sidebar.tsx +234 -0
  257. package/src/components/skeleton.stories.tsx +22 -0
  258. package/src/components/skeleton.tsx +96 -0
  259. package/src/components/slider.stories.tsx +20 -0
  260. package/src/components/slider.tsx +176 -0
  261. package/src/components/slideshow.stories.tsx +30 -0
  262. package/src/components/slideshow.tsx +291 -0
  263. package/src/components/source.stories.tsx +32 -0
  264. package/src/components/source.test.tsx +40 -0
  265. package/src/components/source.tsx +161 -0
  266. package/src/components/spinner.stories.tsx +19 -0
  267. package/src/components/spinner.tsx +76 -0
  268. package/src/components/stat-strip.stories.tsx +36 -0
  269. package/src/components/stat-strip.test.tsx +25 -0
  270. package/src/components/stat-strip.tsx +85 -0
  271. package/src/components/stats.stories.tsx +24 -0
  272. package/src/components/stats.tsx +83 -0
  273. package/src/components/step-indicator.stories.tsx +18 -0
  274. package/src/components/step-indicator.test.tsx +18 -0
  275. package/src/components/step-indicator.tsx +286 -0
  276. package/src/components/switch.stories.tsx +26 -0
  277. package/src/components/switch.tsx +32 -0
  278. package/src/components/table.stories.tsx +38 -0
  279. package/src/components/table.tsx +220 -0
  280. package/src/components/tabs.stories.tsx +25 -0
  281. package/src/components/tabs.tsx +276 -0
  282. package/src/components/testimonials.stories.tsx +22 -0
  283. package/src/components/testimonials.tsx +109 -0
  284. package/src/components/text-link.stories.tsx +47 -0
  285. package/src/components/text-link.test.tsx +18 -0
  286. package/src/components/text-link.tsx +88 -0
  287. package/src/components/text.stories.tsx +49 -0
  288. package/src/components/text.tsx +105 -0
  289. package/src/components/thinking-bar.stories.tsx +19 -0
  290. package/src/components/thinking-bar.test.tsx +27 -0
  291. package/src/components/thinking-bar.tsx +64 -0
  292. package/src/components/thinking-steps.stories.tsx +44 -0
  293. package/src/components/thinking-steps.test.tsx +42 -0
  294. package/src/components/thinking-steps.tsx +92 -0
  295. package/src/components/toaster.stories.tsx +80 -0
  296. package/src/components/toaster.tsx +36 -0
  297. package/src/components/toggle.stories.tsx +21 -0
  298. package/src/components/toggle.tsx +103 -0
  299. package/src/components/tool-call-card.stories.tsx +97 -0
  300. package/src/components/tool-call-card.test.tsx +88 -0
  301. package/src/components/tool-call-card.tsx +231 -0
  302. package/src/components/tooltip.stories.tsx +25 -0
  303. package/src/components/tooltip.tsx +43 -0
  304. package/src/components/top-nav.stories.tsx +20 -0
  305. package/src/components/top-nav.tsx +76 -0
  306. package/src/docs/Colors.stories.tsx +192 -0
  307. package/src/docs/GettingStarted.mdx +72 -0
  308. package/src/docs/Mcp.mdx +52 -0
  309. package/src/docs/Typography.stories.tsx +114 -0
  310. package/src/hooks/use-in-view.ts +32 -0
  311. package/src/hooks/use-reduced-motion.ts +26 -0
  312. package/src/index.ts +343 -0
  313. package/src/lib/cn.test.ts +67 -0
  314. package/src/lib/cn.ts +81 -0
  315. package/src/lib/motion.ts +109 -0
  316. package/src/lib/prefix-utilities.test.ts +56 -0
  317. package/src/lib/prefix-utilities.ts +50 -0
  318. package/src/styles/base.css +489 -0
  319. package/src/styles/motion.css +69 -0
  320. package/src/styles/overrides.css +44 -0
  321. package/src/styles/typography.css +173 -0
  322. package/src/theme/theme.css +391 -0
  323. package/src/theme/tokens.ts +29 -0
  324. package/src/theme/types.ts +26 -0
  325. package/README.md +0 -3
@@ -0,0 +1,158 @@
1
+ ---
2
+ # >>> DERIVED - regenerated by `npm run knowledge:sync`. Do not edit. <<<
3
+ derived:
4
+ schemaVersion: 1
5
+ id: media-gallery
6
+ sourceFile: packages/design-system/src/components/media-gallery.tsx
7
+ client: true
8
+ category: web-app-media
9
+ categoryFromBarrel: web-app-media
10
+ barrelExported: true
11
+ importPath: "@adres/mgda-ui"
12
+ exports:
13
+ - name: Lightbox
14
+ kind: component
15
+ typeText: "({ media, index, onIndexChange, onClose, title }: LightboxProps) => Element"
16
+ - name: LightboxProps
17
+ kind: type
18
+ - name: MediaGallery
19
+ kind: component
20
+ typeText: "({ media, title, thumbnailCount, className }: MediaGalleryProps) => Element"
21
+ - name: MediaGalleryProps
22
+ kind: type
23
+ - name: MediaItem
24
+ kind: type
25
+ - name: MediaKind
26
+ kind: type
27
+ primaryExport: MediaGallery
28
+ subcomponents:
29
+ - Lightbox
30
+ props:
31
+ Lightbox:
32
+ - name: index
33
+ type: number
34
+ required: true
35
+ declaredIn: self
36
+ - name: media
37
+ type: "MediaItem[]"
38
+ required: true
39
+ declaredIn: self
40
+ - name: onClose
41
+ type: "() => void"
42
+ required: true
43
+ declaredIn: self
44
+ - name: onIndexChange
45
+ type: "(index: number) => void"
46
+ required: true
47
+ declaredIn: self
48
+ - name: title
49
+ type: string
50
+ required: false
51
+ declaredIn: self
52
+ MediaGallery:
53
+ - name: className
54
+ type: string
55
+ required: false
56
+ declaredIn: self
57
+ - name: media
58
+ type: "MediaItem[]"
59
+ required: true
60
+ declaredIn: self
61
+ doc: "Ordered media. The first item is the hero; the rest fill the thumbnails."
62
+ - name: thumbnailCount
63
+ type: number
64
+ required: false
65
+ declaredIn: self
66
+ doc: "Thumbnails shown beside the hero (defaults to 4)."
67
+ - name: title
68
+ type: string
69
+ required: false
70
+ declaredIn: self
71
+ doc: "Used for alt text and the lightbox's accessible title."
72
+ extendsProps: []
73
+ variants: {}
74
+ variantSource: none
75
+ compoundVariants: []
76
+ sizeMaps: []
77
+ dataSlots: []
78
+ dependsOn:
79
+ internal:
80
+ - button
81
+ lib:
82
+ - cn
83
+ hooks: []
84
+ external:
85
+ - "@radix-ui/react-dialog"
86
+ - lucide-react
87
+ - react
88
+ contexts: []
89
+ stories:
90
+ - exportName: Default
91
+ id: components-mediagallery--default
92
+ storybookTitle: Components/MediaGallery
93
+ docsId: components-mediagallery--documentation
94
+ argTypeOptions: {}
95
+ resolvedCleanly: true
96
+ contractHash: "8f72385ce536"
97
+ factsHash: "9e472898d4c7"
98
+ # >>> AUTHORED - humans own everything below this line. <<<
99
+ status: stable
100
+ summary: "A hero + thumbnail image/video grid that opens a fullscreen, keyboard-navigable lightbox with zoom/pan and inline video playback."
101
+ useWhen:
102
+ - "showing a browsable set of photos, and optionally video or walkthrough clips, for a single listing or item - a property, product, or unit"
103
+ - "the user should be able to open any thumbnail into a fullscreen, zoomable, swipeable viewer"
104
+ useInstead:
105
+ - id: slideshow
106
+ when: "the images should present one at a time in a single frame - a hero carousel, testimonial rotator - not a browsable grid with a separate fullscreen viewer"
107
+ related:
108
+ - slideshow
109
+ a11y:
110
+ notes:
111
+ - "Lightbox is built on Radix Dialog, so it inherits focus trapping, scroll lock, and Escape-to-close automatically, even though its dark immersive surface looks nothing like a typical dialog."
112
+ - "title is used for both the hero/thumbnail alt text and the lightbox's visually-hidden accessible title - pass a real, descriptive title (e.g. the property name), not a generic placeholder, since it is the only accessible name a screen reader gets for the whole gallery."
113
+ keyboard:
114
+ - "ArrowLeft/ArrowRight navigate between items while the lightbox is open; Escape closes it, inherited from Radix Dialog."
115
+ radixHandles: true
116
+ pitfalls:
117
+ - "media[0] is always the hero tile - reordering the array changes which image is large and which are thumbnails; there is no separate hero flag on a MediaItem."
118
+ - "Only one walkthrough item is surfaced specially: MediaGallery finds the first item with type=\"walkthrough\" and adds a dedicated Walkthrough button over the hero - a second walkthrough item still appears as a normal thumbnail, it does not get its own button."
119
+ - "thumbnailCount only controls how many thumbnails render beside the hero (default 4); it does not limit how many items are browsable in the lightbox - all of media is always reachable there via the thumbnail strip and arrow keys."
120
+ - "Lightbox is exported and can be used standalone, but MediaGallery already renders it internally when a thumbnail is clicked - rendering both in the same tree only makes sense when building a custom trigger for the lightbox that bypasses the grid entirely."
121
+ canonicalSnippet: |
122
+ import { MediaGallery } from "@adres/mgda-ui"
123
+
124
+ <MediaGallery
125
+ title="Unit 2304"
126
+ media={[
127
+ { type: "image", src: "/photos/exterior.jpg" },
128
+ { type: "image", src: "/photos/living-room.jpg" },
129
+ { type: "walkthrough", src: "/videos/tour.mp4", poster: "/photos/tour-poster.jpg", label: "Walkthrough" },
130
+ ]}
131
+ />
132
+ reviewedAt: 2026-09-01
133
+ reviewedAgainstContractHash: "8f72385ce536"
134
+ ---
135
+
136
+ ## Usage
137
+
138
+ `MediaGallery` is for a browsable set of photos, and optionally video or
139
+ walkthrough clips, belonging to a single listing or item - a property unit, a
140
+ product, a place. Reach for `Slideshow` instead when the images should
141
+ present one at a time in a single frame, like a hero carousel or testimonial
142
+ rotator, rather than a grid the user browses into a fullscreen viewer.
143
+
144
+ `media[0]` is always the large hero tile; the rest fill the thumbnail grid up
145
+ to `thumbnailCount` (default 4), with a "+N Photos" overlay on the last
146
+ visible thumbnail when more remain. Every item in `media` stays reachable in
147
+ the fullscreen `Lightbox` regardless of `thumbnailCount`, via its thumbnail
148
+ strip and arrow-key navigation.
149
+
150
+ Give at most one item `type="walkthrough"` to get the dedicated "Walkthrough"
151
+ button over the hero - `MediaGallery` only looks for the first one.
152
+
153
+ ## Anatomy
154
+
155
+ | Part | Role |
156
+ | --- | --- |
157
+ | `MediaGallery` | The hero + thumbnail grid. Opens `Lightbox` internally when a tile is clicked. |
158
+ | `Lightbox` | The fullscreen viewer. Built on Radix Dialog; handles zoom and pan for images, inline playback for video, and keyboard navigation. Exported separately for standalone use, though `MediaGallery` already renders it for you. |
@@ -0,0 +1,175 @@
1
+ ---
2
+ # >>> DERIVED - regenerated by `npm run knowledge:sync`. Do not edit. <<<
3
+ derived:
4
+ schemaVersion: 1
5
+ id: message-actions
6
+ sourceFile: packages/design-system/src/components/message-actions.tsx
7
+ client: true
8
+ category: web-app-ai
9
+ categoryFromBarrel: web-app-ai
10
+ barrelExported: true
11
+ importPath: "@adres/mgda-ui"
12
+ exports:
13
+ - name: MessageAction
14
+ kind: component
15
+ typeText: "ForwardRefExoticComponent<MessageActionProps & RefAttributes<HTMLButtonElement>>"
16
+ - name: MessageActionProps
17
+ kind: type
18
+ - name: MessageActions
19
+ kind: component
20
+ typeText: "ForwardRefExoticComponent<MessageActionsProps & RefAttributes<HTMLDivElement>>"
21
+ - name: MessageActionsProps
22
+ kind: type
23
+ - name: MessageRating
24
+ kind: type
25
+ primaryExport: MessageActions
26
+ subcomponents:
27
+ - MessageAction
28
+ props:
29
+ MessageAction:
30
+ - name: aurora
31
+ type: boolean
32
+ required: false
33
+ declaredIn: button
34
+ doc: "Decorative \"aurora\" - two soft, blurred orbs (primary + accent) drifting behind the label for a modern, glowing look. Designed for the `primary` variant. Ignored with `asChild` (it needs to inject its own children)."
35
+ - name: label
36
+ type: string
37
+ required: true
38
+ declaredIn: self
39
+ doc: "Accessible name and tooltip text."
40
+ - name: pressed
41
+ type: boolean
42
+ required: false
43
+ declaredIn: self
44
+ doc: "Renders as a toggle: sets `aria-pressed` and tints the icon."
45
+ MessageActions:
46
+ - name: copyText
47
+ type: string
48
+ required: false
49
+ declaredIn: self
50
+ doc: "Text the Copy action writes to the clipboard. Omit to hide Copy."
51
+ - name: onCopy
52
+ type: "(() => void)"
53
+ required: false
54
+ declaredIn: self
55
+ - name: onRate
56
+ type: "((rating: MessageRating) => void)"
57
+ required: false
58
+ declaredIn: self
59
+ doc: "Called with the clicked rating; the caller decides whether a second click clears it. Omit to hide rating."
60
+ - name: onRegenerate
61
+ type: "(() => void)"
62
+ required: false
63
+ declaredIn: self
64
+ doc: "Omit to hide Regenerate."
65
+ - name: rating
66
+ type: MessageRating
67
+ required: false
68
+ declaredIn: self
69
+ - name: regenerateDisabled
70
+ type: boolean
71
+ required: false
72
+ declaredIn: self
73
+ - name: regenerating
74
+ type: boolean
75
+ required: false
76
+ declaredIn: self
77
+ doc: "Spins the Regenerate icon and disables it."
78
+ - name: revealOnHover
79
+ type: boolean
80
+ required: false
81
+ declaredIn: self
82
+ doc: "Hides the row until the message is hovered or the row holds focus. Needs a `group/message` ancestor (ChatMessage sets one); touch screens always show it."
83
+ extendsProps:
84
+ - "React.HTMLAttributes<HTMLDivElement>"
85
+ variants:
86
+ rating:
87
+ kind: enum
88
+ options:
89
+ - up
90
+ - down
91
+ default: null
92
+ on: MessageActions
93
+ variantSource: prop-union
94
+ compoundVariants: []
95
+ sizeMaps: []
96
+ dataSlots:
97
+ - message-actions
98
+ dependsOn:
99
+ internal:
100
+ - button
101
+ - tooltip
102
+ lib:
103
+ - cn
104
+ hooks: []
105
+ external:
106
+ - lucide-react
107
+ - react
108
+ contexts: []
109
+ stories:
110
+ - exportName: Default
111
+ id: components-messageactions--default
112
+ - exportName: CopyOnly
113
+ id: components-messageactions--copy-only
114
+ - exportName: Regenerating
115
+ id: components-messageactions--regenerating
116
+ - exportName: WithExtraAction
117
+ id: components-messageactions--with-extra-action
118
+ storybookTitle: Components/MessageActions
119
+ docsId: components-messageactions--documentation
120
+ argTypeOptions: {}
121
+ resolvedCleanly: true
122
+ contractHash: "904203824709"
123
+ factsHash: "43769f63eb08"
124
+ # >>> AUTHORED - humans own everything below this line. <<<
125
+ status: beta
126
+ summary: "The row of icon actions under an assistant message: copy, rate up or down, and regenerate, with room for extra actions."
127
+ useWhen:
128
+ - "an assistant answer needs copy, thumbs up or down, or regenerate"
129
+ - "a chat or AI surface needs a consistent icon action with a tooltip under a message"
130
+ useInstead:
131
+ - id: button-group
132
+ when: "the actions are labelled buttons, not icon-only message actions"
133
+ related:
134
+ - tooltip
135
+ - button
136
+ a11y:
137
+ notes:
138
+ - "Every action is an icon-only button named by its label, which is also the tooltip text."
139
+ - "Ratings are toggles with aria-pressed; pass rating so the pressed state is announced."
140
+ - "Pass role=\"toolbar\" and an aria-label when the row is the main action bar of an answer."
141
+ - "With revealOnHover the row still takes keyboard focus and shows while focused; touch screens always show it."
142
+ radixHandles: true
143
+ pitfalls:
144
+ - "Tooltips need a TooltipProvider above the row; apps usually mount one in the root layout."
145
+ - "onRate gets the clicked value, not the next state. Clear the rating yourself when the same value is clicked twice."
146
+ - "revealOnHover needs a group/message ancestor; ChatMessage provides one. Leave it off on the latest answer so its actions stay visible."
147
+ canonicalSnippet: |
148
+ import { MessageActions } from "@adres/mgda-ui"
149
+
150
+ <MessageActions
151
+ copyText={answer}
152
+ rating={rating}
153
+ onRate={(next) => setRating(rating === next ? null : next)}
154
+ onRegenerate={regenerate}
155
+ />
156
+ reviewedAt: 2026-10-06
157
+ reviewedAgainstContractHash: "904203824709"
158
+ ---
159
+
160
+ ## Usage
161
+
162
+ `MessageActions` sits under an assistant message. Each built-in action shows
163
+ only when its prop is set: `copyText` adds Copy (with a short "Copied"
164
+ confirmation), `onRate` adds thumbs up and down, `onRegenerate` adds
165
+ Regenerate. Rating is controlled: keep it in state and decide what a second
166
+ click on the same thumb does. Extra actions such as a version pager or a More
167
+ menu go in `children` after the built-in ones. Buttons are round ghost icons.
168
+ Set `revealOnHover` to hide the row until the message is hovered or the row
169
+ is focused, as on older turns in a long thread.
170
+
171
+ ## Anatomy
172
+
173
+ - `MessageActions` - the row; renders the built-in actions, then `children`.
174
+ - `MessageAction` - one icon-only ghost button with a tooltip. Set `pressed`
175
+ to make it a toggle. Use it for extra actions so they match the row.
@@ -0,0 +1,225 @@
1
+ ---
2
+ # >>> DERIVED - regenerated by `npm run knowledge:sync`. Do not edit. <<<
3
+ derived:
4
+ schemaVersion: 1
5
+ id: nav-sidebar
6
+ sourceFile: packages/design-system/src/components/nav-sidebar.tsx
7
+ client: true
8
+ category: web-app-layout-navigation
9
+ categoryFromBarrel: web-app-layout-navigation
10
+ barrelExported: true
11
+ importPath: "@adres/mgda-ui"
12
+ exports:
13
+ - name: NavItem
14
+ kind: type
15
+ - name: NavSection
16
+ kind: type
17
+ - name: NavSidebar
18
+ kind: component
19
+ typeText: "({ sections, currentPath, brand, footer, collapsed: collapsedProp, defaultCollapsed, onCollapsedChange, hideCollapseToggle, expandedItems: expandedProp, defaultExpandedItems, onExpandedItemsChange, LinkComponent, expandS...[truncated]"
20
+ - name: NavSidebarProps
21
+ kind: type
22
+ - name: NavSubItem
23
+ kind: type
24
+ primaryExport: NavSidebar
25
+ subcomponents: []
26
+ props:
27
+ NavSidebar:
28
+ - name: brand
29
+ type: ReactNode
30
+ required: false
31
+ declaredIn: self
32
+ doc: "Optional brand slot rendered in the sidebar header. Typically a logo with an optional sub-label. Hidden in collapsed mode (the collapse toggle takes the slot instead) - the consumer is responsible for rendering a compact mark separately if needed."
33
+ - name: collapsed
34
+ type: boolean
35
+ required: false
36
+ declaredIn: self
37
+ - name: collapseItemLabel
38
+ type: "((label: string) => string)"
39
+ required: false
40
+ declaredIn: self
41
+ - name: collapseSidebarLabel
42
+ type: string
43
+ required: false
44
+ declaredIn: self
45
+ - name: currentPath
46
+ type: string
47
+ required: true
48
+ declaredIn: self
49
+ doc: "The application's current pathname - used to compute active rows and to auto-open the active branch on first render. Pass `usePathname()` from your router."
50
+ - name: defaultCollapsed
51
+ type: boolean
52
+ required: false
53
+ declaredIn: self
54
+ - name: defaultExpandedItems
55
+ type: "Record<string, boolean>"
56
+ required: false
57
+ declaredIn: self
58
+ - name: expandedItems
59
+ type: "Record<string, boolean>"
60
+ required: false
61
+ declaredIn: self
62
+ doc: "Map of item href → explicit open state. Items not present in the map fall back to auto-open-when-active."
63
+ - name: expandItemLabel
64
+ type: "((label: string) => string)"
65
+ required: false
66
+ declaredIn: self
67
+ doc: "Called with `(label)` to format aria-labels for chevron toggle buttons. Defaults to `\"Expand {label}\"` / `\"Collapse {label}\"`."
68
+ - name: expandSidebarLabel
69
+ type: string
70
+ required: false
71
+ declaredIn: self
72
+ - name: footer
73
+ type: ReactNode
74
+ required: false
75
+ declaredIn: self
76
+ doc: "Optional footer slot, typically a `SidebarUserCard`."
77
+ - name: hideCollapseToggle
78
+ type: boolean
79
+ required: false
80
+ declaredIn: self
81
+ doc: "Hide the built-in collapse toggle. Useful when the consumer controls collapse from elsewhere (e.g. a media-query hook on mobile)."
82
+ - name: LinkComponent
83
+ type: "ElementType<any, keyof IntrinsicElements>"
84
+ required: false
85
+ declaredIn: self
86
+ doc: "Component used to render navigable rows. Defaults to a plain anchor; pass your router's link component (e.g. Next.js `<Link>`) to get client-side navigation. Receives standard anchor props."
87
+ - name: onCollapsedChange
88
+ type: "((collapsed: boolean) => void)"
89
+ required: false
90
+ declaredIn: self
91
+ - name: onExpandedItemsChange
92
+ type: "((next: Record<string, boolean>) => void)"
93
+ required: false
94
+ declaredIn: self
95
+ - name: sections
96
+ type: "NavSection[]"
97
+ required: true
98
+ declaredIn: self
99
+ extendsProps: []
100
+ variants: {}
101
+ variantSource: none
102
+ compoundVariants: []
103
+ sizeMaps: []
104
+ dataSlots: []
105
+ dependsOn:
106
+ internal:
107
+ - sidebar
108
+ - tooltip
109
+ lib:
110
+ - cn
111
+ hooks: []
112
+ external:
113
+ - lucide-react
114
+ - react
115
+ contexts: []
116
+ stories:
117
+ - exportName: Default
118
+ id: components-navsidebar--default
119
+ - exportName: WithCounts
120
+ id: components-navsidebar--with-counts
121
+ storybookTitle: Components/NavSidebar
122
+ docsId: components-navsidebar--documentation
123
+ argTypeOptions: {}
124
+ resolvedCleanly: true
125
+ contractHash: "5c27ead74713"
126
+ factsHash: "7380688639b1"
127
+ # >>> AUTHORED - humans own everything below this line. <<<
128
+ status: stable
129
+ summary: "Config-driven app sidebar navigation: active-state routing, nested items, and a collapse toggle, built on Sidebar."
130
+ useWhen:
131
+ - "the app's primary nav is a persistent left column driven by a route/pathname"
132
+ - "sections have nested sub-items that should expand under a parent"
133
+ - "you want a built-in collapse-to-icon-rail toggle instead of building one"
134
+ useInstead:
135
+ - id: sidebar
136
+ when: "the built-in routing/active-state/collapse behavior doesn't fit and you need to compose the raw structural pieces yourself"
137
+ - id: top-nav
138
+ when: "the app's primary navigation is horizontal, not a side column"
139
+ related:
140
+ - sidebar
141
+ - button
142
+ - tooltip
143
+ composesWith:
144
+ - sidebar
145
+ - button
146
+ tokens:
147
+ - "--card"
148
+ - "--border"
149
+ - "--foreground"
150
+ - "--primary-foreground"
151
+ - "--muted-foreground"
152
+ - "--accent"
153
+ - "--ring"
154
+ a11y:
155
+ notes:
156
+ - "Renders a Sidebar underneath, so it inherits the aria-label=\"Primary\" landmark - don't nest a second NavSidebar/Sidebar on the same page."
157
+ - "Each nav row sets aria-current=\"page\" when active, computed from currentPath, not from the browser's own navigation state."
158
+ - "The chevron toggle for items with children is a sibling <button>, not part of the link, so it has its own focus stop, aria-expanded, and an aria-label from expandItemLabel/collapseItemLabel."
159
+ - "In collapsed mode a row shows its label in a Tooltip and names the link with aria-label (label plus count, e.g. \"Drafts, 4 items\"), since the visible text is gone - keep item.label short."
160
+ requiredProps:
161
+ - "sections and currentPath are required; currentPath must come from the consumer's router (e.g. usePathname())"
162
+ keyboard:
163
+ - "Rows are rendered through LinkComponent (a plain <a> by default), so they take part in tab order and activate with Enter."
164
+ - "The children-toggle chevron is a real <button>, reachable and activatable with Enter/Space independently of the row's own link."
165
+ radixHandles: false
166
+ pitfalls:
167
+ - "currentPath must be supplied by the consumer (e.g. usePathname()) - NavSidebar does not read the URL itself, so a stale or hardcoded value freezes active-state and auto-open detection."
168
+ - "exact on a NavItem changes active-match from prefix (pathname.startsWith(href + \"/\")) to exact equality - a parent item covering /courses/* needs exact left unset, not exact: true."
169
+ - "expandedItems/onExpandedItemsChange only overrides items present in the map; items absent from it still fall back to auto-open-when-active, so partially controlling open state is intentional, not a bug."
170
+ - "dot on an item with children is silently not rendered - the chevron owns that trailing space, so a badge count belongs on the item's own row only when it has no children."
171
+ - "count follows the same rule: it renders on items without children, is hidden at 0, and moves into the tooltip (\"Drafts · 4\") when the sidebar is collapsed."
172
+ subcomponentNotes:
173
+ NavItem: "One top-level entry: href, label, icon, optional exact, dot, count, and children (NavSubItem[]) for a nested submenu."
174
+ NavSection: "A group of NavItems with an optional label, rendered as a small caption above the group while expanded and hidden when collapsed. Every section after the first also gets a divider."
175
+ NavSubItem: "A nested row under an item with children: href, label, and an optional trailing count."
176
+ rtl: "Inherits Sidebar's logical properties; the chevron's rotation includes an explicit rtl: variant (-rotate-90 rtl:rotate-90) so it points the correct direction when the layout mirrors."
177
+ canonicalSnippet: |
178
+ import { NavSidebar } from "@adres/mgda-ui"
179
+ import Link from "next/link"
180
+ import { usePathname } from "next/navigation"
181
+ import { Home, Book } from "lucide-react"
182
+
183
+ <NavSidebar
184
+ LinkComponent={Link}
185
+ currentPath={usePathname()}
186
+ brand={<img src="/logo.svg" alt="Acme" className="ax:h-6" />}
187
+ sections={[
188
+ {
189
+ items: [
190
+ { href: "/dashboard", label: "Dashboard", icon: <Home /> },
191
+ {
192
+ href: "/courses",
193
+ label: "Courses",
194
+ icon: <Book />,
195
+ children: [
196
+ { href: "/courses", label: "All courses" },
197
+ { href: "/courses/categories", label: "Categories" },
198
+ ],
199
+ },
200
+ ],
201
+ },
202
+ ]}
203
+ />
204
+ reviewedAt: 2026-10-06
205
+ reviewedAgainstContractHash: "5c27ead74713"
206
+ ---
207
+
208
+ ## Usage
209
+
210
+ NavSidebar is the opinionated, route-aware layer on top of `Sidebar`: it takes
211
+ a declarative `sections`/`items` config plus the current pathname, and
212
+ computes active state, auto-opens the branch containing the active route, and
213
+ renders a chevron toggle for items with nested children. It also owns the
214
+ collapse-to-icon-rail toggle button that `Sidebar` itself leaves to the
215
+ consumer.
216
+
217
+ Collapse state and per-item open overrides can be either controlled (pass
218
+ `collapsed`/`expandedItems` plus their `onChange` callbacks) or left
219
+ uncontrolled (the component manages its own state, seeded from
220
+ `defaultCollapsed`/`defaultExpandedItems`). Reach for the controlled form only
221
+ when something outside the component needs to react to or drive that state -
222
+ for example, collapsing on a media query.
223
+
224
+ Pass a router's link component via `LinkComponent` (defaults to a plain `<a>`)
225
+ to get client-side navigation instead of full page loads.