@open-mercato/ui 0.6.4-develop.4178.1.aad9ddaa95 → 0.6.4-develop.4210.1.d412061cfe

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 (92) hide show
  1. package/.turbo/turbo-build.log +1 -1
  2. package/AGENTS.md +14 -0
  3. package/dist/backend/DataTable.js +28 -62
  4. package/dist/backend/DataTable.js.map +2 -2
  5. package/dist/backend/detail/AttachmentMetadataDialog.js +1 -1
  6. package/dist/backend/detail/AttachmentMetadataDialog.js.map +2 -2
  7. package/dist/primitives/activity-feed.js +196 -0
  8. package/dist/primitives/activity-feed.js.map +7 -0
  9. package/dist/primitives/avatar.js +140 -14
  10. package/dist/primitives/avatar.js.map +3 -3
  11. package/dist/primitives/badge.js +94 -5
  12. package/dist/primitives/badge.js.map +2 -2
  13. package/dist/primitives/button-group.js +52 -0
  14. package/dist/primitives/button-group.js.map +7 -0
  15. package/dist/primitives/color-picker.js +520 -0
  16. package/dist/primitives/color-picker.js.map +7 -0
  17. package/dist/primitives/command-menu.js +355 -0
  18. package/dist/primitives/command-menu.js.map +7 -0
  19. package/dist/primitives/dialog.js +210 -35
  20. package/dist/primitives/dialog.js.map +2 -2
  21. package/dist/primitives/drawer.js +219 -0
  22. package/dist/primitives/drawer.js.map +7 -0
  23. package/dist/primitives/notification-feed.js +213 -0
  24. package/dist/primitives/notification-feed.js.map +7 -0
  25. package/dist/primitives/notification.js +23 -2
  26. package/dist/primitives/notification.js.map +2 -2
  27. package/dist/primitives/pagination.js +245 -0
  28. package/dist/primitives/pagination.js.map +7 -0
  29. package/dist/primitives/progress.js +178 -5
  30. package/dist/primitives/progress.js.map +2 -2
  31. package/dist/primitives/rating.js +174 -0
  32. package/dist/primitives/rating.js.map +7 -0
  33. package/dist/primitives/scroll-area.js +82 -0
  34. package/dist/primitives/scroll-area.js.map +7 -0
  35. package/dist/primitives/segmented-control.js +101 -0
  36. package/dist/primitives/segmented-control.js.map +7 -0
  37. package/dist/primitives/separator.js +103 -4
  38. package/dist/primitives/separator.js.map +2 -2
  39. package/dist/primitives/slider.js +115 -0
  40. package/dist/primitives/slider.js.map +7 -0
  41. package/dist/primitives/step-indicator.js +187 -0
  42. package/dist/primitives/step-indicator.js.map +7 -0
  43. package/dist/primitives/table.js +102 -10
  44. package/dist/primitives/table.js.map +2 -2
  45. package/dist/primitives/tabs.js +122 -14
  46. package/dist/primitives/tabs.js.map +2 -2
  47. package/dist/primitives/time-picker.js +9 -11
  48. package/dist/primitives/time-picker.js.map +2 -2
  49. package/package.json +8 -4
  50. package/src/backend/DataTable.tsx +43 -60
  51. package/src/backend/detail/AttachmentMetadataDialog.tsx +1 -1
  52. package/src/primitives/__tests__/activity-feed.test.tsx +216 -0
  53. package/src/primitives/__tests__/avatar.test.tsx +131 -0
  54. package/src/primitives/__tests__/badge.test.tsx +189 -0
  55. package/src/primitives/__tests__/button-group.test.tsx +117 -0
  56. package/src/primitives/__tests__/color-picker.test.tsx +589 -0
  57. package/src/primitives/__tests__/command-menu.test.tsx +231 -0
  58. package/src/primitives/__tests__/dialog.test.tsx +290 -0
  59. package/src/primitives/__tests__/drawer.test.tsx +264 -0
  60. package/src/primitives/__tests__/notification-feed.test.tsx +303 -0
  61. package/src/primitives/__tests__/notification.test.tsx +102 -2
  62. package/src/primitives/__tests__/pagination.test.tsx +268 -0
  63. package/src/primitives/__tests__/progress.test.tsx +222 -0
  64. package/src/primitives/__tests__/rating.test.tsx +164 -0
  65. package/src/primitives/__tests__/scroll-area.test.tsx +109 -0
  66. package/src/primitives/__tests__/segmented-control.test.tsx +129 -0
  67. package/src/primitives/__tests__/separator.test.tsx +143 -0
  68. package/src/primitives/__tests__/slider.test.tsx +86 -0
  69. package/src/primitives/__tests__/step-indicator.test.tsx +205 -0
  70. package/src/primitives/__tests__/table.test.tsx +199 -0
  71. package/src/primitives/__tests__/tabs.test.tsx +139 -0
  72. package/src/primitives/activity-feed.tsx +326 -0
  73. package/src/primitives/avatar.tsx +225 -22
  74. package/src/primitives/badge.tsx +141 -6
  75. package/src/primitives/button-group.tsx +100 -0
  76. package/src/primitives/color-picker.tsx +693 -0
  77. package/src/primitives/command-menu.tsx +503 -0
  78. package/src/primitives/dialog.tsx +315 -51
  79. package/src/primitives/drawer.tsx +338 -0
  80. package/src/primitives/notification-feed.tsx +358 -0
  81. package/src/primitives/notification.tsx +42 -2
  82. package/src/primitives/pagination.tsx +376 -0
  83. package/src/primitives/progress.tsx +267 -6
  84. package/src/primitives/rating.tsx +245 -0
  85. package/src/primitives/scroll-area.tsx +169 -0
  86. package/src/primitives/segmented-control.tsx +162 -0
  87. package/src/primitives/separator.tsx +163 -3
  88. package/src/primitives/slider.tsx +160 -0
  89. package/src/primitives/step-indicator.tsx +287 -0
  90. package/src/primitives/table.tsx +142 -11
  91. package/src/primitives/tabs.tsx +174 -12
  92. package/src/primitives/time-picker.tsx +9 -11
