@flamingo-stack/openframe-frontend-core 0.0.543 → 0.0.544-1804.4776.1

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 (104) hide show
  1. package/dist/{chunk-WPIFOMFD.cjs → chunk-3DERWWWX.cjs} +37 -37
  2. package/dist/{chunk-WPIFOMFD.cjs.map → chunk-3DERWWWX.cjs.map} +1 -1
  3. package/dist/{chunk-7G734VXA.js → chunk-3MMSQ7SC.js} +2 -2
  4. package/dist/{chunk-RGI45NCV.cjs → chunk-3UCQWXA3.cjs} +26 -26
  5. package/dist/{chunk-RGI45NCV.cjs.map → chunk-3UCQWXA3.cjs.map} +1 -1
  6. package/dist/{chunk-KFRFOOLI.cjs → chunk-5CWG5JAO.cjs} +4 -4
  7. package/dist/{chunk-KFRFOOLI.cjs.map → chunk-5CWG5JAO.cjs.map} +1 -1
  8. package/dist/{chunk-FOOQ3FN3.js → chunk-5NZLZTUD.js} +6 -6
  9. package/dist/{chunk-3ROT5PX2.cjs → chunk-5W2OUL2H.cjs} +9 -9
  10. package/dist/{chunk-3ROT5PX2.cjs.map → chunk-5W2OUL2H.cjs.map} +1 -1
  11. package/dist/{chunk-NMMBXECI.cjs → chunk-6MOD65VQ.cjs} +87 -87
  12. package/dist/{chunk-NMMBXECI.cjs.map → chunk-6MOD65VQ.cjs.map} +1 -1
  13. package/dist/{chunk-IWGK2OSV.cjs → chunk-AFQZIKIC.cjs} +27 -27
  14. package/dist/{chunk-IWGK2OSV.cjs.map → chunk-AFQZIKIC.cjs.map} +1 -1
  15. package/dist/{chunk-YXYYPTLR.cjs → chunk-CHQOAONB.cjs} +5 -5
  16. package/dist/{chunk-YXYYPTLR.cjs.map → chunk-CHQOAONB.cjs.map} +1 -1
  17. package/dist/{chunk-WCXM43JA.js → chunk-CHZ57UPO.js} +4 -4
  18. package/dist/{chunk-R53YBUQ3.js → chunk-CJ4KV7D2.js} +2 -2
  19. package/dist/{chunk-D7GX56ZJ.cjs → chunk-CKU7C2NQ.cjs} +11 -11
  20. package/dist/{chunk-D7GX56ZJ.cjs.map → chunk-CKU7C2NQ.cjs.map} +1 -1
  21. package/dist/{chunk-GBPWUSVD.js → chunk-DCQN7QEU.js} +5 -5
  22. package/dist/{chunk-2BSDGGMZ.js → chunk-EOZBJY22.js} +2 -2
  23. package/dist/{chunk-VRS3EJNW.cjs → chunk-ERRD2KX7.cjs} +61 -61
  24. package/dist/{chunk-VRS3EJNW.cjs.map → chunk-ERRD2KX7.cjs.map} +1 -1
  25. package/dist/{chunk-TUPAJW3I.js → chunk-HDDPE36K.js} +2 -2
  26. package/dist/{chunk-ERUCYF54.js → chunk-J6AT6PCW.js} +2 -2
  27. package/dist/{chunk-6J7TWGNV.js → chunk-K3GU3GXP.js} +2 -2
  28. package/dist/{chunk-SNFFVRXR.js → chunk-M4H6XBEL.js} +40 -20
  29. package/dist/chunk-M4H6XBEL.js.map +1 -0
  30. package/dist/{chunk-ZFRSWZGZ.cjs → chunk-MEJDX5UP.cjs} +3 -3
  31. package/dist/{chunk-ZFRSWZGZ.cjs.map → chunk-MEJDX5UP.cjs.map} +1 -1
  32. package/dist/{chunk-AO7OPQKS.js → chunk-OYNCKOLU.js} +2 -2
  33. package/dist/{chunk-RWZE5FC5.js → chunk-Q6I6XGMX.js} +2 -2
  34. package/dist/{chunk-PQ6FUNPA.cjs → chunk-QZLWVIT4.cjs} +14 -14
  35. package/dist/{chunk-PQ6FUNPA.cjs.map → chunk-QZLWVIT4.cjs.map} +1 -1
  36. package/dist/{chunk-T65SKWRT.js → chunk-RCEVUZEI.js} +2 -2
  37. package/dist/{chunk-L46PXCHD.cjs → chunk-SDXCNTEC.cjs} +7 -7
  38. package/dist/{chunk-L46PXCHD.cjs.map → chunk-SDXCNTEC.cjs.map} +1 -1
  39. package/dist/{chunk-Z34YRIM7.cjs → chunk-TW6NP2IH.cjs} +40 -20
  40. package/dist/chunk-TW6NP2IH.cjs.map +1 -0
  41. package/dist/{chunk-EUM4XBDN.cjs → chunk-YMXJJ4MY.cjs} +31 -31
  42. package/dist/{chunk-EUM4XBDN.cjs.map → chunk-YMXJJ4MY.cjs.map} +1 -1
  43. package/dist/{chunk-SHLL6E5T.js → chunk-YVLIC36O.js} +4 -4
  44. package/dist/components/case-studies/index.cjs +8 -8
  45. package/dist/components/case-studies/index.js +2 -2
  46. package/dist/components/chat/index.cjs +2 -2
  47. package/dist/components/chat/index.js +1 -1
  48. package/dist/components/contact/index.cjs +3 -3
  49. package/dist/components/contact/index.js +2 -2
  50. package/dist/components/docs/index.cjs +5 -5
  51. package/dist/components/docs/index.js +4 -4
  52. package/dist/components/embeds/index.cjs +3 -3
  53. package/dist/components/embeds/index.js +2 -2
  54. package/dist/components/faq/index.cjs +3 -3
  55. package/dist/components/faq/index.js +2 -2
  56. package/dist/components/features/ai-enrich/AIEnrichSection.d.ts.map +1 -1
  57. package/dist/components/features/index.cjs +2 -2
  58. package/dist/components/features/index.js +1 -1
  59. package/dist/components/help-center-pages/index.cjs +22 -22
  60. package/dist/components/help-center-pages/index.js +13 -13
  61. package/dist/components/index.cjs +132 -138
  62. package/dist/components/index.cjs.map +1 -1
  63. package/dist/components/index.js +13 -19
  64. package/dist/components/index.js.map +1 -1
  65. package/dist/components/meeting-scheduler/index.cjs +34 -34
  66. package/dist/components/meeting-scheduler/index.js +3 -3
  67. package/dist/components/navigation/index.cjs +2 -2
  68. package/dist/components/navigation/index.js +1 -1
  69. package/dist/components/onboarding-guides/index.cjs +5 -5
  70. package/dist/components/onboarding-guides/index.js +4 -4
  71. package/dist/components/related-content/index.cjs +3 -3
  72. package/dist/components/related-content/index.js +2 -2
  73. package/dist/components/tickets/index.cjs +6 -6
  74. package/dist/components/tickets/index.js +5 -5
  75. package/dist/components/ui/index.cjs +2 -8
  76. package/dist/components/ui/index.cjs.map +1 -1
  77. package/dist/components/ui/index.js +3 -9
  78. package/dist/components/ui/modal-v2.d.ts +27 -1
  79. package/dist/components/ui/modal-v2.d.ts.map +1 -1
  80. package/dist/components/ui/modal.d.ts +6 -26
  81. package/dist/components/ui/modal.d.ts.map +1 -1
  82. package/dist/index.cjs +2 -8
  83. package/dist/index.cjs.map +1 -1
  84. package/dist/index.js +3 -9
  85. package/package.json +1 -1
  86. package/src/components/features/ai-enrich/AIEnrichSection.tsx +1 -0
  87. package/src/components/ui/.modal-v2.md +21 -3
  88. package/src/components/ui/modal-v2.tsx +76 -6
  89. package/src/components/ui/modal.tsx +8 -31
  90. package/dist/chunk-SNFFVRXR.js.map +0 -1
  91. package/dist/chunk-Z34YRIM7.cjs.map +0 -1
  92. /package/dist/{chunk-7G734VXA.js.map → chunk-3MMSQ7SC.js.map} +0 -0
  93. /package/dist/{chunk-FOOQ3FN3.js.map → chunk-5NZLZTUD.js.map} +0 -0
  94. /package/dist/{chunk-WCXM43JA.js.map → chunk-CHZ57UPO.js.map} +0 -0
  95. /package/dist/{chunk-R53YBUQ3.js.map → chunk-CJ4KV7D2.js.map} +0 -0
  96. /package/dist/{chunk-GBPWUSVD.js.map → chunk-DCQN7QEU.js.map} +0 -0
  97. /package/dist/{chunk-2BSDGGMZ.js.map → chunk-EOZBJY22.js.map} +0 -0
  98. /package/dist/{chunk-TUPAJW3I.js.map → chunk-HDDPE36K.js.map} +0 -0
  99. /package/dist/{chunk-ERUCYF54.js.map → chunk-J6AT6PCW.js.map} +0 -0
  100. /package/dist/{chunk-6J7TWGNV.js.map → chunk-K3GU3GXP.js.map} +0 -0
  101. /package/dist/{chunk-AO7OPQKS.js.map → chunk-OYNCKOLU.js.map} +0 -0
  102. /package/dist/{chunk-RWZE5FC5.js.map → chunk-Q6I6XGMX.js.map} +0 -0
  103. /package/dist/{chunk-T65SKWRT.js.map → chunk-RCEVUZEI.js.map} +0 -0
  104. /package/dist/{chunk-SHLL6E5T.js.map → chunk-YVLIC36O.js.map} +0 -0
@@ -5,12 +5,27 @@ Accessible, animated modal dialog component with compound sub-components for bui
5
5
 
6
6
  | Export | Description |
7
7
  |---|---|
8
- | `ModalV2` | Root modal container managing open/close state, backdrop, animations, scroll lock, and Escape key handling |
8
+ | `ModalV2` | Root modal container managing open/close state, backdrop, animations, scroll lock, focus management, and Escape key handling. `size?: ModalV2Size` selects the panel width |
9
9
  | `ModalV2Header` | Header row with auto-injected close button (desktop only) via `ModalContext` |
10
10
  | `ModalV2Title` | Semantic `<h2>` styled with design system text tokens |
11
11
  | `ModalV2Content` | Scrollable body area with `overflow-y-auto` and flex-grow |
12
+ | `ModalV2TwoColumn` | Two-column editor body — use INSTEAD OF `ModalV2Content` on a `size="wide"` modal. Props `{ left, right, className? }` |
12
13
  | `ModalV2Footer` | Horizontal action row for buttons or other controls |
13
14
 
15
+ ## Sizes
16
+
17
+ `ModalV2Size` = `'default' | 'medium' | 'wide'` (default `'default'`). Every arm keeps a
18
+ `calc(100vw-2rem)` arm so content can never stretch the panel past the viewport on narrow screens.
19
+
20
+ | Size | Width | Use |
21
+ |---|---|---|
22
+ | `default` | `28rem` | Confirms and short prompts |
23
+ | `medium` | `42rem` | Single-column forms |
24
+ | `wide` | `1400px` | Two-column editors and master-detail panes. Also FIXES the desktop height (`md:h-[min(90dvh,100%-2rem)]`) so the panel doesn't jump as an entity hydrates in |
25
+
26
+ Prefer the `size` prop over a call-site `max-w-*`. The size class is emitted before `className`,
27
+ so an override still wins where one is genuinely needed.
28
+
14
29
  **Internal:**