@@ -3,9 +3,44 @@
3
3
  import * as React from 'react'
4
4
  import * as DialogPrimitive from '@radix-ui/react-dialog'
5
5
  import { X } from 'lucide-react'
6
+ import { cva, type VariantProps } from 'class-variance-authority'
7
+
6
8
  import { cn } from '@open-mercato/shared/lib/utils'
7
9
  import { useT } from '@open-mercato/shared/lib/i18n/context'
8
10
 
11
+ /**
12
+ * Modal dialog primitive. Phase B.7 rewrite per Figma `Modals` page
13
+ * (`466:4630`) — `Modal Header [1.1]` (`466:4778`, title + optional
14
+ * leading icon badge + optional description), `Modal Footer [1.1]`
15
+ * (`472:566`, right-aligned buttons or 50/50 stretched layout),
16
+ * `Status Modals [1.1]` (`480:1372`, status-icon hero variant).
17
+ *
18
+ * Backward compatibility (40 import sites — every dialog in the
19
+ * product). All existing exports (`Dialog`, `DialogTrigger`,
20
+ * `DialogPortal`, `DialogOverlay`, `DialogClose`, `DialogContent`,
21
+ * `DialogHeader`, `DialogFooter`, `DialogTitle`, `DialogDescription`)
22
+ * stay callable verbatim. Default `size="default"` reproduces the
23
+ * original `sm:max-w-lg` width; default header has no leading badge;
24
+ * default footer is right-aligned (current look).
25
+ *
26
+ * New (additive):
27
+ * DialogContent:
28
+ * - `size: 'sm' | 'default' | 'lg' | 'xl'` — max-width breakpoints
29
+ * - `dismissible: boolean` (default `true`) — render the auto X
30
+ * top-right close button
31
+ *
32
+ * DialogHeader:
33
+ * - `leading?: ReactNode` — `size-10 rounded-full border` icon
34
+ * badge to the left of the title block (matches Figma `Modal
35
+ * Header [1.1]` icon-prefixed variants — same chrome as the
36
+ * Drawer header leading slot)
37
+ *
38
+ * DialogFooter:
39
+ * - `layout: 'default' | 'equal'` (default `default`) — `equal`
40
+ * stretches children flex-1 for 50/50 confirmation footers
41
+ * (Figma `Modal Footer [1.1]` variant 1)
42
+ */
43
+
9
44
  const Dialog = DialogPrimitive.Root
10
45
 