15
30
  - `ModalContext` — React context passing `onClose` to descendants (used by `ModalV2Header`)
16
31
  - `ANIMATION_DURATION` — `200ms` constant kept in sync with Tailwind `duration-200` utilities; controls unmount delay so exit animations complete before DOM removal
@@ -54,9 +69,12 @@ function MyDialog() {
54
69
 
55
70
  ## Behavior Notes
56
71
 
57
- - **Scroll lock** — uses `@react-aria/overlays` `usePreventScroll` (ref-counted, restores prior `overflow` styles)
58
- - **Escape key** — document-level listener active only while `isOpen` is `true`
72
+ - **Scroll lock** — `react-remove-scroll` (the same library Radix primitives use internally, so it composes with the lock a Select opened inside the modal adds on top). Rendered with `forwardProps` so no extra wrapper `<div>` lands in a flex/grid parent's flow
73
+ - **Escape key** — document-level listener, but top-of-stack only: with stacked modals (a confirm above a form) one Escape closes just the top one, and a nested Radix layer's `preventDefault`ed Escape closes only that layer
74
+ - **Focus** — focus moves into the panel on open, is CONTAINED there while it is topmost (with bounded re-asserts for focus dropped by node removal), Tab cycles inside it, and focus returns to the opener on close. Portaled Radix layers (`[data-radix-popper-content-wrapper]`, `[role=listbox]`, `[role=menu]`) are exempt
59
75
  - **Backdrop click** — calls `onClose`
76
+ - **Two-column scroll model** — below `lg` there is one column and the outer region scrolls (identical to a single-column modal on a phone); from `lg` up the outer region is `overflow-hidden` and each column scrolls independently
77
+ - **Software keyboard** — the wrapper pads by `--of-keyboard-inset` rather than shrinking, since neither mobile shell shrinks the layout viewport when the IME opens
60
78
  - **Animations** — slide-up on mobile, zoom on desktop; `fill-mode-forwards` prevents opacity flash between animation end and unmount
61
79
  - **Close button** — rendered inside `ModalV2Header`, visible on `md:` breakpoint and above only
62
80
 
@@ -12,11 +12,28 @@ const ANIMATION_DURATION = 200
12
12
 
13
13
  const ModalContext = React.createContext<{ onClose?: () => void }>({})
14
14
 
15
+ /**
16
+ * Panel width, as a named variant rather than a per-call-site `max-w-*`.
17
+ * `medium` is the single-column form width; `wide` is the two-column editor
18
+ * width and pairs with `ModalV2TwoColumn`.
19
+ *
20
+ * Every arm keeps the `calc(100vw-2rem)` arm so content can never stretch the
21
+ * panel past the viewport (minus the `mx-4` margins) on narrow screens.
22
+ */
23
+ export type ModalV2Size = "default" | "medium" | "wide"
24
+
25
+ const MODAL_V2_SIZE_CLASSES: Record<ModalV2Size, string> = {
26
+ default: "max-w-[min(28rem,calc(100vw-2rem))]",
27
+ medium: "max-w-[min(42rem,calc(100vw-2rem))]",
28
+ wide: "max-w-[min(1400px,calc(100vw-2rem))]",
29
+ }
30
+
15
31
  interface ModalProps {
16
32
  isOpen: boolean
17
33
  onClose: () => void
18
34
  children: React.ReactNode
19
35
  className?: string
36
+ size?: ModalV2Size
20
37
  }
21
38
 
22
39
  interface ModalContentProps {
@@ -39,6 +56,12 @@ interface ModalFooterProps {
39
56
  className?: string
40
57
  }
41
58
 
59
+ interface ModalTwoColumnProps {
60
+ left: React.ReactNode
61
+ right: React.ReactNode
62
+ className?: string
63
+ }
64
+
42
65
  // Topmost-modal stack: with stacked modals (confirm above a form) only the
43
66
  // TOP one may contain focus, or they fight each other.
44
67
  const modalStack: symbol[] = []
@@ -58,7 +81,7 @@ const isInPortaledLayer = (node: Node | null): boolean =>
58
81
  ) !== null
59
82
 
60
83
  const Modal = React.forwardRef<HTMLDivElement, ModalProps>(
61
- ({ isOpen, onClose, children, className }, ref) => {
84
+ ({ isOpen, onClose, children, className, size = "default" }, ref) => {
62
85
  // Keep the modal mounted while the exit animation plays.
63
86
  const [isMounted, setIsMounted] = useState(isOpen)
64
87
  const panelRef = React.useRef<HTMLDivElement | null>(null)
@@ -247,11 +270,17 @@ const Modal = React.forwardRef<HTMLDivElement, ModalProps>(
247
270
  tabIndex={-1}
248
271
  data-state={state}
249
272
  className={cn(
250
- // min() keeps the desktop cap at 28rem while never letting content
251
- // stretch the panel past the viewport (minus the mx-4 margins) on
252
- // narrow screens. A single base utility (not md:max-w-md) so consumer
273
+ // A single base utility per size (not md:max-w-*) so consumer
253
274
  // max-w-* overrides via className still win at every breakpoint.
254
- "relative z-10 w-full min-w-0 max-w-[min(28rem,calc(100vw-2rem))] flex flex-col",
275
+ "relative z-10 w-full min-w-0 flex flex-col",
276
+ // The panel is a focus TARGET (tabIndex -1), not a control: focus
277
+ // moves here on open so the dialog owns the keyboard, and the UA
278
+ // then paints its default ring around the whole modal. Opening by
279
+ // click hides it via :focus-visible heuristics, but a modal opened
280
+ // from a URL on page load has no preceding pointer event, so the
281
+ // ring showed on every refresh. Fields inside keep their own rings.
282
+ "outline-none",
283
+ MODAL_V2_SIZE_CLASSES[size],
255
284
  "mx-4 mb-4 md:mb-0",
256
285
  // dvh, not vh: vh ignores a mobile browser's retracting URL bar, so
257
286
  // 90vh already overflowed behind Safari's toolbar. The `100%-2rem`
@@ -261,6 +290,11 @@ const Modal = React.forwardRef<HTMLDivElement, ModalProps>(
261
290
  // stay pinned, ModalV2Content scrolls. min() picks 90dvh on any
262
291
  // viewport over 320px tall, so desktop is untouched.
263
292
  "max-h-[min(90dvh,100%-2rem)]",
293
+ // `wide` also FIXES the desktop height rather than only capping it:
294
+ // its columns scroll independently, and a height that tracks
295
+ // content makes the panel jump as an entity hydrates in. Mobile
296
+ // keeps the bottom-sheet's content-sized height.
297
+ size === "wide" && "md:h-[min(90dvh,100%-2rem)]",
264
298
  "bg-ods-bg md:bg-ods-card",
265
299
  "border border-ods-border rounded-md shadow-xl",
266
300
  "p-[var(--spacing-system-xl)] gap-[var(--spacing-system-l)]",
@@ -297,6 +331,41 @@ const ModalContent = React.forwardRef<HTMLDivElement, ModalContentProps>(
297
331
  )
298
332
  ModalContent.displayName = "ModalV2Content"
299
333
 
334
+ /**
335
+ * The two-column editor body. Use INSTEAD OF `ModalV2Content` (not inside it)
336
+ * on a `size="wide"` modal — it owns the same `flex-1 min-h-0` slot.
337
+ *
338
+ * Scroll model, which is the whole reason this is a component and not a pair
339
+ * of copy-pasted class strings: below `lg` there is ONE column and the outer
340
+ * region scrolls, so a phone behaves exactly like every single-column modal.
341
+ * From `lg` up the outer region is `overflow-hidden` and each column scrolls
342
+ * independently, so a long left column never drags the right one out of view.
343
+ */
344
+ const ModalTwoColumn = React.forwardRef<HTMLDivElement, ModalTwoColumnProps>(
345
+ ({ left, right, className }, ref) => (
346
+ <div
347
+ ref={ref}
348
+ className={cn("flex-1 min-h-0 overflow-y-auto lg:overflow-hidden", className)}
349
+ >
350
+ {/* `lg:grid-rows-[minmax(0,1fr)]` is what makes the columns scroll: an
351
+ implicit `auto` row sizes to the TALLER column, so the columns had no
352
+ bounded height to scroll inside and the outer `overflow-hidden`
353
+ silently clipped them instead. minmax(0,…) also beats the default
354
+ `min-height:auto` on the row, which would otherwise refuse to shrink
355
+ below content height. */}
356
+ <div className="grid grid-cols-1 gap-[var(--spacing-system-xl)] lg:h-full lg:min-h-0 lg:grid-cols-2 lg:grid-rows-[minmax(0,1fr)]">
357
+ <div className="min-h-0 space-y-[var(--spacing-system-lf)] lg:overflow-y-auto lg:pr-[var(--spacing-system-sf)]">
358
+ {left}
359
+ </div>
360
+ <div className="min-h-0 space-y-[var(--spacing-system-lf)] lg:overflow-y-auto lg:pr-[var(--spacing-system-sf)]">
361
+ {right}
362
+ </div>
363
+ </div>
364
+ </div>
365
+ )
366
+ )
367
+ ModalTwoColumn.displayName = "ModalV2TwoColumn"
368
+
300
369
  const ModalHeader = React.forwardRef<HTMLDivElement, ModalHeaderProps>(
301
370
  ({ children, className }, ref) => {
302
371
  const { onClose } = React.useContext(ModalContext)
@@ -352,5 +421,6 @@ export {
352
421
  ModalContent as ModalV2Content,
353
422
  ModalFooter as ModalV2Footer,
354
423
  ModalHeader as ModalV2Header,
355
- ModalTitle as ModalV2Title
424
+ ModalTitle as ModalV2Title,
425
+ ModalTwoColumn as ModalV2TwoColumn
356
426
  }
@@ -6,40 +6,18 @@ import { usePreventScroll } from "@react-aria/overlays"
6
6
  import { cn } from "../../utils/cn"
7
7
 
8
8
  /**
9
- * Modal width presets — the SSOT for admin modal sizing. Pick a preset via
10
- * `size` instead of stacking `max-w-*` className overrides per call site.
11
- * - default: compact dialogs (confirmations, small forms)
12
- * - wide: two-column editor modals (interview / case study / release …)
9
+ * Sizing and the two-column editor layout moved to `ModalV2` (`size` prop +
10
+ * `ModalV2TwoColumn`), which is where the focus trap, Escape stacking and
11
+ * keyboard-inset handling already live. The class-string constants this file
12
+ * used to export were copied per call site and drifted; a component owns the
13
+ * scroll model instead. What remains here is the compact legacy dialog used by
14
+ * the confirm modals that have not moved yet.
13
15
  */
14
- export const MODAL_SIZE_CLASSES = {
15
- default: 'max-w-md',
16
- wide: 'max-w-[1400px]',
17
- } as const
18
- export type ModalSize = keyof typeof MODAL_SIZE_CLASSES
19
-
20
- /**
21
- * Two-column editor-modal layout SSOT (body wrapper → grid → column).
22
- * Every dual-column admin modal composes these three, so the shell can't
23
- * drift per entity:
24
- *
25
- * <div className={TWO_COLUMN_MODAL_BODY_CLASS}>
26
- * <div className={TWO_COLUMN_MODAL_GRID_CLASS}>
27
- * <div className={TWO_COLUMN_MODAL_COLUMN_CLASS}>…left…</div>
28
- * <div className={TWO_COLUMN_MODAL_COLUMN_CLASS}>…right…</div>
29
- * </div>
30
- * </div>
31
- */
32
- export const TWO_COLUMN_MODAL_BODY_CLASS = 'px-6 py-4 flex-1 min-h-0 flex flex-col max-h-[70vh]'
33
- export const TWO_COLUMN_MODAL_GRID_CLASS = 'grid grid-cols-1 lg:grid-cols-2 gap-8 flex-1 min-h-0'
34
- export const TWO_COLUMN_MODAL_COLUMN_CLASS = 'space-y-6 overflow-y-auto pr-4'
35
-
36
16
  interface ModalProps {
37
17
  isOpen: boolean
38
18
  onClose: () => void
39
19
  children: React.ReactNode
40
20
  className?: string
41
- /** Width preset from MODAL_SIZE_CLASSES. Default 'default' (max-w-md). */
42
- size?: ModalSize
43
21
  }
44
22
 
45
23
  interface ModalContentProps {
@@ -64,7 +42,7 @@ interface ModalFooterProps {
64
42
 
65
43
  /** @deprecated Use ModalV2 from './modal-v2' instead. */
66
44
  const Modal = React.forwardRef<HTMLDivElement, ModalProps>(
67
- ({ isOpen, onClose, children, className, size = 'default' }, ref) => {
45
+ ({ isOpen, onClose, children, className }, ref) => {
68
46
  // Shared ref-counted scroll lock (react-aria) — restores prior styles on
69
47
  // release instead of clobbering to 'unset'.
70
48
  usePreventScroll({ isDisabled: !isOpen })
@@ -95,8 +73,7 @@ const Modal = React.forwardRef<HTMLDivElement, ModalProps>(
95
73
  <div
96
74
  ref={ref}
97
75
  className={cn(
98
- "relative z-10 w-full mx-4 max-h-[90vh] flex flex-col overflow-hidden bg-ods-card border border-ods-border rounded-lg shadow-xl",
99
- MODAL_SIZE_CLASSES[size],
76
+ "relative z-10 w-full mx-4 max-w-md max-h-[90vh] flex flex-col overflow-hidden bg-ods-card border border-ods-border rounded-lg shadow-xl",
100
77
  className
101
78
  )}
102
79
  role="dialog"