11
46
  const DialogTrigger = DialogPrimitive.Trigger
@@ -24,80 +59,307 @@ const DialogOverlay = React.forwardRef<
24
59
  >(({ className, elevated, ...props }, ref) => (
25
60
  <DialogPrimitive.Overlay
26
61
  ref={ref}
62
+ data-slot="dialog-overlay"
27
63
  className={cn(
28
64
  'fixed inset-0 bg-black/50 backdrop-blur-sm transition-opacity data-[state=open]:animate-in data-[state=closed]:animate-out',
29
65
  elevated ? 'z-modal-elevated' : 'z-modal',
30
- className
66
+ className,
31
67
  )}
32
68
  {...props}
33
69
  />
34
70
  ))
35
71
  DialogOverlay.displayName = DialogPrimitive.Overlay.displayName
36
72
 
37
- const DialogContent = React.forwardRef<
38
- React.ElementRef<typeof DialogPrimitive.Content>,
39
- React.ComponentPropsWithoutRef<typeof DialogPrimitive.Content> & {
73
+ const dialogContentVariants = cva(
74
+ 'fixed inset-x-0 bottom-0 flex max-h-[90vh] w-full translate-x-0 translate-y-0 flex-col gap-4 overflow-y-auto rounded-t-xl border-t bg-card p-6 shadow-lg sm:inset-auto sm:left-1/2 sm:top-1/2 sm:min-h-0 sm:h-auto sm:w-full sm:max-h-[90vh] sm:-translate-x-1/2 sm:-translate-y-1/2 sm:rounded-xl sm:border focus-visible:outline-none data-[state=open]:animate-in data-[state=closed]:animate-out',
75
+ {
76
+ variants: {
77
+ size: {
78
+ sm: 'sm:max-w-sm',
79
+ default: 'sm:max-w-lg',
80
+ lg: 'sm:max-w-2xl',
81
+ xl: 'sm:max-w-4xl',
82
+ },
83
+ },
84
+ defaultVariants: {
85
+ size: 'default',
86
+ },
87
+ },
88
+ )
89
+
90
+ export type DialogContentProps = React.ComponentPropsWithoutRef<
91
+ typeof DialogPrimitive.Content
92
+ > &
93
+ VariantProps<typeof dialogContentVariants> & {
40
94
  /** Render above popovers (z-modal-elevated, 55) instead of the default z-modal (40).
41
95
  * Set on dialogs that open from inside another popover (e.g. the SaveFilterDialog
42
96
  * inside the AdvancedFilterPanel popover) so they aren't hidden behind the popover. */
43
97
  elevated?: boolean
98
+ /** Render the auto X top-right close button. @default true */
99
+ dismissible?: boolean
100
+ /** Aria label for the auto X close button. Defaults to the
101
+ * `ui.dialog.close.ariaLabel` translation (`"Close"`). */
102
+ closeAriaLabel?: string
44
103
  }
45
- >(({ className, children, elevated, ...props }, ref) => {
46
- const t = useT()
47
-
48
- React.useEffect(() => {
49
- return () => {
50
- if (typeof window === 'undefined') return
51
- window.setTimeout(() => {
52
- if (document.querySelector('[data-dialog-content][data-state="open"]')) return
53
- document.body.style.removeProperty('overflow')
54
- document.body.style.removeProperty('pointer-events')
55
- }, 0)
56
- }
57
- }, [])
58
104
 
59
- return (
60
- <DialogPortal>
61
- <DialogOverlay elevated={elevated} />
62
- <DialogPrimitive.Content
63
- ref={ref}
64
- data-dialog-content=""
65
- // Sizing: mobile uses a bottom-sheet (`fixed inset-x-0 bottom-0`) that resizes to
66
- // the form's content with a cap at 90% viewport height. The previous version forced
67
- // `min-h-[50vh]`, which made every short dialog (Quick deal, Add stage, Change
68
- // owner, etc.) render as a half-screen panel with an empty block below the form.
69
- // Desktop (`sm:`) already used `h-auto`/`min-h-0`, so it's unchanged here.
105
+ const DialogContent = React.forwardRef<
106
+ React.ElementRef<typeof DialogPrimitive.Content>,
107
+ DialogContentProps
108
+ >(
109
+ (
110
+ {
111
+ className,
112
+ children,
113
+ elevated,
114
+ size,
115
+ dismissible = true,
116
+ closeAriaLabel,
117
+ ...props
118
+ },
119
+ ref,
120
+ ) => {
121
+ const t = useT()
122
+
123
+ React.useEffect(() => {
124
+ return () => {
125
+ if (typeof window === 'undefined') return
126
+ window.setTimeout(() => {
127
+ if (document.querySelector('[data-dialog-content][data-state="open"]')) return
128
+ document.body.style.removeProperty('overflow')
129
+ document.body.style.removeProperty('pointer-events')
130
+ }, 0)
131
+ }
132
+ }, [])
133
+
134
+ return (
135
+ <DialogPortal>
136
+ <DialogOverlay elevated={elevated} />
137
+ <DialogPrimitive.Content
138
+ ref={ref}
139
+ data-dialog-content=""
140
+ data-slot="dialog-content"
141
+ data-size={size ?? 'default'}
142
+ className={cn(
143
+ dialogContentVariants({ size }),
144
+ elevated ? 'z-modal-elevated' : 'z-modal',
145
+ className,
146
+ )}
147
+ {...props}
148
+ >
149
+ {dismissible ? (
150
+ <DialogClose
151
+ data-dialog-close=""
152
+ data-slot="dialog-close-button"
153
+ className="absolute right-4 top-4 rounded-sm opacity-70 transition-opacity hover:opacity-100 focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2"
154
+ aria-label={closeAriaLabel ?? t('ui.dialog.close.ariaLabel', 'Close')}
155
+ >
156
+ <X className="h-4 w-4" />
157
+ </DialogClose>
158
+ ) : null}
159
+ {children}
160
+ </DialogPrimitive.Content>
161
+ </DialogPortal>
162
+ )
163
+ },
164
+ )
165
+ DialogContent.displayName = DialogPrimitive.Content.displayName
166
+
167
+ export type DialogHeaderTone =
168
+ | 'default'
169
+ | 'accent'
170
+ | 'success'
171
+ | 'warning'
172
+ | 'error'
173
+ | 'info'
174
+
175
+ // Soft-tinted status leading badges per canonical Figma `Status
176
+ // Modals [1.1]` (`480:1372`). Each status tone uses the soft tint
177
+ // background paired with a saturated colored icon (red `!` on light
178
+ // pink, amber triangle on light amber, green check on light green,
179
+ // indigo `i` on light indigo). The bordered `default` tone keeps
180
+ // the white-bg + border-input shell for generic settings icons per
181
+ // `Modal Header [1.1]` (`466:4778`).
182
+ const DIALOG_HEADER_TONE_CLASS: Record<DialogHeaderTone, string> = {
183
+ default: 'border border-input bg-background text-muted-foreground',
184
+ accent: 'bg-accent-indigo/10 text-accent-indigo',
185
+ success: 'bg-status-success-bg text-status-success-icon',
186
+ warning: 'bg-status-warning-bg text-status-warning-icon',
187
+ error: 'bg-status-error-bg text-status-error-icon',
188
+ info: 'bg-status-info-bg text-status-info-icon',
189
+ }
190
+
191
+ export type DialogHeaderProps = React.HTMLAttributes<HTMLDivElement> & {
192
+ /** Optional leading icon — rendered inside a size-10 rounded-full
193
+ * badge to the left of the title block. Matches Figma `Modal
194
+ * Header [1.1]` icon-prefixed variants and `Status Modals [1.1]`
195
+ * status-tinted badges. */
196
+ leading?: React.ReactNode
197
+ /** Visual tone for the leading badge. `default` keeps the
198
+ * bordered white badge (generic settings icons); status tones
199
+ * (`success`/`warning`/`error`/`info`) use the matching
200
+ * `bg-status-*-bg text-status-*-icon` tint per Figma `Status
201
+ * Modals [1.1]`. Use `error` / `warning` to signal destructive
202
+ * flows via the badge instead of a red CTA button.
203
+ * @default 'default' */
204
+ leadingTone?: DialogHeaderTone
205
+ }
206
+
207
+ const DialogHeader = ({
208
+ className,
209
+ leading,
210
+ leadingTone = 'default',
211
+ children,
212
+ ...props
213
+ }: DialogHeaderProps) => (
214
+ <div
215
+ data-slot="dialog-header"
216
+ className={cn(
217
+ leading ? 'flex items-start gap-3 text-left' : 'flex flex-col space-y-1.5 text-center sm:text-left',
218
+ className,
219
+ )}
220
+ {...props}
221
+ >
222
+ {leading ? (
223
+ <span
224
+ data-slot="dialog-header-leading"
225
+ data-tone={leadingTone}
226
+ aria-hidden="true"
227
+ className={cn(
228
+ 'inline-flex size-10 shrink-0 items-center justify-center rounded-full',
229
+ DIALOG_HEADER_TONE_CLASS[leadingTone],
230
+ )}
231
+ >
232
+ {leading}
233
+ </span>
234
+ ) : null}
235
+ {leading ? (
236
+ <div
237
+ data-slot="dialog-header-text"
238
+ className="flex min-w-0 flex-1 flex-col gap-1 text-left"
239
+ >
240
+ {children}
241
+ </div>
242
+ ) : (
243
+ children
244
+ )}
245
+ </div>
246
+ )
247
+ DialogHeader.displayName = 'DialogHeader'
248
+
249
+ export type DialogFooterProps = React.HTMLAttributes<HTMLDivElement> & {
250
+ /** Footer layout. `default` reproduces the original
251
+ * `flex flex-col-reverse gap-2 sm:flex-row sm:justify-end` look.
252
+ * `equal` stretches children flex-1 for 50/50 confirmation footers
253
+ * per Figma `Modal Footer [1.1]` variant 1. */
254
+ layout?: 'default' | 'equal'
255
+ /** Render the canonical `border-t` separator above the button row.
256
+ * Per Figma `Modal Footer [1.1]` every variant ships the rule.
257
+ * @default true */
258
+ bordered?: boolean
259
+ /** Optional left-side slot — typically a "Don't show it again"
260
+ * CheckboxField, a "Remember me" Switch, a left link button, or a
261
+ * step-indicator. Per Figma `Modal Footer [1.1]` variants 2–6.
262
+ * When provided, children stay right-aligned and the leading slot
263
+ * anchors left. Mutually exclusive with `layout="equal"` (the
264
+ * 50/50 split is a confirmation-flow shape that doesn't combine
265
+ * with the leading-content footers per Figma). */
266
+ leading?: React.ReactNode
267
+ }
268
+
269
+ const DialogFooter = ({
270
+ className,
271
+ layout = 'default',
272
+ bordered = true,
273
+ leading,
274
+ children,
275
+ ...props
276
+ }: DialogFooterProps) => {
277
+ if (layout === 'equal') {
278
+ return (
279
+ <div
280
+ data-slot="dialog-footer"
281
+ data-layout="equal"
282
+ data-bordered={bordered ? 'true' : undefined}
70
283
  className={cn(
71
- 'fixed inset-x-0 bottom-0 flex max-h-[90vh] w-full translate-x-0 translate-y-0 flex-col gap-4 overflow-y-auto rounded-t-2xl border-t bg-card p-6 shadow-lg',
72
- elevated ? 'z-modal-elevated' : 'z-modal',
73
- 'sm:inset-auto sm:left-1/2 sm:top-1/2 sm:min-h-0 sm:h-auto sm:w-full sm:max-w-lg sm:max-h-[90vh] sm:-translate-x-1/2 sm:-translate-y-1/2 sm:rounded-xl sm:border',
74
- 'focus-visible:outline-none data-[state=open]:animate-in data-[state=closed]:animate-out',
284
+ // Per Figma: thin border-t separator above the footer in
285
+ // every Modal Footer [1.1] variant. Rule is inset inside
286
+ // the DialogContent's `p-6` padding — true edge-to-edge
287
+ // ran the footer's layout box past the parent's
288
+ // overflow-y-auto scrollbar gutter, pushing the scrollbar
289
+ // outside the rounded card (caught in QuickDeal modal
290
+ // testing). Edge-to-edge polish deferred to a v6 dialog
291
+ // restructure that splits scrolling body from sticky
292
+ // header/footer.
293
+ bordered ? 'border-t border-input pt-4' : '',
294
+ 'flex flex-row gap-2 [&>*]:flex-1',
75
295
  className,
76
296
  )}
77
297
  {...props}
78
298
  >
79
- <DialogClose
80
- data-dialog-close=""
81
- className="absolute right-4 top-4 rounded-sm opacity-70 transition-opacity hover:opacity-100 focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2"
82
- aria-label={t('ui.dialog.close.ariaLabel', 'Close')}
83
- >
84
- <X className="h-4 w-4" />
85
- </DialogClose>
86
299
  {children}
87
- </DialogPrimitive.Content>
88
- </DialogPortal>
89
- )
90
- })
91
- DialogContent.displayName = DialogPrimitive.Content.displayName
300
+ </div>
301
+ )
302
+ }
92
303
 
93
- const DialogHeader = ({ className, ...props }: React.HTMLAttributes<HTMLDivElement>) => (
94
- <div className={cn('flex flex-col space-y-1.5 text-center sm:text-left', className)} {...props} />
95
- )
96
- DialogHeader.displayName = 'DialogHeader'
304
+ if (leading) {
305
+ return (
306
+ <div
307
+ data-slot="dialog-footer"
308
+ data-layout="default"
309
+ data-bordered={bordered ? 'true' : undefined}
310
+ className={cn(
311
+ // Per Figma: thin border-t separator above the footer in
312
+ // every Modal Footer [1.1] variant. Rule is inset inside
313
+ // the DialogContent's `p-6` padding — true edge-to-edge
314
+ // ran the footer's layout box past the parent's
315
+ // overflow-y-auto scrollbar gutter, pushing the scrollbar
316
+ // outside the rounded card (caught in QuickDeal modal
317
+ // testing). Edge-to-edge polish deferred to a v6 dialog
318
+ // restructure that splits scrolling body from sticky
319
+ // header/footer.
320
+ bordered ? 'border-t border-input pt-4' : '',
321
+ 'flex flex-col gap-3 sm:flex-row sm:items-center',
322
+ className,
323
+ )}
324
+ {...props}
325
+ >
326
+ <div
327
+ data-slot="dialog-footer-leading"
328
+ className="inline-flex items-center gap-2 sm:mr-auto"
329
+ >
330
+ {leading}
331
+ </div>
332
+ <div
333
+ data-slot="dialog-footer-trailing"
334
+ className="flex flex-col-reverse gap-2 sm:flex-row sm:items-center"
335
+ >
336
+ {children}
337
+ </div>
338
+ </div>
339
+ )
340
+ }
97
341
 
98
- const DialogFooter = ({ className, ...props }: React.HTMLAttributes<HTMLDivElement>) => (
99
- <div className={cn('flex flex-col-reverse gap-2 sm:flex-row sm:justify-end', className)} {...props} />
100
- )
342
+ return (
343
+ <div
344
+ data-slot="dialog-footer"
345
+ data-layout="default"
346
+ data-bordered={bordered ? 'true' : undefined}
347
+ className={cn(
348
+ // Per Figma: the border-t separator runs edge-to-edge across
349
+ // the modal card (terminates at the rounded corners), NOT
350
+ // inset inside the DialogContent's `p-6` padding. We escape
351
+ // the parent's horizontal padding with `-mx-6` and re-apply
352
+ // `px-6` so the button row keeps its inset position.
353
+ bordered ? '-mx-6 border-t border-input px-6 pt-4' : '',
354
+ 'flex flex-col-reverse gap-2 sm:flex-row sm:justify-end',
355
+ className,
356
+ )}
357
+ {...props}
358
+ >
359
+ {children}
360
+ </div>
361
+ )
362
+ }
101
363
  DialogFooter.displayName = 'DialogFooter'
102
364
 
103
365
  const DialogTitle = React.forwardRef<
@@ -106,6 +368,7 @@ const DialogTitle = React.forwardRef<
106
368
  >(({ className, ...props }, ref) => (
107
369
  <DialogPrimitive.Title
108
370
  ref={ref}
371
+ data-slot="dialog-title"
109
372
  className={cn('text-lg font-semibold leading-none tracking-tight', className)}
110
373
  {...props}
111
374
  />
@@ -118,6 +381,7 @@ const DialogDescription = React.forwardRef<
118
381
  >(({ className, ...props }, ref) => (
119
382
  <DialogPrimitive.Description
120
383
  ref={ref}
384
+ data-slot="dialog-description"
121
385
  className={cn('text-sm text-muted-foreground', className)}
122
386
  {...props}
123
387
  />